1.设置响应行
格式:HTTP/1.1 200 ok
设置状态码:setStatus(int sc):传入一个int型的状态码就把状态码设置了
2.设置响应头:setHeader(String name,String value)
响应行+响应头实现重定向
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 旗木五五开 * @create 2020-03-06 9:59 * 重定向 */ @WebServlet("/responseDemo1") public class ResponseDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("1被访问"); // 访问responseDemo1会自动跳转到responseDemo2 // 1.设置状态码为302 response.setStatus(302); // 2.设置响应头:头名称:location,值:资源路径 response.setHeader("location","/day15/responseDemo2"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 旗木五五开 * @create 2020-03-06 10:01 */ @WebServlet("/responseDemo2") public class ResponseDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("2被访问"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
回车确定后1变2
控制台输出
简单的重定向response.sendRedirect
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 旗木五五开 * @create 2020-03-06 9:59 * 重定向 */ @WebServlet("/responseDemo1") public class ResponseDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("1被访问"); response.sendRedirect("/day15/responseDemo2"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
重定向的特点:redirect
①地址栏发生变化
②重定向可以访问其他 站点(服务器)的资源
③重定向是两次请求:不能使用request域来共享数据
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 旗木五五开 * @create 2020-03-06 9:59 * 重定向 */ @WebServlet("/responseDemo1") public class ResponseDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("1被访问"); request.setAttribute("sm","request"); response.sendRedirect("/day15/responseDemo2"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 旗木五五开 * @create 2020-03-06 10:01 */ @WebServlet("/responseDemo2") public class ResponseDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("2被访问"); Object sm = request.getAttribute("sm"); System.out.println(sm); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
转发的特点:forward
①转发地址栏路径不变
②转发只能访问当前服务器下的资源
③转发是一次请求:可以使用request域来共享数据
路径写法
相对路径:通过路径不可以确定唯一资源。
规则:不以/开头的,以 . 开头路径。不写默认./当前路径 ../后退一级的目录。jsp页面不推荐使用相对路径
如:./index.html index.html
规则:找到当前资源 和目标资源的 相对位置关系
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>找到当前资源 和目标资源的 相对位置关系</h1> <p> 当前资源:localtion http://localhost/day15/localtion.html </p> <p> 目标资源:requestDemo2 http://localhost/day15/responseDemo2 </p> <a href="./responseDemo2"> responseDemo2 </a> <a href="responseDemo2"> responseDemo </a> </body> </html>
绝对路径:通过路径可以确定唯一资源。以/开头的
如:http://localhost/day15/responseDemo2或者 /day15/responseDemo2
规则:判断定义的路径是给谁用的。判断请求从哪发出。使用动态虚拟目录
给客户端浏览器使用:需要加虚拟目录(项目的访问路径)。重定向、<A>、<form>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>绝对路径</h1> <a href="/day15/responseDemo2"> responseDemo2 </a> </body> </html>
给服务器使用:不需要加虚拟目录。转发
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 旗木五五开 * @create 2020-03-07 17:32 */ @WebServlet("/responseDemo3") public class ResponseDemo3 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/responseDemo2").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
动态的获取虚拟目录request.getContextPath()
html不行,jsp可以
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 旗木五五开 * @create 2020-03-06 9:59 * 重定向 */ @WebServlet("/responseDemo1") public class ResponseDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 调用request请求头方法 String contextPath = request.getContextPath(); // 拼接 虚拟目录 资源路径 response.sendRedirect(contextPath+"/responseDemo2"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
3.设置响应体:通过流的方式
使用步骤:
1.获取输出流
字符输出流:只能输出字符
PrintWiter getWiter():打印流
有两种输出数据的方式
write方法,
print方法:自动刷新(不刷新把数据写出缓冲区的效果)
但是这个方法是response获取的,上面两个方法都可以自动刷新。response在一次响应完成之后会自动销毁,获取的流也会被自动关闭。
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @author 旗木五五开 * @create 2020-03-07 19:03 */ @WebServlet("/responseDemo4") public class ResponseDemo4 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.获取字符输出流 PrintWriter pw = response.getWriter(); // 2.输出数据 pw.write("<h1>hello response</h1>"); /* 数据会被浏览器解析展示到页面上 */ } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
解决中文乱码:乱码的原因:编码解码用的字符集不一致
浏览器打开默认的字符集和当前操作系统的语言环境有关系,现在用的是中文的Windows操作系统。打开浏览器默认的字符集(编码表)就是GBK(国标扩展码)或GB2312(国标码)都是中文的码表。
由此可知服务器用的不是GB2312
服务器用的是啥呢
解决方法:获取去流对象之前,设置默认编码
text/html;charset=utf-8 文本数据/值类型HTML;字符设置=utf-8
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @author 旗木五五开 * @create 2020-03-07 19:03 */ @WebServlet("/responseDemo4") public class ResponseDemo4 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.获取流对象之前,设置默认编码 /*光写这行代码不够,如果浏览器用的不是GBK还是会乱码。需要2*/ response.setCharacterEncoding("GBK"); // 2.设置响应体,告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码 /*这一行代码可以代替1,一行代码干两件事*/ response.setHeader("content-type","text/html;charset=utf-8");
// 2的简单的形式,设置编码-----------------用这个 response.setContentType("text/html;charset=utf-8"); // 获取字符输出流 PrintWriter pw = response.getWriter(); // 输出数据 pw.write("<h1>hello response</h1>"); /* 数据会被浏览器解析展示到页面上 */ pw.write("你好 response"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
字节输出流:能输出任何数据
ServletOutputStream getOutputStream():当做OutputStream来使用
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 旗木五五开 * @create 2020-03-07 21:14 */ @WebServlet("/responseDemo5") public class ResponseDemo5 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 解决乱码同上 response.setContentType("text/html;charset=utf-8"); // 1.获取直接输出流 ServletOutputStream sos = response.getOutputStream(); // 2.输出数据 /*字节流输出字符数据 getBytes()获取字节数组 括号内可以设置编码*/ sos.write("hello 你好".getBytes("utf-8")); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
2.使用输出流,将数据输出到客户端浏览器
验证码
本质:图片
目的:防止恶意表单注册
图片是怎么来的?
第一种:在文件夹中放很多图片随机显示(第一种,一万张图片,通过穷举的方式能把一万张图片弄完)
第二种:在程序中动态的生成,一张图片,输出到页面上(随机生成,要列举出来所有的情况基本不可能)程序都采用的这种方式
package cn.itcast.web.servlet; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; /** * @author 旗木五五开 * @create 2020-03-07 21:37 */ @WebServlet("/checkCodServlet") public class CheckCodServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int width = 100; int height = 50; // 1.创建一个对象,在内存中代表一张图片。 /*参数宽、高、图片类型*/ BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); // 2.美化图片 // 2.1填充背景色 Graphics g = image.getGraphics();//画笔对象 g.setColor(Color.PINK);//设置颜色,大小写没有区别 g.fillRect(0, 0, width, height);//填充 /*x和y在图片中是左上角那个点,从左到右,从上到下*/ // 2.2给图片画一个边框 g.setColor(Color.BLUE);//设置颜色,大小写没有区别 /*不减1,右边和下边就会画到外面,无法显示*/ g.drawRect(0, 0, width - 1, height - 1); // 验证码内容 String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; // 随机角标 Random ran = new Random(); // 2.3写验证码 for (int i = 1; i <= 4; i++) { // 最大值 int index = ran.nextInt(str.length()); // 获取字符 char ch = str.charAt(index); g.drawString(ch + "", width / 5 * i, height / 2); } // 2.4画干扰线 g.setColor(Color.GREEN);//颜色 // 画线 for (int i = 0; i < 10; i++) { // 随机生成坐标点 int x1 = ran.nextInt(width); int y1 = ran.nextInt(width); int x2 = ran.nextInt(width); int y2 = ran.nextInt(width); // 线段 g.drawLine(x1,y1,x2,y2); } // 3.将图片输出到页面展示。因为现在图片在内存中要输出它需要一个对象 /*将内存中的一张图片写到页面,任意的流中。参数图片对象,图片后缀名,OutputStream*/ /*后缀名是为了输出到对应的文件使用的,页面上无所谓*/ ImageIO.write(image, "jpg", response.getOutputStream()); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
开发中使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script> /* * 分析: * 点击超链接或者图片,切换图片 * 1.给超链接和图片绑定单机事件 * 2.重新设置图片的src属性值 * 页面加载完后 * */ window.onload = function () { // 1.给图片绑定单机事件 var img = document.getElementById("checkCode"); // 2.绑定单机事件 img.onclick=function () { /* * 因为两次请求图片路径一样会被浏览器当做缓存 * */ //所以+时间戳 var date=new Date().getTime(); img.src="/day15/checkCodServlet?"+date; } // 给超链接绑定单机事件 var t=document.getElementById("change"); t.onclick=function () { /* * 因为两次请求图片路径一样会被浏览器当做缓存 * */ //所以+时间戳 var date=new Date().getTime(); img.src="/day15/checkCodServlet?"+date; } } </script> </head> <body> <img id="checkCode" src="/day15/checkCodServlet" alt=""> <a id="change"href="javascript:void(0)"> 看不清换一张</a> </body> </html>