Servlet
大约 16 分钟
全称为 Server Applet(服务器小程序),主要功能用于生成动态的 Web 内容
- 缺点
- 静态 HTML 与动态 Java 代码混合在一起,难以维护
- Servlet 利用 out.print() 语句输出,开发效率低下
- Eclipse 很难在开发过程中发现错误,调试困难
发展史
单机时代
桌面应用:桌面应用俗称单机应用,软件所有数据都保存在电脑本地硬盘中
优点
- 易于使用
- 结构简单
缺点
- 数据难以共享
- 安全性差
- 更新不及时
联机时代
Client-Server 模式(C/S 架构):客服端/服务器模式
优点
- 数据方便共享
- 安全性高
缺点
- 必须安装客户端
- 升级与维护困难
互联网时代
Browser-Server 模式(B/S 架构):浏览器/服务器模式
- 优点
- 开发简单
- 无需安装客户端
- 易于数据共享
- 缺点
- 相较于 C/S 模式,执行速度与用户体验较弱
J2EE
- J2EE 是一组技术规范与指南,具体实现由软件厂商决定
- Tomcat 是 J2EE Web(Servlet 与 JSP)标准的实现者
- J2SE 是 J2EE 运行的基石,运行 Tomcat 离不开 J2SE
![](https://cdn.jsdelivr.net/gh/sunzhenyang/blog-img/img/20210510230104.png)
![](https://cdn.jsdelivr.net/gh/sunzhenyang/blog-img/img/20210511002301.png)
开发步骤
- 创建 Servlet 类,继承 HttpServlet
- 重写 service 方法,编写程序代码
service
方法可同时处理GET
、POST
请求doGet
方法用来处理GET
请求doPost
方法用来处理POST
请求
// com.imooc.servlet.FirstServlet.java
package com.imooc.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FirstServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) {
// 接受请求发来的参数
String name = request.getParameter("name");
String html = "<h1 style='color:red;font-size:20px;font-weight:bold;'>" + name + "</h1>";
System.out.println("返回给浏览器的数据为:" + html);
try {
PrintWriter out = response.getWriter();
out.println(html);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 配置 web.xml,绑定 URL
<!-- web.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>FirstServlet</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- Servlet 别名 -->
<servlet>
<servlet-name>first</servlet-name>
<servlet-class>com.imooc.servlet.FirstServlet</servlet-class>
</servlet>
<!-- 将 Servlet 与 URL 绑定 -->
<servlet-mapping>
<servlet-name>first</servlet-name>
<url-pattern>/hi</url-pattern>
</servlet-mapping>
</web-app>
- 访问路径:
http://localhost:8080/FirstServlet/hi?name=Yang
- 结构:
http://IP地址:端口/context-path/url-mappint
context-path
:上下文路径,默认为工程名
- 结构:
数据请求
请求方法
GET
将数据通过在 URL 附加数据显性向服务器发送数据
- 常用于不包含敏感信息的查询功能
POST
将数据放在
请求体
中隐性向服务器发送数据
- 常用于安全性要求较高的功能或者服务器的
写
操作
Request 方法
request.getMethod()
:获取请求方法request.getHeader("User-Agent")
:获取请求头中的属性request.getParameter()
:接受单个参数request.getParameterValues()
:接受相同名称的多个值request.getAttribute(属性名)
:获取请求自定义属性(返回 Object)req.getAttribute("javax.servlet.forward.query_string")
:访问最初的查询串
request.setAttribute(属性名,属性值)
:设置请求自定义属性
Response 方法
response.setContentType("text/html;charset=utf-8")
:设置 ContentTyperesponse.sendError(404)
:生成错误
HTTP 常见状态码
1xx
:信息提示,表示临时的响应2xx
:响应成功,表明服务器成功的接受了客户端的请求3xx
:重定向4xx
:客户端错误,表名客户端可能有问题5xx
:服务器错误,表明服务期由于遇到某种错误而不能响应客户请求
状态码 | 错误描述 |
---|---|
200 | 服务器处理(响应)成功 |
301、302 | 请求重定向 |
400 | 无效(错误)的请求,客户端发送的 HTTP 请求不正确 |
401 | 未经过授权 |
403 | 服务器拒绝访问 |
404 | 文件不存在,在服务器上没有客户要求访问的文档 |
405 | 服务器不支持客户的请求方式 |
500 | 服务器内部错误 |
503 | 服务器超负载或正停机维护,无法处理请求 |
ContentType
决定浏览器采用何种方式对响应体进行处理
MIME 类型 | 描述 |
---|---|
text/plain | 纯文本 |
text/html | HTML 文档 |
text/xml | XML 文档 |
Application/x-msdownload | 需要下载的资源 |
image/jpeg image/gif image/... | 图片资源 |
请求转发与重定向
多个 Servlet(JSP)之间跳转有两种方式
- 请求转发:
request.getRequestDispatcher("/direct/index").forward()
- 服务器跳转,只会产生一次请求
- 响应重定向:
response.sendRedirect("/servlet_advanced/direct/index")
- 浏览器端跳转,会产生两次请求
Cookie
浏览器保存在本地的文本内容
- 常用于保存登录状态、用户资料等小文本
- Cookie 具有时效性,Cookie 内容会伴随请求发送给 Tomcat
- 默认时限为浏览器打开状态,浏览器退出后 Cookie 消失
// 获取 Cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
System.out.println(cookie.getName() + ":" + cookie.getValue());
}
// 设置 Cookie
Cookie cookie = new Cookie("user", "admin");
cookie.setMaxAge(60*60*24*7); // 设置 Cookie 有效期(秒)
response.addCookie(cookie);
Session
用户会话,用于保存与 “浏览器窗口” 对应的数据
- 存储在 Tomcat 服务器的内存中,具有时效性
- 没有人访问时,时效为 30 分钟
- 通过浏览器 Cookie 的 SessionId 值提取用户数据
// 获取 session
HttpSession session = request.getSession();
String sessionId = session.getId(); // 获取 SessionId
response.setContentType("text/html;charset=utf-8"); // 设置字符编码方式
String name = (String) session.getAttribute("name");
response.getWriter().println("<div>SessionId:" + sessionId + "</div>");
response.getWriter().println("name:" + name);
// 设置 session
HttpSession session = request.getSession();
session.setAttribute("name", "张三");
request.getRequestDispatcher("/session/index").forward(request, response);
Ajax
/* onreadystatechange():监听 Ajax 执行过程
* status:服务器响应状态码
* 200:成功
* 404:未找到
* readyState:说明 XMLHttpRequest 当前状态
* 0:请求未初始化
* 1:服务器连接已建立
* 2:请求已被接受
* 3:请求正在处理
* 4:响应文本已被接受
*/
// 创建 XMLHttpRequest 对象
var xmlhttp
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest()
} else {
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
}
// 发送 Ajax 请求
xmlhttp.open('GET', 'http://localhost:8080/jquery/content')
xmlhttp.send()
// 处理服务器响应
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// 获取响应体文本
var responseText = xmlhttp.responseText
// 对服务器结果进行处理
console.log(responseText)
}
}
// JQuery
$.ajax({
url: 'http://localhost:8080/jquery/news_list',
type: 'GET',
dataType: 'json',
success: function (result) {
console.log(result)
}
})
过滤器
过滤器(Filter):是 J2EE Servlet 模块下的组件
- 对 URL 请求进行统一的拦截处理
- 通常用于应用程序层面进行全局处理
三要素
- 任何过滤器都要实现
javax.servlet.Filter
接口 - 在
Filter
接口的doFilter()
方法中便携过滤器的功能代码 - 在
web.xml
中对过滤器进行配置,说明拦截URL
的范围
// 过滤器
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyFirstFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("过滤器已生效");
// 将请求和响应对象随着过滤链依次传递
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
<!-- web.xml -->
<!-- filter 用于说明哪个类是过滤器,并在应用启动时自动加载 -->
<filter>
<filter-name>MyFirstFilter</filter-name>
<filter-class>com.imooc.filter.MyFirstFilter</filter-class>
</filter>
<!--
filter-mapping 标签用于说明过滤器对 URL 应用的范围,要点有二:
1. filter-name:过滤器名称要与 filter.filter-name 保持一致
2. url-pattern:说明过滤器的作用范围,/* 表示对所有的 URL 进行过滤
-->
<!-- filter-mapping 可以写多个,对同一个类设置多个作用范围 -->
<filter-mapping>
<filter-name>MyFirstFilter</filter-name>
<!-- 对所有请求进行拦截 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
生命周期
Tomcat
启动,web
应用被加载初始化(过滤器对象被 Tomcat 创建)-
Filter.init()
,创建之后,长期存在于Tomcat
内存中提供服务 -
Filter.doFilter()
销毁(web 应用重启或关闭) -
Filter.destory()
特性
- 过滤器对象在 Web 应用启动时被创建且全局唯一
- 唯一的过滤器对象在并发环境中采用
多线程
提供服务
开发方式
建议尽量选一种,不然后期会变得难以维护
- 配置形式:在
web.xml
进行配置- 维护性好,适合应用全局过滤
- 注解形式:
@WebFilter(filterName="MyFilterName",urlPatterns="/*")
- 开发体验好,适用于小型项目敏捷开发
字符编码过滤器
ServletRequest
为请求最顶层抽象RequestFacade
是Tomcat
的接口实现类
![](https://cdn.jsdelivr.net/gh/sunzhenyang/blog-img/img/20210519233916.png)
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CharacterEncodingFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
req.setCharacterEncoding("UTF-8");
HttpServletResponse res = (HttpServletResponse) response;
res.setContentType("text/html;charset=UTF-8");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
过滤器参数化
过滤器为了增强灵活性,允许配置信息放在
web.xml
中,使用<init-param>
设置过滤器参数
配置形式
<!-- filter 用于说明哪个类是过滤器,并在应用启动时自动加载 -->
<!--
filter-mapping 标签用于说明过滤器对 URL 应用的范围,要点有二:
1. filter-name:过滤器名称要与 filter.filter-name 保持一致
2. url-pattern:说明过滤器的作用范围,/* 表示对所有的 URL 进行过滤
-->
<filter>
<filter-name>MyFirstFilter</filter-name>
<filter-class>com.imooc.filter.MyFirstFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>p1</param-name>
<param-value>v1</param-value>
</init-param>
<init-param>
<param-name>p2</param-name>
<param-value>v2</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFirstFilter</filter-name>
<!-- URL模式映射,对所有请求进行拦截 -->
<url-pattern>/*</url-pattern>
<!-- Servlet名称映射 -->
<servlet-name>AdviceServlet</servlet-name>
<!-- dispatcher 请求分派,默认为 REQUEST -->
<!--
可以有 0 ~ 4 个 dispatcher 元素
REQUEST:表示对客户请求启用过滤器
INCLUDE:表示对由一个 include() 调用分派来的请求启用过滤器
FORWARD:表示对由一个 forward() 调用分派来得请求启用过滤器
ERROR:表示对错误处理器调用的资源启用过滤器
-->
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CharacterEncodingFilter implements Filter {
private String encoding;
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
req.setCharacterEncoding(encoding);
HttpServletResponse res = (HttpServletResponse) response;
res.setContentType("text/html;charset=" + encoding);
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
encoding = filterConfig.getInitParameter("encoding");
System.out.println(encoding);
}
}
注解形式
// 单个作用范围
@WebFilter(filterName="MyFilterName",urlPatterns="/*",initParams={
@WebInitParam(name="encoding", value="UTF-8"),
@WebInitParam(name="p1", value="v1"),
@WebInitParam(name="p2", value="v2")
})
// 多个作用范围
@WebFilter(filterName="MyFilterName",urlPatterns={
"/*",
"*.jsp"
},initParams={
@WebInitParam(name="encoding", value="UTF-8"),
@WebInitParam(name="p1", value="v1"),
@WebInitParam(name="p2", value="v2")
})
过滤范围
- 常用写法
/index.jsp
:执行资源精确匹配/servlet/*
:以前缀进行模糊匹配*.jsp
:以后缀进行模糊匹配
/
映射问题/
:指映射 Web 应用根路径,且只对Servlet
生效- 默认首页
index.jsp
会让/
失效 /
和/*
不同,前者指向根路径,后者代表所有
过滤链
注意事项
- 每一个过滤器应具有单独职能
- 过滤器的执行顺序以
<filter-mapping>
为准 - 调用
chain.doFilter()
将请求向后传递
多端适配过滤器
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DeviceAdapterFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
if (uri.startsWith("/desktop") || uri.startsWith("/mobile")) {
chain.doFilter(request, response);
} else {
String userAgent = req.getHeader("user-agent");
String targetURI = "";
if (userAgent.indexOf("android") != -1 || userAgent.indexOf("iphone") != -1) {
targetURI = "/mobile" + uri;
} else {
targetURI = "/desktop" + uri;
}
res.sendRedirect(targetURI);
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
监听器
是 J2EE Servlet 模块下的组件,对 Web 应用对象的行为进行监控
监听对象
ServletContext
:对全局ServletContent
及其属性进行监听HttpSession
:对用户会话及其属性操作进行监听ServletRequest
:对请求及属性操作进行监听
三要素
- 实现
xxxListerer
接口,不同接口对应不同监听对象- 内置对象监听接口
ServletContextlistener
:监听ServletContext
对象的创建和销毁等操作HttpSessionListener
:监听HttpSession
对象创建和销毁等操作ServletRequestListener
:监听ServletRequest
对象创建和销毁等操作
- 属性监听接口
ServletContextAttributeListener
:监听全局属性操作HttpSessionAttributeListener
:监听用户会话属性操作ServletRequestAttributeListener
:监听请求属性操作
- 内置对象监听接口
- 实现每个接口中独有的方法,实现触发监听的后续操作
- 配置方法
- 在
web.xml
中配置<listener>
使监听器生效 @WebListener
- 在
<web-app>
<listener>
<listener-class>com.imooc.listener.FirstListener</listener-class>
</listener>
</web-app>
监听器实现
内置对象监听
// WebListener
package com.imooc.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class WebListener implements ServletContextListener,HttpSessionListener,ServletRequestListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
System.out.println("ServletContext已初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
System.out.println("ServletContext已被销毁");
}
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
// TODO Auto-generated method stub
System.out.println("Session已被创建,SessionId:" + session.getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// TODO Auto-generated method stub
System.out.println("Session已被销毁");
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
// TODO Auto-generated method stub
System.out.println("HttpServletRequest已被销毁");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
// TODO Auto-generated method stub
System.out.println("HttpServletRequest已被创建,URI:" + request.getRequestURI());
}
}
属性监听
// WebAttributeListener
package com.imooc.listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class WebAttributeListener implements ServletContextAttributeListener,HttpSessionAttributeListener ,ServletRequestAttributeListener{
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
// TODO Auto-generated method stub
System.out.println("ServletContext新增属性:" + event.getName() + "->" + event.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
// TODO Auto-generated method stub
}
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
// TODO Auto-generated method stub
}
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
System.out.println("HttpSession新增属性:" + event.getName() + "->" + event.getValue());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
}
@Override
public void attributeAdded(ServletRequestAttributeEvent srae) {
// TODO Auto-generated method stub
System.out.println("Request新增属性:" + srae.getName() + "->" + srae.getValue());
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent srae) {
// TODO Auto-generated method stub
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent srae) {
// TODO Auto-generated method stub
}
}
web.xml 配置
<listener>
<listener-class>com.imooc.listener.WebListener</listener-class>
</listener>
<listener>
<listener-class>com.imooc.listener.WebAttributeListener</listener-class>
</listener>
测试
// HelloServlet
package com.imooc.listener;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class HelloServlet
*/
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public HelloServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().println("Hello World!");
request.getServletContext().setAttribute("sc-attr1", "sc-attr-value1");
request.getServletContext().removeAttribute("sc-attr1");
request.getSession().setAttribute("session-attr1", "session-attr-value1");
request.setAttribute("request-attr1", "request-attr-value1");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
常见问题
端口占用
检查 8080 端口占用情况:
lsof -i :8080
请求乱码
请求中的乱码
// GET (Tomcat 8.x 版本,默认 GET 请求发送中文就是 UTF-8 格式)
// server.xml 中设置 URIEncoding( tomcat -> conf -> server.xml )
<Connector URIEncoding="UTF-8" />
// POST 乱码处理
request.setCharacterEncoding("UTF-8"); // 设置请求体字符集编码
响应中的乱码
response.setContentType("text/html;charset=utf-8");
JSON
JavaScript Object Notation( JavaScript 对象表示法 )
- 轻量级的文本数据交换格式
- 独立于语言,具有自我描述性,更易理解
JavaScript 与 JSON
JSON.stringify(jsonObj)
:将 JSON 对象转换为字符串JSON.parse(jsonStr)
:将 JSON 字符串转换为对象
Java 与 JSON
工具包
FastJson
Jackson
:国外老牌工具包Gson
:谷歌开发Json-lib
:开源平台的明星工具包
FastJson
阿里巴巴开发的著名 JSON 序列化与反序列化工具包
例子
// Employee.java
package com.imooc.jstl;
import java.util.Date;
import com.alibaba.fastjson.annotation.JSONField;
public class Employee {
private Integer empno;
private String ename;
private String job;
// 设置序列化名称,格式化字符串
@JSONField(name = "hiredate", format = "yyyy-MM-dd")
private Date hdate;
private Float salary;
// serialize 不对 dname 进行序列化
@JSONField(serialize = false)
private String dname;
public Integer getEmpno() {
return empno;
}
public void setEmpno(Integer empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Date getHdate() {
return hdate;
}
public void setHdate(Date hdate) {
this.hdate = hdate;
}
public Float getSalary() {
return salary;
}
public void setSalary(Float salary) {
this.salary = salary;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
// FastJsonSample1.java
package com.imooc.jstl;
import java.util.Calendar;
import com.alibaba.fastjson.JSON;
public class FastJsonSample1 {
public static void main(String[] args) {
Employee employee = new Employee();
employee.setEmpno(4488);
employee.setEname("王晓东");
employee.setJob("客户经理");
employee.setSalary(10000f);
employee.setDname("市场部");
Calendar c = Calendar.getInstance();
c.set(2019, 0, 30, 0, 0, 0);
employee.setHdate(c.getTime());
// 序列化
String json = JSON.toJSONString(employee);
System.out.println(json);
// 反序列化
Employee emp = JSON.parseObject(json, Employee.class);
System.out.println("Empno:" + emp.getEmpno());
System.out.println("Ename:" + emp.getEname());
System.out.println("Job:" + emp.getJob());
}
}
// FastJsonSample2.java
package com.imooc.jstl;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
public class FastJsonSample2 {
public static void main(String[] args) {
List emplist = new ArrayList();
for (int i = 1; i <= 100; i++) {
Employee employee = new Employee();
employee.setEmpno(4488 + i);
employee.setEname("员工 " + i);
emplist.add(employee);
}
// 序列化
String json = JSON.toJSONString(emplist);
System.out.println(json);
// 反序列化
List<Employee> emps = JSON.parseArray(json, Employee.class);
for (Employee e : emps) {
System.out.println(e.getEname() + ":" + e.getEmpno());
}
}
}
ServletContext
Web 应用全局对象
- 一个 Web 应用只会创建一个 ServletContext 对象
- ServletContext 随着 Web 应用启动而自动创建,随着 Web 应用的重启或者关闭而销毁
// 获取 ServletContext
ServletContext context = request.getServletContext();
String copyright = (String) context.getAttribute("copyright");
String title = (String) context.getAttribute("title");
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<h1>" + copyright + "</h1>" + title);
// 设置 ServletContext
ServletContext context = request.getServletContext();
context.setAttribute("copyright", "© 2021 imooc.com 京ICP备 12003892号-11");
context.setAttribute("title", "慕课网-程序员的梦工厂");
response.getWriter().println("Init success");
web.xml 常用配置
默认首页
<!-- 按顺序检查文件是否存在 -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
启动时加载 Servlet
<load-on-startup>
:大于0
就会在部署时或服务器启动时初始化,而不需要等到第一个请求到来- 如果预加载多个 Servle,可根据
<load-on-startup>
值的决定顺序
<servlet>
<servlet-name>DemoTest</servlet-name>
<servlet-class>com.example.web.DemoTest</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
初始化参数
init-param
- 定义在
<servlet>
标签中 - 只能由
<servlet-class>
中书写的类调用 - 容器初始化一个
Servlet
时,会为这个Servlet
从创建一个唯一的ServletConfig
,容器从 XML 文档中读出初始化参数,并把这些参数交给ServletConfig
,然后把ServletConfig
传递给Servlet
的Init()
方法
<servlet>
<servlet-name>DemoTest</servlet-name>
<servlet-class>com.example.web.DemoTest</servlet-class>
<init-param>
<param-name>email</param-name>
<param-value>874530670@qq.com</param-value>
</init-param>
</servlet>
// com.example.web.DemoTest
String email = getServletConfig().getInitParameter("email");
context-param
- 定义在
<web-app>
标签中 - 全局可使用
<!-- web.xml -->
<context-param>
<param-name>title</param-name>
<param-value>标题</param-value>
</context-param>
String title = getServletContext().getInitParameter("title");
// 或
ServletContext context = getServletContext();
String title = context.getInitParameter("title");
// 或
String title = this.getServletContext().getInitParameter("title");
// 或( ServletConfig 对象有该 Servlet 的 ServletContext 的和一个引用)
String title = getServletConfig().getServletContext().getInitParameter("title");
会话配置
超时
<!-- 单位:分钟 -->
<session>
<session-timeout>15</session-timeout>
</session>
错误页面
固定状态码
<!-- web.xml -->
<error-page>
<error-code>500</error-code>
<location>/error/500.html</location>
</error-page>
固定错误
<!-- web.xml -->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.html</location>
</error-page>
Java Web 三大作用域对象
- 请求对象:
HttpServletRequest
- 用户会话对象:
HttpSession
- Web 应用全局对象:
ServletContext
生命周期
- 装载
web.xml
- 创建 - 执行
构造函数
- 初始化 -
init()
- 提供服务 -
service()
- 销毁 -
destory()
启动时加载
web.wml -> <servlet>
中使用<load-on-start>
设置启动加载<load-on-start>0~999</load-on-start>
- 启动时加载在工作中常用与系统的预处理
- 执行对应类的
init()
函数 - 注解方式:
@WebServlet(urlPatterns="/unused", loadOnStartup=2)
注解
import javax.servlet.annotation.WebServlet;
@WebServlet("/anno")
public class FirstServlet extends HttpServlet {}
// 启动时加载
@WebServlet(urlPatterns="/unused", loadOnStartup=2)