ServletContext,Request (请求)和Response(响应)

tech2022-07-12  156

Request

Requst概述

用户通过浏览器访问服务器时,Tomcat将HTTP请求中所有的信息封装在Request对象中 作用:开发人员可以通过request对象方法,来获取浏览器发送的所有信息 Request体系结构:

ServletRequest | HttpServletRequest | org.apache.catalina.connector.RequestFacade(由tomcat厂商提供实现类)

在JavaEE中我们是面向接口编程:

Request获取Http请求信息

获取请求行信息

例如:GET /day09_request/requestDemo1 HTTP/1.1 相关API

获取请求方式:GET String getMethod()获取项目虚拟路径(项目名):/day09_request String getContextPath()获取URI:/day09_request/requestDemo1 统一资源定位符(确定某一个地址) StringBuffer getRequestURI()获取URL http://localhost:8080/day09_request/requestDemo1 统一资源定位符(确定某一个地址) 中华人民共和国 StringBuffer getRequestURL()获取协议和版本号 HTTP/1.1 String getProtocol()获取客户端ip String getRemoteAddr()
代码演示:
@WebServlet("/requestDemo1") public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // System.out.println(req); System.out.println("请求方式:" + req.getMethod()); System.out.println("虚拟路径:" + req.getContextPath()); System.out.println("URI:" + req.getRequestURI()); System.out.println("URL:" + req.getRequestURL()); System.out.println("协议和版本:" + req.getProtocol()); System.out.println("客户端ip:" + req.getRemoteAddr()); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }

获取请求头信息

例如: Host: localhost:8080

相关API:

获取知道请求头名称对应的值,注:名称不区分大小写 String getHeader(String name)

获取所有请求头的名称 Enumeration getHeaderNames() 注:是Iterator前身

代码演示:
@WebServlet("/requestDemo2") public class RequestDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取所有的请求头名称 Enumeration<String> enumeration = req.getHeaderNames(); // 遍历 while(enumeration.hasMoreElements()){ // 取出元素名(请求头名称) String name = enumeration.nextElement(); // 根据名称获取值 String value = req.getHeader(name); System.out.println(name +" : "+ value); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }

案例1:视频防盗链

referer:请求来源

/* 视频防盗链 */ @WebServlet("/refererRequest") public class RefererRequest extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); // 1.获取请求来源(如果是浏览器地址直接访问的话,referer就是null) String referer = req.getHeader("referer"); // 2.判断是不是自家网站发起的请求 if (referer != null && referer.startsWith("http://localhost:8080")) { resp.getWriter().write("正常播放视频..."); }else{ resp.getWriter().write("想看吗?来优酷吧...."); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }

案例2:浏览器兼容性

现在后端处理兼容性问题的需求越来越少,基本都是前端工程师完成的 user-agen:浏览器版本信息

/* 浏览器兼容性 */ @WebServlet("/userAgentReqeust") public class UserAgentReqeust extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); // 1.获取浏览器版本信息 String userAgent = req.getHeader("user-agent"); // 2.判断浏览器版本 if (userAgent.contains("Chrome")) { resp.getWriter().write("浏览器:谷歌"); } else if (userAgent.contains("Firefox")) { resp.getWriter().write("浏览器:火狐"); } else { resp.getWriter().write("浏览器:其他"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }

获取请求参数体

不论get还是post请求方式,都可以使用下列方法来获取请求参数在web里面,get和post处理的业务逻辑都是一样的…

参数 username=jack&password=123&hobby=drink&hobby=perm

API

获取指定参数名的值 username=jack String getParameter(String name)

获取指定参数名的值数组 hobby=drink&hobby=perm String[] getParameterValues(String name)

获取所有参数名和对应值数组,参数名 name(key),值数组 value,封装map集合 Map<String,String[]> getParameterMap()

中文乱码【重点】 get:在tomcat8及以上版本,内部URL编码(UTF-8) post:编码解码不一致,造成乱码现象 客户端(浏览器)编码:UTF-8 服务器默认 解码:ISO-8859-1 拉丁文 指定解码:void setCharacterEncoding(String env) 注:这哥们必须在方法内,行首

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>form</title> </head> <body> <h3>get方式:</h3> <form action="/day09_request/requestDemo3" method="get"> 用户:<input type="text" name="username"> <br> 密码:<input type="password" name="password"> <br> 爱好: <input type="checkbox" name="hobby" value="somke"/>抽烟 <input type="checkbox" name="hobby" value="drink"/>喝酒 <input type="checkbox" name="hobby" value="perm"/>烫头 <input type="submit" value="get提交..."> </form> <h3>post方式:</h3> <form action="/day09_request/requestDemo3" method="post"> 用户:<input type="text" name="username"> <br> 密码:<input type="password" name="password"> <br> 爱好: <input type="checkbox" name="hobby" value="somke"/>抽烟 <input type="checkbox" name="hobby" value="drink"/>喝酒 <input type="checkbox" name="hobby" value="perm"/>烫头 <input type="submit" value="post提交..."> </form> </body> </html> @WebServlet("/requestDemo3") public class RequestDemo3 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("手动获取---------"); String username = req.getParameter("username"); System.out.println("用户:" + username); String password = req.getParameter("password"); System.out.println("密码:" + password); String[] hobby = req.getParameterValues("hobby"); System.out.println("爱好:" + Arrays.toString(hobby)); System.out.println("自动获取---------"); Map<String, String[]> parameterMap = req.getParameterMap(); parameterMap.forEach((k, v) -> { System.out.println(k + " = " + Arrays.toString(v)); }); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 指定post的解码方式.... req.setCharacterEncoding("UTF-8"); System.out.println("post提交方法,再去调用get...."); this.doGet(req, resp); // 让get小老弟干活... } }

BeanUtils

这哥们apache组织,提供一套工具类,简化参数的封装…简单来说:将前端提交的数据,直接封装到你想要的JavaBean中 使用工具类封装数据 <h3>BeanUtils测试:</h3> <form action="/day09_request/requestDemo4" method="post"> 用户:<input type="text" name="username"> <br> 密码:<input type="password" name="password"> <br> 爱好: <input type="checkbox" name="hobby" value="somke"/>抽烟 <input type="checkbox" name="hobby" value="drink"/>喝酒 <input type="checkbox" name="hobby" value="perm"/>烫头 <input type="submit" value="post提交..."> </form> @WebServlet("/requestDemo4") public class RequestDemo4 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } // 使用BeanUtils快速封装数据到 User对象中 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8");// 指定解码方式 // 1.获取所有参数的数据,map集合 Map<String, String[]> parameterMap = request.getParameterMap(); // 2.创建user对象 User user = new User(); // 3.调用工具类,实现快速封装 try { BeanUtils.populate(user, parameterMap); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println(user); } }

Request其他功能

请求转发:

一种在服务器内部的资源跳转方式

API

通过reqeust对象,获得转发器对象 RequestDispatcher getRequestDispatcher(String path)

通过转发器对象,实现转发功能 void forward(ServletRequest request, ServletResponse response)

请求转发特点 浏览器:发了一次请求 地址栏:没有发生改变 只能转发到服务器内部资源…

链式编程 request.getRequestDispatcher("/bServlet").forward(reqeust,response)

域对象(共享数据)

域对象:一个有作用范围的对象,可以在范围内共享数据request域:代表一次请求的范围,一般用于一次请求中转发的多个资源中共享数据

API

设置数据 void setAttribute(String name, Object o)

获取数据 Object getAttribute(String name)

删除数据 void removeAttribute(String name)

生命周期

何时创建? 用户发送请求时,创建request

何时销毁 服务器返回响应是,销毁request

作用范围? 一次请求,包含多次转发

@WebServlet("/aServlet") public class AServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("aServlet处理功能上...."); // 转发到BServlet /* // 1.获得转发器对象 path = @WebServlet("/bServlet") RequestDispatcher requestDispatcher = request.getRequestDispatcher("/bServlet"); // 2.实现转发功能 requestDispatcher.forward(request, response);*/ // 存一个数据 request.setAttribute("hanbao", "香辣鸡腿堡"); // 链式编程横 request.getRequestDispatcher("bServlet").forward(request, response); } } @WebServlet("/bServlet") public class BServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("bServlet处理功能下...."); // 获取数据 String hanbao = (String) request.getAttribute("hanbao"); System.out.println("hanbao:" + hanbao); } }

获取ServletContext对象【了解】

中文直译:应用上下文对象,表示一个web项目 通过reuqest,可以获得ServletContext对象

public ServletContext getServletContext();

案例:用户登录

需求 实现用户的登录功能 登录成功跳转到SuccessServlet展示:登录成功!xxx,欢迎您 登录失败跳转到FailServlet展示:登录失败,用户名或密码错误 需求分析

创建web项目 导入BeanUtils工具类 编写index.html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> <h4>用户登录</h4> <form action="/day09_login/loginServlet" method="post"> 用户:<input type="text" name="username"> <br> 密码:<input type="password" name="password"> <br> <input type="submit" value="登录"> </form> </body> </html> User实体类 // 用户对象 public class User { private String username;// 用户名 private String password;// 密码 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}'; } } LoginServlet @WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.设置request解码方式 request.setCharacterEncoding("UTF-8"); // 2.获取浏览器请求参数,map集合 Map<String, String[]> parameterMap = request.getParameterMap(); // 3.使用BeanUtils工具类,封装user对象中 User user = new User(); try { BeanUtils.populate(user, parameterMap); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } // 4.判断(课下作业,你们写一个file文件,存储真实用户名和密码 判断) if("jack".equals(user.getUsername())&&"123".equals(user.getPassword())){ // 正确 request.setAttribute("user", user); request.getRequestDispatcher("/successServlet").forward(request,response); }else{ // 错误 request.getRequestDispatcher("/failServlet").forward(request,response); } } } SuccessServlet @WebServlet("/successServlet") public class SuccessServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.从request域获取user对象 User user = (User) request.getAttribute("user"); // 2.友情提示 response.setContentType("text/html;charset=utf-8"); response.getWriter().write(user.getUsername() + ",登录成功"); } } FailServlet @WebServlet("/failServlet") public class FailServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.友情提示 response.setContentType("text/html;charset=utf-8"); response.getWriter().write("用户名或密码错误.."); } }

Servlet模板设置

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end #parse("File Header.java") @javax.servlet.annotation.WebServlet("/${Class_Name}") public class ${Class_Name} extends javax.servlet.http.HttpServlet { protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException { this.doPost(request,response); } protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException { } }

ServletContext

ServletContext概述

Web容器(tomcat)在启动时,他会为每个web项目承建一个对应的ServletContext对象 它代表当前Web项目 主要作用:

域对象(共享数据)获取资源在服务器的真实地址获取全局的配置参数获取文件MIME类型

获取ServletContext对象

通过request对象获取: ServletContext sc = request.getServletContext();继承HttpServlet后,可以直接调用 ServletContext sc = getServletContext();

域对象(共享数据)

在当前项目范围中,共享数据(多个servlet都可以获取)

存储数据: void setAttribute(String name,Object value)获取数据: Object getAttribute(String name)删除数据: void removeAttribute(String name)
代码演示:

OneServlet

@WebServlet("/OneServlet") public class OneServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 向servletContext域存数据.... ServletContext sc1 = request.getServletContext(); ServletContext sc2 = getServletContext(); sc1.setAttribute("user", "jack"); System.out.println("OneServlet存了数据。。。"); } }

TwoServlet

@WebServlet("/TwoServlet") public class TwoServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 从servletContext域获取数据 String user = (String) request.getServletContext().getAttribute("user"); System.out.println("TwoServlet获取数据:"+user); } }

生命周期

何时创建? 项目加载时,创建何时销毁? 项目卸载时,销毁作用范围? 与项目共存亡(多个servlet都可以操作它)

获取资源在服务器的真实地址

可以实现web项目的移植性,动态获取文件真实路径 API: String getRealPath(String path);

@WebServlet("/RealpathServlet") public class RealpathServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取car.jpg 文件真实路径 String carPath = request.getServletContext().getRealPath("/img/car.jpg"); System.out.println(carPath); // 获取web.xml 文件真实路径 String webPath = request.getServletContext().getRealPath("/WEB-INF/web.xml"); System.out.println(webPath); } }

获取全局的配置参数

读取web.xml配置文件中标签信息,实现参数和代码的解耦(多个servlet都可以获取) web.xml

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--全局配置参数:所有的servlet都可以读取...--> <context-param> <param-name>encode</param-name> <param-value>UTF-8</param-value> </context-param> </web-app>

ContextPathServlet

@WebServlet("/ContextPathServlet") public class ContextPathServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取全局参数 String value = request.getServletContext().getInitParameter("encode"); System.out.println("全局配置参数:"+value); } }

获取文件MIME类型

在互联网通信过程中定义的一种文件数据类型 格式:大类型/小类型例如:text/html image/jpeg`

<a href="/day10_servletContext/MimeServlet?filename=luola.avi">获取文件的mime类型</a><br> @WebServlet("/MimeServlet") public class MimeServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取指定文件的mime类型 // 获取请求参数 String filename = request.getParameter("filename"); // 获取文件的mime类型 String mimeType = request.getServletContext().getMimeType(filename); response.getWriter().write(filename + "---" + mimeType); } }

案例:统计网站的访问次数

需求: 一般个人博客的首页,都会显示你是第几位访问此网站…

@WebServlet(value = "/CountServlet", loadOnStartup = 4) // 服务器启动时,创建此servlet对象 public class CountServlet extends HttpServlet { @Override public void init() throws ServletException { getServletContext().setAttribute("count", 0); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置response响应编码 response.setContentType("text/html;charset=utf-8"); response.getWriter().write("<h1>itcast博客网站</h1>"); // 用户每次访问,从域中取出,加1,再存进去 ServletContext servletContext = request.getServletContext(); // 从域中取出 Integer count = (Integer) servletContext.getAttribute("count"); // 加1 count++; // 再存进去 servletContext.setAttribute("count", count); response.getWriter().write("<div>你是,第" + count + "位访问此网站...</div>"); } }

Response

概述:

response对象表示web服务器给浏览器返回的响应信息 作用:开发人员可以使用response对象的方法,设置要返回给浏览器的响应信息

Response体系结构

ServletResponse 接口 | HttpServletResponse 接口 | org.apache.catalina.connector.ResponseFacade 实现类(由tomcat提供的)

设置Http响应消息

响应行:

* 格式 协议/版本号 状态码 * 例如 HTTP/1.1 200 * API 1. 设置状态码 void setStatus(int sc)

响应头

* 格式 响应头名称:响应头的值 * 例如 Location:http://www.itcast.cn * API 1. 设置指定头名称和对应的值 void setHeader(String name, String value)

响应体【重点】

* API(输出流对象) 1. 字符输出流 PrintWriter getWriter() 2. 字节输出流 ServletOutputStream getOutputStream() 注意:在同一个servlet中,二种类型的输出流不能同时存在,互斥

响应重定向

需求: 用户访问AServlet后,服务器告诉浏览器重定向到BServlet

步骤分析:

* 方式一 // 1.设置状态码 response.setStatus(302); // 2.设置响应头 Location response.setHeader("Location","重定向网络地址"); * 方式二 // 1.response这哥们封装专门处理重定向的方法 response.sendRedirect("重定向网络地址");

重定向特点

地址栏会发生改变重定向是二次请求重定向是客户端(浏览器)行为,可以跳转到服务器外部资源…不能使用request域共享数据 @WebServlet("/AServlet") public class AServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("AServlet执行了...."); /* // 1.设置状态码 response.setStatus(302); // 2.设置响应头 Location response.setHeader("Location","/day10_response/BServlet");*/ // 1.response这哥们封装专门处理重定向的方法 response.sendRedirect("http://www.itcast.cn"); } } @WebServlet("/BServlet") public class BServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("BServlet执行了...."); } }

转发与重定向的区别:

哪个对象 转发(request对象的方法) request.getRequestDispatcher("/bServlet").forward(request,response); 重定向(response对象的方法) response.sendRedirect("/day10_response/bServlet");

几次请求 转发 地址栏: 没有改变 浏览器: 发了一次请求 服务器: 只有一对请求和响应对象 发生的位置: 服务器 重定向 地址栏: 发生了改变 浏览器: 发了两次请求 服务器: 有两对请求和响应对象 发生的位置: 浏览器

小结 写法 转发("/servlet资源路径") 服务器内部行为 重定向 ("/虚拟路径(项目名)/servlet资源路径") 浏览器外部行为 使用场景(重点掌握) 如果需要传递数据(request域),使用转发 如果不需要传递数据(request域),使用重定向

响应定时刷新

需求:在当前页面停留3秒钟之后,跳转到传智播客首页

步骤分析

通过response设置响应头 Refresh response.setHeader("Refresh","间隔时间(秒);跳转页面"); @WebServlet("/RefreshServlet") public class RefreshServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 通过response设置响应头 Refresh response.setHeader("Refresh", "3;http://www.itcast.cn"); response.setContentType("text/html;charset=utf-8"); response.getWriter().write("操作成功,3秒后跳转到传智首页..."); } }

响应体【重中之重】

需求:向页面输出中文数据没有乱码

步骤分析:

通过response获取字符输出流 PrintWriter pw = response.getWriter();通过字符输出输出文本 pw.write(“中文…”);

解决中文乱码

指定服务器响应编码方式 response.setCharacterEncoding(“GBK”);统一浏览器和服务器编码 response.setContentType(“text/html;charset=utf-8”); @WebServlet("/EncodeServlet") public class EncodeServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 指定服务器响应编码方式 // response.setCharacterEncoding("UTF-8"); // 统一浏览器和服务器编码 response.setContentType("text/html;charset=utf-8"); // 1. 通过response获取字符输出流 PrintWriter pw = response.getWriter(); // 2. 通过字符输出输出文本 pw.write("中文...."); } }

综合案例【作业】

点击切换验证码:

需求:在页面展示登录验证码,点击辞严证码可以更换新的验证码 作用:防止表单的恶意提交 本质上:就是一张随机图片 如何通过java代码制作一个验证码

/* 跟我一起了解一下验证码的制作代码.... */ @WebServlet("/CheckcodeServlet") public class CheckcodeServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 创建画布 int width = 120; int height = 40; BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获得画笔 Graphics g = bufferedImage.getGraphics(); // 填充背景颜色 g.setColor(Color.white); g.fillRect(0, 0, width, height); // 绘制边框 g.setColor(Color.red); g.drawRect(0, 0, width - 1, height - 1); // 生成随机字符 // 准备数据 String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; // 准备随机对象 Random r = new Random(); // 声明一个变量 保存验证码 String code = ""; // 书写4个随机字符 for (int i = 0; i < 4; i++) { // 设置字体 g.setFont(new Font("宋体", Font.BOLD, 28)); // 设置随机颜色 g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255))); String str = data.charAt(r.nextInt(data.length())) + ""; g.drawString(str, 10 + i * 28, 30); // 将新的字符 保存到验证码中 code = code + str; } // 绘制干扰线 for (int i = 0; i < 6; i++) { // 设置随机颜色 g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255))); g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height)); } // 将验证码 打印到控制台 System.out.println(code); // 将验证码放到session中 request.getSession().setAttribute("code_session", code); // 将画布显示在浏览器中 ImageIO.write(bufferedImage, "jpg", response.getOutputStream()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } <img src="/day10_response/CheckcodeServlet" alt="servlet随机验证码" id="img1"> <br> <script> // 给图片绑定一个点击事件 document.getElementById('img1').onclick=function () { // 重置src路径,重写发送请求 this.src='/day10_response/CheckcodeServlet?'+new Date().getTime(); // 后面加一个毫秒值的时间戳,欺骗浏览器 } </script>

文件下载

需求:用户点击页面的链接,浏览器开始下载文件。

将需要下载的素材复制到web项目中 编写下载页面 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>donload.html</title> </head> <body> <h3>文件下载</h3> <h5>超链接下载</h5> <a href="/day10_response/download/demo.docx">word文档</a><br> <a href="/day10_response/download/car.jpg">图片下载</a><br> <a href="/day10_response/download/test.zip">压缩包下载</a><br> <h5>servlet下载</h5> </body> </html>

缺点:

浏览器可识别的媒体类型,是直接打开而不是下载不能判断用户是否登录,进行限制

使用Servlet下载文件 两个响应头两个字节流

被下载文件的字节输入流 FileInputStreamresponse字节输出流 ServletOutputStream告知客户端下载文件的MIME类型(最新的浏览器此步骤可以省略…) Content-Type:MIME类型告知浏览器以附件的方式保存 Content-Disposition:attachment;filename=文件名 attachment 附件 filename=文件名 .

download.html

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>donload.html</title> </head> <body> <h3>文件下载</h3> <h5>超链接下载</h5> <a href="/day10_response/download/demo.docx">word文档</a><br> <a href="/day10_response/download/car.jpg">图片下载</a><br> <a href="/day10_response/download/test.zip">压缩包下载</a><br> <h5>servlet下载</h5> <a href="/day10_response/DownLoadServlet?filename=demo.docx">word文档</a><br> <a href="/day10_response/DownLoadServlet?filename=girl.jpg">靓女</a><br> <a href="/day10_response/DownLoadServlet?filename=禽兽.jpg">禽兽</a><br> </body> </html> DownLoadServlet @WebServlet("/DownLoadServlet") public class DownLoadServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.获取请求文件名 String filename = request.getParameter("filename"); // 2.获取文件真实路径,封装到字节输入流 ServletContext servletContext = request.getServletContext(); String realPath = servletContext.getRealPath("/download/" + filename); FileInputStream in = new FileInputStream(realPath); // 3.告诉浏览器mime类型 String mimeType = servletContext.getMimeType(filename); response.setContentType(mimeType); // 4.告诉浏览器以附件方式保存 // 解决中文乱码和浏览器兼容性 String userAgent = request.getHeader("user-agent"); // 调用工具类处理 filename = DownLoadUtils.getName(userAgent, filename); response.setHeader("content-disposition", "attachment;filename=" + filename); // 5.获取字节输出流 ServletOutputStream out = response.getOutputStream(); // 6.io流的拷贝 byte[] b = new byte[4096];// 4kb int len = -1; while((len = in.read(b))!=-1){ out.write(b, 0, len); } // 7.释放资源 out.close(); // out流对象,可以交给tomcat关闭 in.close(); } } 中文乱码

如果该下载文件名是中文的话,会出现乱码… 谷歌和绝大多数的浏览器是通过 url编码 URLEncode() 编码 URLDecode() 解码 火狐浏览器 base64编码

我们就需要考虑浏览器兼容性问题… 今天帅哥提供了判断浏览器不同编码的工具类直接使用即可…

hutool工具包 这哥们封装了se阶段的很多基础操作…官网:https://www.hutool.cn/

最新回复(0)