跳至主要內容

Servlet

Yang大约 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

开发步骤

  • 创建 Servlet 类,继承 HttpServlet
  • 重写 service 方法,编写程序代码
    • service 方法可同时处理 GETPOST 请求
    • 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"):设置 ContentType
  • response.sendError(404):生成错误

HTTP 常见状态码

  • 1xx:信息提示,表示临时的响应
  • 2xx:响应成功,表明服务器成功的接受了客户端的请求
  • 3xx:重定向
  • 4xx:客户端错误,表名客户端可能有问题
  • 5xx:服务器错误,表明服务期由于遇到某种错误而不能响应客户请求
状态码错误描述
200服务器处理(响应)成功
301、302请求重定向
400无效(错误)的请求,客户端发送的 HTTP 请求不正确
401未经过授权
403服务器拒绝访问
404文件不存在,在服务器上没有客户要求访问的文档
405服务器不支持客户的请求方式
500服务器内部错误
503服务器超负载或正停机维护,无法处理请求

ContentType

决定浏览器采用何种方式对响应体进行处理

MIME 类型描述
text/plain纯文本
text/htmlHTML 文档
text/xmlXML 文档
Application/x-msdownload需要下载的资源
image/jpeg
image/gif
image/...
图片资源

请求转发与重定向

多个 Servlet(JSP)之间跳转有两种方式

  • 请求转发:request.getRequestDispatcher("/direct/index").forward()
    • 服务器跳转,只会产生一次请求
  • 响应重定向:response.sendRedirect("/servlet_advanced/direct/index")
    • 浏览器端跳转,会产生两次请求

浏览器保存在本地的文本内容

  • 常用于保存登录状态、用户资料等小文本
  • 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 为请求最顶层抽象
  • RequestFacadeTomcat 的接口实现类
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 传递给 ServletInit() 方法
<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)
上次编辑于:
贡献者: sunzhenyang