JavaWeb三大组件之Servlet------Servlet详细讲解
Servlet
Servlet介绍
- Servlet 是 Java提供的一门动态web资源开发技术
- Servlet 是运行在Web服务器中的小型Java程序
- Servlet 通常通过HTTP(超文本传输协议)接收和响应来自Web客户端的请求
- Servlet 是JavaEE 规范之一,其实就是一个接口
Servlet快速入门
- 创建web项目,导入Servlet依赖坐标
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies>
- 创建:定义一个类,实现Servlet接口,并重写接口中所有方法,并在service方法中输入一句话
- 配置:在类上使用@WebServlet注解,配置该Servlet的访问路径
package com.moming.web_servlet; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import java.io.IOException; //指定访问路径,servlet的映射路径 @WebServlet(urlPatterns = "/demo1",loadOnStartup = 1) public class ServletDemo1 implements Servlet { /** * 初始化方法 * 1.调用时机:默认情况下,Servlet被第一次访问时调用 * *修改调用时机loadOnStartup,默认是-1(即被访问时调用) * *改为1时,在服务器启动时就调用了 * 2.调用次数:1次 * @param servletConfig * @throws ServletException */ @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("servlet对象创建了"); } /** * 提供服务 * 1.调用时机:每一次Servlet被访问时调用 * 2.调用次数:多次 * @param servletRequest * @param servletResponse * @throws ServletException * @throws IOException */ @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("service方法被调用了"); } //获取ServletConfig对象(servlet配置对象) @Override public ServletConfig getServletConfig() { return null; } //获取Servlet信息(例如作者版权信息) @Override public String getServletInfo() { return null; } /** * 销毁方法 * 1.调用方法:内存释放或者服务器关闭的时候,Servlet对象被销毁,调用 * 2.调用次数:1次 * @return */ @Override public void destroy() { System.out.println("servlet对象被销毁了"); } }
- 访问:启动Tomcat,浏览器输入URL访问该Servlet
Servlet执行流程
- Servlet由web服务器创建,Servlet方法由web服务器调用
Servlet生命周期
- 对象的生命周期指一个对象从被创建到被销毁的整个过程
Servlet运行在Servlet容器(web服务器)中,其生命周期由容器来管理,分为4个阶段:
- 加载和实例化:默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象
- 初始化:在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次
- 请求处理:每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理。
- 服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法完成资源的释放。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收
Servlet体系结构
我们将来开发B/S架构的web项目,都是针对HTTP协议,所以我们自定义Servlet,会继承HttpServlet
package com.moming.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; @WebServlet("/demo2") public class ServletDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get---"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //doGet(req, resp);//正常逻辑是在doPost方法里调用doGet方法 System.out.println("post---"); } }
Servlet urlPattern配置
- Servlet要想被访问,必须配置其访问路径(urlPattern)
- 一个Servlet,可以配置多个urlPattern---@WebServlet(urlPattern = {"/demo1","/demo2"})
urlPattern配置规则
- 精确配置
- 目录匹配
- 扩展名匹配
- 任意匹配
XML配置方法编写Servlet(老版本)
Servlet 从3.0版本后开始支持使用注解配置,3.0版本前只支持 XML 配置文件的配置方式
步骤
- 编写 Servlet类 在
- web.xml中配置该Servlet
<!--Servlet全类名--> <servlet> <servlet-name>demo3</servlet-name> <servlet-class>com.moming.web_servlet.ServletDemo3</servlet-class> </servlet> <!--Servlet的访问路径--> <servlet-mapping> <servlet-name>demo3</servlet-name> <url-pattern>/demo3</url-pattern> </servlet-mapping>
Request
- Request(请求):获取请求数据
Request继承体系
Request获取请求数据
1.请求行:例:GET /request-demo/req1?username=zhangsan HTTP/1.1
- String getMethod():获取请求方式: GET
- String getContextPath():获取虚拟目录(项目访问路径): /request-demo
- StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
- String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
- String getQueryString():获取请求参数(GET方式): username=zhangsan&password=123
2.请求头:例:User-Agent:Mozilla/5.0 Chrome/91.0.4472.106
- String getHeader(String name):根据请求头名称,获取值
3.请求体:例:username=superbaby&password=123
- ServletInputStream getInputStream():获取字节输入流(一般是文件上传的时候使用)
- BufferedReader getReader():获取字符输入流
- 两种流不能同时使用
通用方式获取请求参数
- GET 方式:String getQueryString()
- POST 方式:BufferedReader getReader()
- Map<String, String[ ]> getParameterMap():获取所有参数Map集合
- String[ ] getParameterValues(String name) :根据名称获取参数值(数组)
- String getParameter(String name):根据名称获取参数值(单个值)
请求参数中文乱码处理
- post: 不考虑tomcat版本,统一都是直接使用:request.setCharacterEncoding("utf-8")
- get: tomcat8以后的版本,在tomcat内部已经解决了(就不需要设置下图的配置),7及以前的通过配置文件设置编码格式,或者:new String(username.getBytes("ISO-8859-1"),"UTF-8"); 其中username为乱码属性
Request请求转发
请求转发(forward):
- 一种在服务器内部的资源跳转方式
实现方式:
- req.getRequestDispatcher("资源B路径").forward(req,resp);
请求转发资源间共享数据:使用Request对象
- void setAttribute(String name, Object o):存储数据到 request域中
- Object getAttribute(String name):根据 key,获取值
- void removeAttribute(String name):根据 key,删除该键值对
请求转发特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器的内部资源
- 一次请求,可以在转发的资源间使用request共享数据
- getParameter获取浏览器的请求参数
- getAttribute是获取域中共享的数据
Response
- Response(响应):设置响应数据
Response 设置响应数据功能介绍
响应数据分为3部分:
响应行:HTTP/1.1 OK
- void setStatus(int sc) :设置响应状态
响应头:Content-Type: text/html
- void setHeader(String name, String value) :设置响应头键值对
响应体:<html><head></head><body></body></html>
- PrintWriter getWriter():获取字符输出流
- ServletOutputStream getOutputStream():获取字节输出流(一般文件下载时使用)
Response 完成重定向
重定向(Redirect):一种资源跳转方式
实现方式:
- response.setStatus(302);
- response.setHeader("location","需要跳转资源的路径");
- 简化方式:
- response.sendRedirect("需要跳转资源的路径"); 带虚拟目录(内部服务器可以省略协议IP和端口)
- 路径:协议://IP: 端口/虚拟目录/servlet映射路径
重定向特点:
- 浏览器地址栏路径发生变化
- 可以重定向到任意位置的资源(服务器内部、外部均可)
- 两次请求,不能在多个资源使用request共享数据
路径问题
- 浏览器使用(浏览器到服务器):需要加虚拟目录(项目访问路径)
- 服务端使用:不需要加虚拟目录
重定向与转发的区别
- 在服务器内部访问资源路径一般使用转发
- 而在访问第三方网址的时候就只能使用重定向跳转资源路径
Response 响应字符数据
步骤:
- 通过Response对象获取字符输出流: PrintWriter writer = response.getWriter();
- 写数据: writer.write("写的文本内容");
注意:
- 该流不需要关闭,随着响应结束,response对象销毁,由服务器关闭
- 中文数据乱码:原因通过Response获取的字符输出流默认编码:ISO-8859-1
- 解决方法: response.setContentType("text/html;charset=utf-8");
Response 响应字节数据
步骤:
- 通过Response对象获取字节输出流: ServletOutputStream outputStream = resp.getOutputStream();
- 写数据: outputStream.write(字节数据);
IOUtils工具类使用
- 添加坐标
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
- IOUtils.copy(输入流,输出流);
- 一般项目图片都是在项目中的,即在webapp目录下,考虑到项目可能运行在不同的环境下,所以对图片的绝对路径需要进一步处理
注意: 中文参数请求乱码,由于超链接是get请求,在pom.xml中已经处理过了,不需要加request.setCharacterEncoding("utf-8"); 否则的化会乱码报错