Java EE: Servlet API
javax.servlet
Java EE介绍
在
Java EE 8及之前,这个企业版是由Oracle开发的闭源项目,包括一系列大型或中小型的商业软件包,但由于Spring等框架的流行,Java EE开始力不从心于是在之后,
Oracle将整个Java EE移交给Eclipse开源基金会维护,并强制要求Eclipse不能继续使用Java EE的项目名以及javax的命名空间,因此在Eclipse接手这个项目后迫不得已将javax改为jakarta,并将大版本号提升至5,表示不再向下兼容总而言之,
javax命名空间适用于4.0及之前的企业版项目,jakarta适用于5.0及之后的企业版Servlet源于Server Applet,即在服务端上运行的小程序在
SE的网络编程中对于Http的处理只介绍了HttpClient,即客户端的编写,是因为服务端需要考虑的东西过多而
Servlet项目致力于高效而安全地开发服务器Servlet本质可用于任意通信协议,但主要用于HTTP它内部封装了线程池,通过多线程的方式处理请求,因此比起此前的方案性能更高
Servlet需要部署到专用的Web服务器上,称作Servlet容器,例如Apache的Tomcat项目、Eclipse的Jetty项目因为
Servlet本质是一个Web应用,是Servlet容器向开发者暴露的规范接口,Servlet容器是更复杂的应用
servlet依赖
接口依赖:
1
2
3
4
5
6
7
8
9
10
11<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
</dependency>Servlet接口的实现由Web容器提供,可以使用provided表示仅编译时需要
Servlet接口与HttpServlet实现类
Servlet有三个重要方法:init()、service()、destroy(),由Servlet容器调用进行生命周期管理service()含有两个参数HttpServletRequest与HttpServletResponseHttpServlet是最常用的实现类,有四个重要方法:doGet()、doPost()、doPut()、doDelete()它们也均含有两个参数:
HttpServletRequest与HttpServletResponse重写它们来自定义处理逻辑
一般不需要重写
service(),由HttpServlet已经实现好了,他会自动解析请求方法并调用doXxx()除非需要使用
HttpServlet处理其它通信协议HttpServletRequest接口表示一个HTTP请求报文,常用方法如下:setCharsetEncoding(String):设置解析的编码集String getParameter(String name):获取某个请求参数这里的参数已经消除了
GET、POST等不同请求方法的差异,但对于POST方法而言,只会解析类型为application/x-www-form-urlencoded或multipart/form-data,其它类型如application/json需要通过输入流获取String getHeader(String name):获取某个请求头getRequestDispatcher(String location):获取一个请求分发器,指向内部的另一个URI,通常会继续调用RequestDispatcher接口的forward(req, resp)内部转发出去或include(req, resp)转发后回来getAttribute()和setAttribute():可以主动设置属性,方便请求处理链条中数据的传递
HttpServletResponse接口表示一个HTTP响应报文,常用方法如下:setCharsetEncoding(String):设置解析的编码集setContentType(String type):设置响应体的类型PrintWriter getWriter():获取绑定的字符输出流ServletOutputStream getOutputStream():获取绑定的字节输出流setStatus(int):设置状态码setHeader(String name, String value):设置响应头sendRedirect(String):302临时重定向到另一个URI
一个服务器的所有
Servlet实现类只会有一个实例,因此遇到多个请求时会用同一个实例来处理因此实现类的实例属性的所有访问需要保证线程安全
Session与Cookie
Session用于存储客户端的某种状态,能保证每个Session唯一,内部类似于一个Map<String, Object>HttpServletRequest对象的getSession()方法会(若不存在)创建并返回一个HttpSession对象,(若存在)直接返回HttpSession对象getSession(false)则不会创建,而只是返回已有的对象,若无则返回nullHttpSession实例的常用方法为setAttribute(String, Object)和Object getAttribute(Stirng)以及removeAttribute(String)分别为设置、获取、删除其存储的对象数据
Session通常是通过Cookie技术实现的,它会让客户端在发送请求时同时发送一个Session自定义
Cookie需直接通过构造方法new Cookie(String name, String value)创建Cookie可设置最大时间setMaxAge(seconds)通过
HttpServletResponse实例的addCookie(Cookie)方法传递给客户端通过
HttpServletRequest实例的getCookies()获取Cookie[]数组通过
Cookie实例的getName()和getValue()获取键值对
ServletContext
ServletContext是Web应用上下文的抽象,可以用它获取整个Web应用的信息,最常用的方法如下:- 获取
Web应用的属性:Object getAttribute(String) - 设置
Web应用的属性:void setAttribute(String, Object) - 移除
Web应用的属性:void removeAttribute(String) - 记录日志:
log(String) - 使用上下文需注意,因为处于多线程环境,虽然
ServletContext本身是线程安全的,但传入的属性值需要自行确保线程安全
ServletConfig
ServletConfig是某个Servlet服务的配置的抽象,可以用它获取某个Servlet服务独有的配置项,最常用的方法如下:- 获取初始参数:
String getInitParameter(),这个初始参数可以用XML或注解的形式设置,也可由内嵌Tomcat的Wrapper配置
JSP技术
JSP技术比较落后,了解即可由于
Servlet本质是内嵌HTML的Java微服务程序,大量的HTML文本由一行行的输出流打印比较麻烦,因此JSP技术出现JSP本质也是一个Servlet应用,由Web服务器在启动时自动将其编译成Servlet程序并在服务器上运行JSP作为静态资源可由Web容器自动部署,但也可以自定义部署URL路径JSP语法:Jsp脚本:<% Java代码 %>,只执行代码,没有返回值Jsp表达式:<%= Expr %>,返回表达式的值Jsp声明:<%! 成员变量、方法 %>Jsp指令:<%@ 指令 %>Jsp动作:<jsp:action />Jsp注释:<%-- 注释 --%>EL表达式:$ { expr }
JSP隐含对象:在Jsp脚本中不用声明就可使用的对象,但不能重复定义HttpServletRequest request与HttpServletResponse response:因为JSP本身就是一个Servlet,自然有request和response参数HttpSession session:等价于request.getSession()ServletConfig config:JSP这个Servlet的配置JspWriter out:不常用PageContext pageContext:是整个页面上下文的抽象page:等价于this,是这个Jsp翻译得到的Servlet程序实例,因为this是可省略的所以page不会被直接使用Exception exception:用于异常处理
JSP指令:- 声明页面的属性:
<%@ page import="java.util.*, java.net.*" %> - 声明页面包含其它页面:
<%@ include other.jsp %> - 声明
Tag的来源以及前缀:<%@ taglib uri="" prefix="" %>
- 声明页面的属性:
EL表达式的隐含对象PageContext pageContext:除它之外,以下所有都是Mapparam:对应request的参数表paramValues:对应request的参数表,只不过值是数组用于存储含多个值的参数header:对应request的请求头表headerValues:对应request的请求头表,只不过值是数组用于存储含多个值的请求头cookie:对应cookie表initParam:对应ServletConfig的初始参数表pageScope:页面作用域,可通过它访问所有在页面内定义的标识符requestScope:请求作用域,可通过它访问所有在request中定义的attributesessionScope:会话作用域,可通过它访问所有在session中定义的attributeapplicationScope:应用作用域EL表达式可以不指定隐含对象地输出字段,此时会从小到大(pageScope->requestScope->sessionScope->applicationScope)地查找该字段
EL表达式的关键字:not、le、lt、ge、gt、eq、ne、div等Jsp动作:<jsp:useBean id="a" class="com.Clazz" scope="page|request|session|application"/>创建一个标识为
a、类型为com.Clazz、所属作用域为所有作用域的对象<jsp:getProperty name="a" property="age"/>获取标识为
a的对象的age属性<jsp:setProperty name="a" property="age" value="value"/>设置标识为
a的对象的age属性为字面量"value"<jsp:setProperty name="a" property="age" param="age"/>设置标识为
a的对象的age属性为引用变量age的值
Filter
Filter接口作用于收到请求、初始化响应之后,Servlet服务处理请求之前,可用于身份校验、初始化配置等- 实现
Filter接口需要实现doFilter(ServletRequest, ServletResponse, FilterChain)方法,如果需要拦截则直接return,如果放行则需要调用FilterChain实例的doFilter(ServletRequest, ServletResponse)方法
Listener
Listener采用观察者模式,当某种实例创建、更改、销毁时,自定义的Listener组件会随之调用对应的方法Listener本身并不存在,只存在一系列的XxxListener接口