Servlet教程
- 1、JAVAEE简介
- 2、Servlet简介
- 3、服务器
- 4、Servlet技术
- 5、Cookie 对象与 HttpSession 对象
- 6、自启动 Servlet
- 7、Servlet 线程安全问题
- 8、Servlet 的 url-pattern 配置
- 9、基于注解式开发 Servlet
- 10、文件上传
- 11、Filter 过滤器
- 12、Listener监听器
- 13、Filter 与 Listener 设计模式
1、JAVAEE简介
2、Servlet简介
2.1 Servlet技术特点
2.2 Servlet在应用程序中的位置
3、服务器
3.1 JavaEE应用服务器(JavaEE Application Server)
3.2 Web容器(Web Server)
3.2.1 Tomcat的使用
3.2.1.1 Tomcat 安裝和配置
3.2.1.2 Tomcat 目录结构
3.2.1.2.1 bin
3.2.1.2.2 conf
3.2.1.2.3 lib
3.2.1.2.4 logs
3.2.1.2.5 temp
3.2.1.2.6 webapps
3.2.1.2.7 work
3.2.1.3 Tomcat 启动与关闭
3.2.1.3.1 Tomcat启动
3.2.1.3.2 Tomcat关闭
- 方式一:
- 方式二:
3.2.1.3.3 访问Tomcat
3.2.2 Tomcat 的配置
3.2.2.1 Tomcat 的配置文件介绍
3.2.2.1.1 context.xml
3.2.2.1.2 web.xml
3.2.2.1.3 server.xml
3.2.2.1.4 tomcat-users.xml
3.2.2.2 解决控制台乱码
3.2.2.3 修改Tomcat监听端口
3.2.2.4 配置Tomcat Manager
3.2.2.4.1 配置Tomcat Manger 的访问用户
- manager-gui 角色
- manager-script 角色
- manager-jmx 角色
- manager-status 角色
- conf\tomcat-users.xml 配置用户角色
热部署:是在tomcat的启动情况下,进行部署
3.2.3 Tomcat工作原理
3.2.3.1 Tomcat 作用
3.2.3.2 Tomcat 运行原理
3.2.4 Tomcat架构
3.2.5 Tomcat组件
3.2.5.1 Server组件
3.2.5.2 Service组件
3.2.5.3 Connector组件
3.2.5.4 Engine组件
3.2.5.5 Host组件
3.2.5.6 Context组件
3.2.6 Tomcat处理请求过程
3.2.7 在Tomcat中配置虚拟主机(Host)
3.2.7.1 需求
3.2.7.2 创建页面
3.2.7.3 修改server.xml添加Host配置
3.2.7.4 添加Context配置
3.2.7.5 修改windows的Host文件
3.2.7.5.1 Host文件位置
3.2.7.5.2 修改内容
3.2.7.5.3 访问资源测试结果
4、Servlet技术
4.1 Servlet 版本
Servlet4.0、Tomcat9以上、JDK8以上
4.2 创建第一个Servlet案例
4.2.1 创建Servlet
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloWorld extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse) throws ServletException,IOException{
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE html>");
out.println("<HTML>");
out.println("<HEAD><TITLE>AABB</TITLE></HEAD>")
out.println("<BODY>");
out.println("<font color=blue>Hello World</font>");
out.println("</BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
}
4.2.2 编译Servlet
- 在编译的时候,需要在tomcat的libservlet-api.jar下编译,是由于引入了servlet-api的包,这样才能编译通过
4.2.3 创建web.xml
4.2.3.1 web.xml文件中的头信息
4.2.3.2 web.xml文件中配置Servlet
<?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_4_0.xsd"
version="4.0">
<servlet>
<!-- 名字随便取,但要见名知意 -->
<servlet-name>helloworld</servlet-name>
<!-- servlet全名 -->
<servlet-class>com.test.servlet.HelloWorld</servlet-class>
</servlet>
<!-- 与Servlet映射 -->
<servlet-mapping>
<servlet-name>helloworld</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
4.2.4 部署Servlet
4.2.4.1 Web工程目录结构
4.2.4.2 访问servlet与测试结果
4.3 Servlet继承结构
4.3.1 Servlet接口
4.3.2 ServletConfig接口
4.3.3 GenericServlet抽象类
4.3.4 HttpServlet
4.4 Servlet的生命周期
4.5 Servlet处理请求的原理
4.6 Servlet的使用
4.7 Idea中开发Servlet
4.7.1 创建Web工程
4.7.1.1 创建java项目
4.7.1.2 创建web工程
4.7.1.3 web工程目录结构
- servlet-api.jar在tomcat的lib目录中
- idea:File---->Project Structure---->Libraries---->
+
---->Java---->选择tomcat的lib下的servlet-api.jar导入即可
4.7.1.4 配置Tomcat
4.7.2 Web项目部署
4.7.2.1 默认部署方式
-
idea会在CATALINA_BASE的路径下创建一个独立的Tomcat副本
-
会在…\tomcat\11e7605d-34df-4b7b-82f2-b2790096ea5c\conf\Catalina\localhost目录中生成一个改项目的xml文件名称为:“项目名.xml”
-
在xml文件中指定web项目编译后的artifacts目录的位置
4.7.2.2 web项目部署到Tomcat的webapps中
- idea:File---->Project Structure---->Artifacts---->Output directory
4.8 HttpServletRequest对象
4.8.1 获取请求信息
4.8.2 获取请求数据
4.8.2.1 在Servlet获取请求数据的方式
4.8.2.2 获取复选框(checkbox组件)中的值
4.8.2.3 获取所有提交数据的 key
4.8.2.4 使用 Map 结构获取提交数据
4.8.3 设置请求编码
4.8.4 资源访问方式
4.8.4.1 绝对路径
4.8.4.2 相对路径
- 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_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>demoServlet</servlet-name>
<servlet-class>com.test.servlet.DemoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demoServlet</servlet-name>
<url-pattern>/demo.do</url-pattern>
</servlet-mapping>
</web-app>
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Servlet</title>
</head>
<body>
<!--action="demo.do" 跟的是相对路径 action="/demo.do" 跟的是绝对路径-->
<form action="demo.do" method="post">
用户名:<input type="text" name="username">
<input type="submit" value="ok">
用户爱好:<input type="checkbox" name="userlike" value="sport">体育
<input type="checkbox" name="userlike" value="music">音乐
</form>
</body>
</html>
- 类DemoServlet
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class DemoServlet extends HttpServlet {
// 获取请求信息
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("<body>");
// 获取请求信息
StringBuffer requestURL = req.getRequestURL();
String requestURI = req.getRequestURI();
String remoteAddr = req.getRemoteAddr();
out.println("URL:" + requestURL + "\t" + "URI:" + requestURI + "\t" + "remoteAddr:" + remoteAddr);
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
// 获取请求数据
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("<body>");
req.setCharacterEncoding("utf-8"); // 让请求对象解析出来的结果重新按照新的编码方式解析,只解决请求的中文乱码问题,但响应的乱码问题依然存在
// 获取请求数据
String username = req.getParameter("username");
// username = new String(username.getBytes("iso-8859-1"),"utf-8"); // 只解决了控制台打印的中文乱码问题,但响应中文乱码未解决
System.out.println(username);
out.println("username:" + username + "<br>");
// 获取复选框(checkbox组件)中的值
String[] userlikes = req.getParameterValues("userlike");
List<String> strings = Arrays.asList(userlikes);
out.println("username:" + strings + "<br>");
// 获取所有提交数据的 key
Enumeration<String> parameterNames = req.getParameterNames();
List<String> keys = new ArrayList<>();
while (parameterNames.hasMoreElements()) {
keys.add(parameterNames.nextElement());
}
out.println("keys:" + keys + "<br>");
// 使用 Map 结构获取提交数据
Map<String, String[]> parameterMap = req.getParameterMap();
Iterator<Map.Entry<String, String[]>> iterator = parameterMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String[]> entry = iterator.next();
out.println("keys:" + entry.getKey() + " values:" + Arrays.asList(entry.getValue()));
}
// 获取请求头
String header = req.getHeader("Accept-Language");
// 获取请求头中所有的key,该方法返回乜距类型
Enumeration<String> headerNames = req.getHeaderNames();
out.println("Header:" + header + "<br>");
// 获取请求头Accept-Language的值,可做语言识别
if (header.indexOf("zh-CN") != -1) {
out.println("您好!!!");
} else if (header.indexOf("en-US") != -1) {
out.println("Hello");
} else {
out.println("sorry");
}
while (headerNames.hasMoreElements()) {
String key = headerNames.nextElement();
String value = req.getHeader(key);
out.println("key:" + key + " value:" + value + "<br>");
}
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
}
4.8.5 获取请求头信息
4.8.6 HttpServletRequest 对象的生命周期
4.8 HttpServletResponse 对象
4.8.1 设置响应类型
4.8.1.1 设置字符型响应
4.8.1.2 设置字节型响应
4.8.2 设置响应编码
- 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_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>respCharacterServlet</servlet-name>
<servlet-class>com.test.servlet.RespCharacterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>respCharacterServlet</servlet-name>
<url-pattern>/char.do</url-pattern>
</servlet-mapping>
</web-app>
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class RespCharacterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// =====================字符响应类型===============================
// 默认的响应类型"text/html"
// 设置普通文本响应类型
// 给响应头设置字符编码,客户端/服务端的字符编码都设置了,解决乱码更彻底一些
resp.setContentType("text/plain;charset=utf-8");
// 设置字符编码
// resp.setCharacterEncoding("utf-8");
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("您好!!!");
out.println("<body>");
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
// =====================字节响应类型===============================
// 读取图片文件
// File file = new File("C:\\img\\1.png");
// FileInputStream fis = new FileInputStream(file);
// byte[] buf = new byte[fis.available()];
// fis.read(buf);
// // 设置响应类型
// resp.setContentType("image/png");
// // HttpServletResponse对象中获取字节输出流对象
// OutputStream os = resp.getOutputStream();
// os.write(buf);
// os.flush();
// os.close();
// fis.close();
}
}
4.8.3 在响应中添加附加信息
4.8.3.1 重定向响应
4.8.3.2 文件下载
4.8.3.3 解决文件名中文乱码问题
4.9 ServletContext对象
4.9.1 ServletContext 对象的作用
4.9.2 ServletContext 对象的使用
4.9.2.1 相对路径转绝对路径
4.9.2.2 获取容器的附加信息
4.9.2.3 获取 web.xml 文件中的信息
4.9.2.4 全局容器
4.9.3 ServletContext 对象生命周期
4.10 ServletConfig 对象
- 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_4_0.xsd"
version="4.0">
<context-param>
<param-name>key1</param-name>
<param-value>AAA1</param-value>
</context-param>
<context-param>
<param-name>key2</param-name>
<param-value>AAA2</param-value>
</context-param>
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.test.servlet.TestServlet</servlet-class>
<init-param>
<param-name>servletConfig_key1</param-name>
<param-value>servletConfig_AAA1</param-value>
</init-param>
<init-param>
<param-name>servletConfig_key2</param-name>
<param-value>servletConfig_AAA2</param-value>
<init-param>
<param-name>path</param-name>
<param-value>image</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/servlet.do</url-pattern>
</servlet-mapping>
</web-app>
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
/**
* 自启动Servlet
*/
public class AutoStartServlet extends HttpServlet {
@Override
public void init() throws ServletException {
ServletConfig servletConfig = this.getServletConfig();
String value = servletConfig.getInitParameter("path");
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("path",value);
}
}
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* 重定向响应
*/
// req.setCharacterEncoding("utf-8");
// String search = req.getParameter("search");
// // 在URL(地址栏)需要对中文进行编码处理
// resp.sendRedirect("https://www.baidu.com/s?wd="+ URLEncoder.encode(search, "utf-8")/*中文字符做编码处理*/);
/**
* 文件下载
*/
// 获取ServletContext对象
// ServletContext servletContext = this.getServletContext();
// String path = servletContext.getAttribute("path")
// // 路径转换
// String realPath = servletContext.getRealPath(path + "/1.png");
// System.out.println(realPath);
// // 读文件
File file = new File("c:/img/你好.png");
// File file = new File(realPath);
// System.out.println(file.getName());
// FileInputStream fis = new FileInputStream(file);
// byte[] buf = new byte[fis.available()];
// fis.read(buf);
//
// // 在响应头添加附加信息
// // 文件名是中文,需要做字符编码处理
// resp.addHeader("Content-Disposition","attachment;filename=" + new String(file.getName().getBytes("utf-8"),"iso-8859-1"));
// OutputStream os = resp.getOutputStream();
// os.write(buf);
// os.flush();
// os.close();
/**
* 获取容器的附加信息
*/
// 获取ServletContext对象
// ServletContext servletContext = this.getServletContext();
// // 设置响应的字符编码
// resp.setContentType("text/html;charset=utf-8");
// // 获取Servlet容器的名称和版本号
// String servletInfo = servletContext.getServerInfo();
// int majorVersion = servletContext.getMajorVersion();
// int minorVersion = servletContext.getMinorVersion();
// PrintWriter out = resp.getWriter();
// out.println("<!DOCTYPE html>");
// out.println("<html lang=\"en\">");
// out.println("<head>");
// out.println("<title>Hello Servlet</title>");
// out.println("</head>");
// out.println("<body>");
// out.println("Servlet容器的名称和版本: " + servletInfo + "\nServlet的主版本:" + majorVersion + "\nServlet的副版本" + minorVersion);
// out.println("</body>");
// out.println("</html>");
// out.flush();
// out.close();
/**
* ServletContext对象读取web.xml文件中的信息
*/
// 设置响应的字符编码
// resp.setContentType("text/html;charset=utf-8");
// // 获取ServletContext对象
// ServletContext servletContext = this.getServletContext();
// Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
// PrintWriter out = resp.getWriter();
// out.println("<!DOCTYPE html>");
// out.println("<html lang=\"en\">");
// out.println("<head>");
// out.println("<title>Hello Servlet</title>");
// out.println("</head>");
// out.println("<body>");
// while (initParameterNames.hasMoreElements()) {
// String name = initParameterNames.nextElement();
// out.println("获取context-param中的name:" + name + " value:" + servletContext.getInitParameter(name));
// }
// out.println("</body>");
// out.println("</html>");
// out.flush();
// out.close();
/**
* 全局容器
*/
// 获取ServletContext对象
// ServletContext servletContext = this.getServletContext();
// servletContext.setAttribute("key1","BBB1");
// servletContext.setAttribute("key2","BBB2");
// PrintWriter out = resp.getWriter();
// out.println("<!DOCTYPE html>");
// out.println("<html lang=\"en\">");
// out.println("<head>");
// out.println("<title>Hello Servlet</title>");
// out.println("</head>");
// out.println("<body>");
// String value1 = (String)servletContext.getAttribute("key1");
// String value2 = (String)servletContext.getAttribute("key2");
// out.println("value1:" + value1 + "<br>" +"value2:" + value2);
// out.println("</body>");
// out.println("</html>");
// out.flush();
// out.close();
// 获取ServletConfig对象
ServletConfig servletConfig = this.getServletConfig();
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("<body>");
while (initParameterNames.hasMoreElements()) {
String name = initParameterNames.nextElement();
out.println("name:" + name + "<br>" + "value:" + servletConfig.getInitParameter(name)+ "<br>");
}
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
}
5、Cookie 对象与 HttpSession 对象
5.1 Cookie 对象
5.1.1 Cookie 对象的特点
5.1.2 Cookie 对象的创建
5.1.3 获取 Cookie 中的数据
5.1.4 解决 Cookie 不支持中文
5.1.5 Cookie跨域问题
5.1.6 状态 Cookie 与持久化 Cookie
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建Cookie对象
// Cookie cookie = new Cookie("name", "hello");
// resp.addCookie(cookie);
// 创建Cookie对象
// Servlet4.0之前的版本是不支持的中文,需要对中文做编码处理
Cookie cookie = new Cookie("name",URLEncoder.encode("你好","utf-8"));
// 设置Cookie的失效时间,一旦设置了失效时间,该Cookie就持久化了
cookie.setMaxAge(60);
resp.addCookie(cookie);
// 由于Cookie有中文,需要对字符进行编码处理
resp.setContentType("text/html;charset=utf-8");
// 获取Cookie对象
Cookie[] cookies = req.getCookies();
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("<body>");
for (int i = 0; i < cookies.length; i++) {
Cookie cookiee = cookies[i];
// Servlet4.0之前版本是不支持中文,需要对字符做解码处理
out.println("name:" + cookiee.getName() + "<br>" + "value:" + URLDecoder.decode(cookiee.getValue(),"utf-8") + "<br>");
}
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
}
5.1.7 通过 Cookie 实现客户端与服务端会话的维持
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取Cookie
Cookie[] cookies = req.getCookies();
boolean flag = false;
if (cookies != null) {
for (Cookie cookie:cookies) {
if ("first".equals(cookie.getName())) {
flag = true;
}
}
}
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("<body>");
if (flag) {
// flag: true 表示第二次访问
out.print("欢迎您回来!");
} else {
// flag: false 表示第一次访问,创建Cookie
out.print("您好,欢迎您第一次访问!");
Cookie cookie = new Cookie("first","first");
cookie.setMaxAge(60);
resp.addCookie(cookie);
}
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
}
5.1.8 Cookie 总结
5.2 HttpSession 对象
5.2.1 HttpSession 对象的特点
5.2.2 HttpSession 对象的使用
5.2.2.1 HttpSession 对象的创建
5.2.2.2 获取 HttpSession 中的数据
5.2.2.3 HttpSession 的销毁方式
5.2.2.4 通过 HttpSession 实现客户端与服务端会话的维持
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 使用HttpSession对象维持客户端与服务端的会话状态
*/
public class WelcomeSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession(false);
boolean flag = true;
if (session == null) {
flag = false;
session = req.getSession(true);
}
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("<body>");
if (flag) {
out.print("欢迎您回来!");
} else {
out.print("您好,欢迎您第一次访问!");
}
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
}
5.2.2.5 HttpSession 生命周期
5.2.2.6 HttpSession 对象总结
5.2.2.6.1 HttpSession 与 Cookie 的区别
5.2.2.6.2 HttpSession 的使用建议
5.2.2.6.3 HttpSession 与 Cookie 的总结
- cookie是由服务器端创建(new Cookie()),存储在客户端浏览器上的文件,用来跟踪客户端和服务器之间的会话,cookie的安全性能较低,并且存储的最大数据不能超过4k。
- 不支持跨一级域名访问,但是可以跨二级域名访问。
- 分为状态cookie和持久化cookie,
- 状态cookie会在用户关闭浏览器时自动销毁。
- 持久化cookie存储在用户硬盘中,设置的失效时间,到达时间后,系统会自动删除该文件,导致持久化cookie失效。
- session时在服务器创建并存储在服务器上的,创建时间取决于我们什么时候调用getSession()或getSession(true)方法。安全性能较高。
- 原则上session的存储大小不受限制,但是因为会占用服务器内存,如果session数量级过大,对服务器性能有影响。
- session的销毁形式有两种,调用invalidate()方法和设置失效时间,
- cookie和session的关系:
session对象创建后,会生成一个sessionID放到cookie中,客户端每次向服务器端发出请求时,会把所有的请求信息和sessionID放到cookies中发送到服务器端,服务器端通过解析cookie对象,如果包含sessionID,服务器端会将和sessionID向对应的session取出。如果没有对应的session ID,服务器端会重新创建一个session对象。因为cookie记录着sessionID,如果cookie被销毁,服务器端对应的session将失效。因为cookie中的sessioID被销毁,客户端下次请求时就不再是之前的sessionID,而服务器端存储的仍然是之前的sessionID及session信息,所以无法找到相对应的session文件。
6、自启动 Servlet
- 必须是整数,整数越小,自启动的优先级越高
7、Servlet 线程安全问题
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Servlet线程安全问题
*/
public class ThreadSafeServlet extends HttpServlet {
// 定义成员变量,会造成线程安全问题
private PrintWriter pw;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
// 加锁解决了线程安全,因此两个不同浏览器都会有结果返回
synchronized (this) {
pw = resp.getWriter();
try{
Thread.sleep(5000);
pw.println(name);
pw.flush();
pw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
8、Servlet 的 url-pattern 配置
8.1 URL 的匹配规则
8.1.1 精确匹配
8.1.2 扩展名匹配
8.1.3 路径匹配
8.1.4 任意匹配
8.1.5 优先顺序
8.2 URL 映射方式
8.2.1 方式一
8.2.2 方式二
9、基于注解式开发 Servlet
9.1 @WebServlet 注解中属性
9.2 @WebInitParam 注解中的属性
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns = "/initParam.do", initParams = {@WebInitParam(name="key1", value = "value1"), @WebInitParam(name = "key2", value = "value2")}, loadOnStartup = 1)
public class AnnotationServlet extends HttpServlet {
@Override
public void init() throws ServletException {
ServletConfig servletConfig = this.getServletConfig();
System.out.println(servletConfig.getInitParameter("key1"));
System.out.println(servletConfig.getInitParameter("key2"));
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = this.getServletConfig();
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("value1:" + servletConfig.getInitParameter("key1"));
out.println("value2:" + servletConfig.getInitParameter("key2"));
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
}
10、文件上传
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.UUID;
@WebServlet("/fileupload.do")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 中文字符做编码处理
req.setCharacterEncoding("utf-8");
String desc = req.getParameter("desc");
Part part = req.getPart("file");
// 获取文件上传的字节流
// InputStream inputStream = part.getInputStream();
// 给文件改名
String fileName = UUID.randomUUID().toString() + part.getSubmittedFileName().substring(part.getSubmittedFileName().indexOf("."))/*文件的后缀名*/; // getSubmittedFileName()获取原始的文件名
// 路径转换
ServletContext servletContext = this.getServletContext();
String path = servletContext.getRealPath("image/" + fileName);
part.write(path); // 文件上传
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("上传成功!!!" + desc);
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
}
11、Filter 过滤器
11.1 过滤器作用
11.2 Filter 的使用
11.2.1 Filter 对象的创建
11.2.2 FilterConfig 对象的使用
<?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_4_0.xsd"
version="4.0">
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.test.testfilter.EncodingFilter</filter-class>
<init-param>
<param-name>code</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
import javax.servlet.*;
import java.io.IOException;
/**
* 处理请求编码Filter
*/
public class EncodingFilter implements Filter {
private String encode;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String code = filterConfig.getInitParameter("code");
this.encode = code;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
if (this.encode == null) {
servletRequest.setCharacterEncoding("utf-8");
} else {
servletRequest.setCharacterEncoding(this.encode);
}
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
11.3 FilterChain(过滤器链)
11.4 Filter 的生命周期
11.5 基于注解式开发 Filter
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@WebFilter(urlPatterns = {"/*","/filter/*"}, initParams = {@WebInitParam(name = "name1", value = "filter1")})
public class AnnotationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Annotaion Filter.....");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}