summarize
在创建Servlet时,会覆盖service方法或doGet()/doPost(),它俩都是 HTTPServletresponse这些方法都有俩参数,一个是请求request,一个是响应response,HttpServletResponse是ServletResponset的子接口,
浏览器发出http请求,会直接传给Tomcat,Tomcat将请求的信息封装成request,和response 传给web,这时的response是空的,web调用write方法将内容存到缓冲区,此时,Tomcat从response里获取设置的内容组装成一个http响应(行、头、体)回写给客户端
响应行只能设置状态码
重定向特点:请求服务器两次,地址栏变化
location:
HttpServletResponse
response运行流程图
通过response设置响应行
设置响应行的状态码: setStatus(int sc)
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class HeadServlet */ public class HeadServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public HeadServlet() { super(); } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置响应头中的状态码 response.setStatus(404); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
重定向:1.状态码:302 + 2 .响应头:Location
其实请求了两次 但客户端只做了一次请求
原理图
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /*// 设置响应状态码 response.setStatus(302); // 设置响应头中的Location response.setHeader("Location","/WEB05/Servlet02");*/ // 重定向 sendRedirect方法 下面这一句话就等于上面两句话 response.sendRedirect("/WEB05/Servlet02"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ---------------------------------------------- package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet02 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().write("Servlet02"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
通过response设置响应头
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class RefreshServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置定时刷新的头 response.setHeader("Refresh","5;url=https://www.baidu.com"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
用JSP写一个重定向
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript"> window.onload=function(){ //获取span元素 var second=document.getElementById("second"); //定义秒数 var time=5; //设置定时器 var timer=setInterval(function(){ //获得元素里面的文本节点 second.innerHTML=time; time--; if(time<0){ clearInterval(timer); location.href="http://www.baidu.com"; } },1000); } </script> </head> <body> 恭喜你,注册成功! <span id="second" style="color:red">5</span> 秒后跳转,如没跳转,请点击 <a href="http://www.baidu.com">这里</a> </body> </html>
通过response设置响应体
(1)响应体设置文本
获得字符流,通过字符流的write(
String s)
方法可以将字符串设置到response 缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端
package com.oracle.demo01; //设置码表让页面显示中文 import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class BodyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /*// 设置缓冲区编码表 response.setCharacterEncoding("UTF-8"); // 设置客户端浏览器使用的码表 response.setHeader("Content-Type","text/html;charset=utf-8");*/ // 解决响应的中文乱码问题 用一个犯法就可以 代替上面两句话 response.setContentType("text/html;charset=utf-8"); response.getWriter().write("中国"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
创建一个download.jsp (能解析的解析,不能解析的下载功能)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="/WEB05/download/a.png">a.png</a>
<a href="/WEB05/download/a.txt">a.txt</a>
<a href="/WEB05/download/a.zip">a.zip</a>
</body>
</html>
(1)响应头设置字节
ServletOutputStream
getOutputStream()
获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字 节,在由Tomcat服务器将字节内容组成Http响应返回给浏览器。
2.案例-完成文件下载
文件下载的实质就是文件拷贝,将文件从服务器端拷贝到浏览器端。所以文件下载需 要IO技术将服务器端的文件使用InputStream读取到,在使用 ServletOutputStream写到response缓冲区中
代码如下:
上述代码可以将图片从服务器端传输到浏览器,但浏览器直接解析图片显示在页面上, 而不是提供下载,需要设置两个响应头,告知浏览器文件的类型和文件的打开方 式。
1)告知浏览器文件的类型:response.setContentType(文件的MIME类型);
2)告示浏览器文件打开方式是下载:response.setHeader("Content-Disposition","attachment;filename=文件名称");
// 告知浏览器文件的类型 response.setContentType(getServletContext().getMimeType(filenameEncoder)); // 告知浏览器以附件的方式提供下载功能 而不是解析
// Content-Disposition:设置用什么方式打开 attachment:代表附件
response.setHeader("Content-Disposition","attachment;filename="+filenameEncoder);
3)解决中文名显示乱码问题
// 获取文件名 String filename=request.getParameter("file");//??.png // 解决文件名中文乱码问题 filename=new String(filename.getBytes("ISO-8859-1"),"UTF-8");//乱码.png // 获取User-Agent获取客户端浏览器是哪个浏览器 String agent=request.getHeader("User-Agent"); String filenameEncoder=""; if (agent.contains("MSIE")) { // IE浏览器 filenameEncoder= URLEncoder.encode(filename, "utf-8"); filenameEncoder= filenameEncoder.replace("+", " "); } else if (agent.contains("Firefox")) { // 火狐浏览器 BASE64Encoder base64Encoder = new BASE64Encoder(); filenameEncoder= "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else { // 其它浏览器 filenameEncoder= URLEncoder.encode(filename, "utf-8"); } // 告知浏览器文件的类型 response.setContentType(getServletContext().getMimeType(filenameEncoder)); // 告知浏览器以附件的方式提供下载功能 而不是解析 // Content-Disposition:设置用什么方式打开 attachment:代表附件 response.setHeader("Content-Disposition","attachment;filename="+filenameEncoder);
全部代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <a href="/WEB05/DownLoadServlet?file=a.png">a.png</a> <a href="/WEB05/DownLoadServlet?file=a.txt">a.txt</a> <a href="/WEB05/DownLoadServlet?file=a.zip">a.zip</a> </body> </html> --------------------------------------- package com.oracle.demo02; //页面文件下载 显示中文 import java.io.FileInputStream; import java.io.IOException; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import sun.misc.BASE64Encoder; public class DownLoadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取文件名 String filename=request.getParameter("file");//??.png // 解决文件名中文乱码问题 filename=new String(filename.getBytes("ISO-8859-1"),"UTF-8");//乱码.png // 获取User-Agent获取客户端浏览器是哪个浏览器 String agent=request.getHeader("User-Agent"); String filenameEncoder=""; if (agent.contains("MSIE")) { // IE浏览器 filenameEncoder= URLEncoder.encode(filename, "utf-8"); filenameEncoder= filenameEncoder.replace("+", " "); } else if (agent.contains("Firefox")) { // 火狐浏览器 BASE64Encoder base64Encoder = new BASE64Encoder(); filenameEncoder= "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else { // 其它浏览器 filenameEncoder= URLEncoder.encode(filename, "utf-8"); } // 告知浏览器文件的类型 response.setContentType(getServletContext().getMimeType(filenameEncoder)); // 告知浏览器以附件的方式提供下载功能 而不是解析 response.setHeader("Content-Disposition","attachment;filename="+filenameEncoder); // 获取字节输出流 ServletOutputStream sos=response.getOutputStream(); // 获取数据源绝对路径 String realpath=getServletContext().getRealPath("download/"+filename); // 获取字节输入流 FileInputStream fis=new FileInputStream(realpath); // 开始复制 byte[] bytes=new byte[1024]; int len=0; while((len=fis.read(bytes))!=-1){ sos.write(bytes,0,len); } // 释放资源 fis.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
生成验证码
这是一个写好的 验证码代码
package com.oracle.demo02; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 验证码生成程序 * * * */ public class CheckImgServlet extends HttpServlet { // 集合中保存所有成语 private List<String> words = new ArrayList<String>(); @Override public void init() throws ServletException { // 初始化阶段,读取new_words.txt // web工程中读取 文件,必须使用绝对磁盘路径 String path = getServletContext().getRealPath("/WEB-INF/new_words.txt"); try { // 读取这个文件 BufferedReader reader = new BufferedReader(new FileReader(path)); String line; while ((line = reader.readLine()) != null) { words.add(line); } reader.close(); } catch (IOException e) { e.printStackTrace(); } } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 禁止缓存 // response.setHeader("Cache-Control", "no-cache"); // response.setHeader("Pragma", "no-cache"); // response.setDateHeader("Expires", -1); int width = 120; int height = 30; // 步骤一 绘制一张内存中图片 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 步骤二 图片绘制背景颜色 ---通过绘图对象 Graphics graphics = bufferedImage.getGraphics();// 得到画图对象 --- 画笔 // 绘制任何图形之前 都必须指定一个颜色 graphics.setColor(getRandColor(200, 250)); graphics.fillRect(0, 0, width, height); // 步骤三 绘制边框 graphics.setColor(Color.WHITE); graphics.drawRect(0, 0, width - 1, height - 1); // 步骤四 四个随机数字 Graphics2D graphics2d = (Graphics2D) graphics; // 设置输出字体 graphics2d.setFont(new Font("宋体", Font.BOLD, 18)); Random random = new Random();// 生成随机数 int index = random.nextInt(words.size()); String word = words.get(index);// 获得成语 // 定义x坐标 int x = 10; for (int i = 0; i < word.length(); i++) { // 随机颜色 graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random .nextInt(110), 20 + random.nextInt(110))); // 旋转 -30 --- 30度 int jiaodu = random.nextInt(60) - 30; // 换算弧度 double theta = jiaodu * Math.PI / 180; // 获得字母数字 char c = word.charAt(i); // 将c 输出到图片 graphics2d.rotate(theta, x, 20); graphics2d.drawString(String.valueOf(c), x, 20); graphics2d.rotate(-theta, x, 20); x += 30; } // 将验证码内容保存session request.getSession().setAttribute("checkcode_session", word); // 步骤五 绘制干扰线 graphics.setColor(getRandColor(160, 200)); int x1; int x2; int y1; int y2; for (int i = 0; i < 30; i++) { x1 = random.nextInt(width); x2 = random.nextInt(12); y1 = random.nextInt(height); y2 = random.nextInt(12); graphics.drawLine(x1, y1, x1 + x2, x2 + y2); } // 将上面图片输出到浏览器 ImageIO graphics.dispose();// 释放资源 //将图片写到response.getOutputStream()中 ImageIO.write(bufferedImage, "jpg", response.getOutputStream()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } /** * 取其某一范围的color * * @param fc * int 范围参数1 * @param bc * int 范围参数2 * @return Color */ private Color getRandColor(int fc, int bc) { // 取其随机颜色 Random random = new Random(); if (fc > 255) { fc = 255; } if (bc > 255) { bc = 255; } int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } }
在配置一下 web.xml,因为这个验证码代码 没有配置过Servlet,所以从新配置,更改一下 name 和class就可以
<servlet> <description></description> <display-name>CheckImgServlet</display-name> <servlet-name>CheckImgServlet</servlet-name> <servlet-class>com.oracle.demo02.CheckImgServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CheckImgServlet</servlet-name> <url-pattern>/CheckImgServlet</url-pattern> </servlet-mapping>
在导入已经写好的 验证码成语
验证码生成程序 实现点击事件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript"> function code(node){ /* 这样请求每次都不一样 */ node.src="/WEB05/CheckImgServlet?time="+new Date().getTime(); } </script> </head> <body> <img alt="" src="/WEB05/CheckImgServlet" onClick="code(this)"> </body> </html>