//设置定时刷新的头 response.setHeader("refresh", "5;url=http://www.baidu.com");
2重定向的实现
1 servlet1代码
package header; 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 Servlet1 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //没有响应 告知客户端去重定向到servlet2 //1、设置状态码302 //response.setStatus(302); //2、设置响应头Location //response.setHeader("Location", "/WEB14/servlet2"); //封装成一个重定向的方法sendRedirect(url) response.sendRedirect("/WEB14/servlet2"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
2 servlet2代码
package header; 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 Servlet2 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().write("hello haohao..."); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
3 手动设置状态码
//手动设置http响应行中的状态码 response.setStatus(404);
4 设置响应头
package header; import java.io.IOException; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HeaderServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Date date = new Date(); //设置响应头 response.addHeader("name", "zhangsan"); //response.addIntHeader("age", 28); //response.addDateHeader("birthday", date.getTime()); response.addHeader("name", "lisi"); response.setHeader("age", "28"); response.setHeader("age", "50"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
5 适用js完成页面定时跳转
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript"> window.onload = function(){ var time = 5; var secondEle = document.getElementById("second"); var timer = setInterval(function(){ secondEle.innerHTML = time; time--; if(time==0){ clearInterval(timer); location.href="http://www.baidu.com"; } },1000); } </script> </head> <body> 恭喜你,注册成功,<span style="color:red" id="second">5</span>秒钟后跳转,如不跳转点击<a href="http://www.baidu.com">这里</a>! </body> </html>
6 使用respone的writer(乱码问题的解决)
package p4.response; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 解决respone乱码问题 * 1. 告知response查询的码表 * response.setCharacterEncoding("UTF-8"); * 2. 通过一个头 Content-Type 告知客户端使用何种码表 * response.setHeader("Content-Type", "UTF-8"); * 注:浏览器默认使用的本地默认语言的编码,一般为gbk; * 实际只写response.setHeader("Content-Type", "UTF-8"); * 这一句代码也可以解决乱码问题。一看使用的是utf-8解码,response * 就会查询utf-8的编码表了。 * * 3 还可以直接使用封装好的方法进行解码 * response.setContentType("text/html;charset=UTF-8"); * 这个方法实际上也就是封装了上面两句话而已。 */ //1. 告知response查询的码表 //response.setCharacterEncoding("UTF-8"); //2. 通过一个头 Content-Type 告知客户端使用何种码表 //response.setHeader("Content-Type", "text/html;charset=UTF-8"); // 3 直接使用封装好的方法进行解决乱码问题 response.setContentType("text/html;charset=UTF-8"); PrintWriter writer = response.getWriter(); writer.write("你好"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
7 使用 response 的 OutputStream
ServletOutputStream getOutputStream()
Returns a ServletOutputStream suitable for writing binary
data in the response.
FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
代码如下:
package p4.response; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ByteServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1 使用response获得字节输出流 ServletOutputStream out = response.getOutputStream(); // 2 获得服务器上的图片的绝对路径 String realPath = this.getServletContext().getRealPath("a.jpg");//"a.jpg"相对于web资源 // 3 用一个输入流和文件相关联 InputStream in = new FileInputStream(realPath); // 4 读取文件并输出 int len=0; byte[] buffer = new byte[1024]; while((len=in.read(buffer))!=-1){ out.write(buffer, 0, len); } // 5 关闭资源 in.close(); out.close(); //respone 获得的流可以不用手动关闭, 会自动关闭。 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
8 完成文件的下载功能
问题 1:什么情况会文件下载?
答:浏览器不能解析的文件默认下载。
问题 2:什么情况下需要再服务端编写文件下载的代码?
答:理论上,浏览器可以解析的代码需要编写文件下载代码。
实际开发中,只要是需要下载的文件都编写文件下载代码。可能浏览器现在不能
解析,要是升级之后就可以解析了。
1 html代码实现
首先应该将相应的资源放入到web资源下
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>演示文件下载</title> </head> <body> <h1>使用 a 标签直接指向服务器上的资源</h1> <a href="/WEB14/download/a.flv">a.flv</a><br> <a href="/WEB14/download/a.jpg">a.jpg</a><br> <a href="/WEB14/download/a.mp3">a.mp3</a><br> <a href="/WEB14/download/a.mp4">a.mp4</a><br> <a href="/WEB14/download/a.txt">a.txt</a><br> <a href="/WEB14/download/a.zip">a.zip</a><br> <h1>使用服务器端编码的方式实现文件下载</h1> <a href="/WEB14/downloadServlet?filename=a.flv">a.flv</a><br> <a href="/WEB14/downloadServlet?filename=a.jpg">a.jpg</a><br> <a href="/WEB14/downloadServlet?filename=a.mp3">a.mp3</a><br> <a href="/WEB14/downloadServlet?filename=a.mp4">a.mp4</a><br> <a href="/WEB14/downloadServlet?filename=a.txt">a.txt</a><br> <a href="/WEB14/downloadServlet?filename=a.zip">a.zip</a><br> <a href="/WEB14/downLoadServlet2?filename=美女.jpg">美女.jpg</a><br> </body> </html>
2 Servlet代码实现
package p4.response; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DownloadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1 获得要下载的文件的名称 String filename = request.getParameter("filename");//a.flv // 2 告知客户端要下载的这个文件的类型-----客户端通过文件的 MIME 类型去区分类型 response.setContentType(this.getServletContext().getMimeType(filename)); // 3 告诉客户端该文件不是直接解析 而是以附件形式打开(下载) response.setHeader("Content-Disposition", "attachment;filename="+filename); //这个 filename 是固定的语法格式 // 4 获取文件的绝对路径 String path = this.getServletContext().getRealPath("download/"+filename); // 5 获得该文件的输入流 InputStream in = new FileInputStream(path); // 6 获得输出流---通过 response 获得的输出流 用于向客户端写内容 ServletOutputStream out = response.getOutputStream(); // 7 文件拷贝的模板代码 int len = 0; byte[] buffer = new byte[1024]; while((len=in.read(buffer))>0){ out.write(buffer, 0, len); } // 8 关闭资源 in.close(); //out.close();//respone 获得的流可以不用手动关闭, 会自动关闭。 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
9 解决下载文件【中文的文件名】乱码问题
但是,如果下载中文文件,页面在下载时会出现中文乱码或不能显示文件名的情
况,原因是不同的浏览器默认对下载文件的编码方式不同,ie 是 UTF-8 编码方
式,而火狐 浏览器是 Base64 编码方式。所里这里需要解决浏览器兼容性问题,
解决浏览器兼容性问题的首要任务是要辨别访问者是 ie 还是火狐(其他),通过
Http 请求体中的一 个属性可以辨别。
解决乱码方法如下 :
//其中 agent 就是请求头 User-Agent 的值
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"); }
1 html部分代码
<body> <h1>使用服务器端编码的方式实现文件下载</h1> <a href="/WEBTest13/download?filename=美女.jpg">美女.jpg</a><br> <!--download这个是Servlet的<url-pattern>配置的名字--> </body>
2 Servlet代码
public class DownloadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /*文件名称是中文的下载*/ //1获取要下载的文件的名称 //ç¾å¥³.jpg这里就已经乱码了 String filename = request.getParameter("filename"); //System.out.println(filename); //2 解决request获取中文乱码 //下面的方式可以解决resquest的get方法和post方式获取参数中文乱码问题。 filename = new String(filename.getBytes("iso8859-1"), "UTF-8"); //System.out.println(filename);//美女.jpg //3 告知客户端文件的类型 --- 客户端根据MIME判断下载的文件类型 response.setContentType(this.getServletContext().getMimeType(filename)); //4 告知客户端文件是以附件的形式打开下载 response.setHeader("Content-Disposition", "attachment;filename="+filename); // 5 获取文件的绝对路径 String path = this.getServletContext().getRealPath("download/"+filename); // 6 获取response输出流 ServletOutputStream out = response.getOutputStream(); // 7 用一个流和文件相关联 InputStream in = new FileInputStream(path); // 8 读取文件并下载 int len = 0; byte[] buffer = new byte[1024]; while((len=in.read(buffer))!=-1){ out.write(buffer, 0, len); } // 9关闭资源 in.close(); //out.close(); //response打开的流可以不用关闭。 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
3 解决上述问题
出现上述问题的原因是:
filename="+filename 客户端默认对名字进行解码
//4 告知客户端文件是以附件的形式打开下载
response.setHeader("Content-Disposition", "attachment;filename="+filename);
package p4.response; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; 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 { /*文件名称是中文的下载*/ //1获取要下载的文件的名称 //ç¾å¥³.jpg这里就已经乱码了 String filename = request.getParameter("filename"); //System.out.println(filename); //2 解决request获取中文乱码 //下面的方式可以解决resquest的get方法和post方式获取参数中文乱码问题。 filename = new String(filename.getBytes("iso8859-1"), "UTF-8"); //System.out.println(filename);//美女.jpg //===================================================== //解决下载文件 文件名为中文的时候 的乱码问题。 //filename="+filename 客户端默认对名字进行解码 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"); } //============================================================== //3 告知客户端文件的类型 --- 客户端根据MIME判断下载的文件类型 response.setContentType(this.getServletContext().getMimeType(filename)); //4//告诉客户端该文件不是直接解析 而是以附件形式打开(下载)----filename="+filename 客户端默认对名字进行解码 response.setHeader("Content-Disposition", "attachment;filename="+filenameEncoder); // 5 获取文件的绝对路径 String path = this.getServletContext().getRealPath("download/"+filename); // 6 获取response输出流 ServletOutputStream out = response.getOutputStream(); // 7 用一个流和文件相关联 InputStream in = new FileInputStream(path); // 8 读取文件并下载 int len = 0; byte[] buffer = new byte[1024]; while((len=in.read(buffer))!=-1){ out.write(buffer, 0, len); } // 9关闭资源 in.close(); //out.close(); //response打开的流可以不用关闭。 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
10 注意的细节点
public class ErrorServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //response.getOutputStream(); //response.getWriter(); //response.sendRedirect(location); } p rotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
11 实现验证码功能
1 动态生成验证码模板代码
1 package checking; 2 3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.Graphics2D; 7 import java.awt.image.BufferedImage; 8 import java.io.BufferedReader; 9 import java.io.FileReader; 10 import java.io.IOException; 11 import java.util.ArrayList; 12 import java.util.List; 13 import java.util.Random; 14 15 import javax.imageio.ImageIO; 16 import javax.servlet.ServletException; 17 import javax.servlet.http.HttpServlet; 18 import javax.servlet.http.HttpServletRequest; 19 import javax.servlet.http.HttpServletResponse; 20 21 /** 22 * 验证码生成程序 23 */ 24 public class CheckImgServlet extends HttpServlet { 25 26 // 集合中保存所有成语 27 private List<String> words = new ArrayList<String>(); 28 29 @Override 30 public void init() throws ServletException { 31 // 初始化阶段,读取new_words.txt 32 // web工程中读取文件,必须使用绝对磁盘路径 33 String path = getServletContext().getRealPath("/WEB-INF/new_words.txt"); 34 try { 35 BufferedReader reader = new BufferedReader(new FileReader(path)); 36 String line; 37 while ((line = reader.readLine()) != null) { 38 words.add(line); 39 } 40 reader.close(); 41 } catch (IOException e) { 42 e.printStackTrace(); 43 } 44 } 45 46 public void doGet(HttpServletRequest request, HttpServletResponse response) 47 throws ServletException, IOException { 48 // 禁止缓存 49 // response.setHeader("Cache-Control", "no-cache"); 50 // response.setHeader("Pragma", "no-cache"); 51 // response.setDateHeader("Expires", -1); 52 53 int width = 120; 54 int height = 30; 55 56 // 步骤一 绘制一张内存中图片 57 BufferedImage bufferedImage = new BufferedImage(width, height, 58 BufferedImage.TYPE_INT_RGB); 59 60 // 步骤二 图片绘制背景颜色 ---通过绘图对象 61 Graphics graphics = bufferedImage.getGraphics();// 得到画图对象 --- 画笔 62 // 绘制任何图形之前 都必须指定一个颜色 63 graphics.setColor(getRandColor(200, 250)); 64 graphics.fillRect(0, 0, width, height); 65 66 // 步骤三 绘制边框 67 graphics.setColor(Color.WHITE); 68 graphics.drawRect(0, 0, width - 1, height - 1); 69 70 // 步骤四 四个随机数字 71 Graphics2D graphics2d = (Graphics2D) graphics; 72 // 设置输出字体 73 graphics2d.setFont(new Font("宋体", Font.BOLD, 18)); 74 75 Random random = new Random();// 生成随机数 76 int index = random.nextInt(words.size()); 77 String word = words.get(index);// 获得成语 78 79 // 定义x坐标 80 int x = 10; 81 for (int i = 0; i < word.length(); i++) { 82 // 随机颜色 83 graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random 84 .nextInt(110), 20 + random.nextInt(110))); 85 // 旋转 -30 --- 30度 86 int jiaodu = random.nextInt(60) - 30; 87 // 换算弧度 88 double theta = jiaodu * Math.PI / 180; 89 90 // 获得字母数字 91 char c = word.charAt(i); 92 93 // 将c 输出到图片 94 graphics2d.rotate(theta, x, 20); 95 graphics2d.drawString(String.valueOf(c), x, 20); 96 graphics2d.rotate(-theta, x, 20); 97 x += 30; 98 } 99 // 将验证码内容保存session 100 request.getSession().setAttribute("checkcode_session", word); 101 102 // 步骤五 绘制干扰线 103 graphics.setColor(getRandColor(160, 200)); 104 int x1; 105 int x2; 106 int y1; 107 int y2; 108 for (int i = 0; i < 30; i++) { 109 x1 = random.nextInt(width); 110 x2 = random.nextInt(12); 111 y1 = random.nextInt(height); 112 y2 = random.nextInt(12); 113 graphics.drawLine(x1, y1, x1 + x2, x2 + y2); 114 } 115 116 // 将上面图片输出到浏览器 ImageIO 117 graphics.dispose();// 释放资源 118 119 //将图片写到response.getOutputStream()中 120 ImageIO.write(bufferedImage, "jpg", response.getOutputStream()); 121 122 } 123 124 public void doPost(HttpServletRequest request, HttpServletResponse response) 125 throws ServletException, IOException { 126 doGet(request, response); 127 } 128 129 /** 130 * 取其某一范围的color 131 * 132 * @param fc 133 * int 范围参数1 134 * @param bc 135 * int 范围参数2 136 * @return Color 137 */ 138 private Color getRandColor(int fc, int bc) { 139 // 取其随机颜色 140 Random random = new Random(); 141 if (fc > 255) { 142 fc = 255; 143 } 144 if (bc > 255) { 145 bc = 255; 146 } 147 int r = fc + random.nextInt(bc - fc); 148 int g = fc + random.nextInt(bc - fc); 149 int b = fc + random.nextInt(bc - fc); 150 return new Color(r, g, b); 151 } 152 153 }