servlet 是一个单实例多线程的普通的java类。
——校验多线程的安全问题的标准
Servlet 中的域对象:
对象 | 类型 |
---|---|
context | PageContext(jsp中的域对象:仅限于当前jsp) |
request | HttpServletRequest |
session | HttpSession |
application | ServletContext |
servlet 的两个重要对象:servletConfig、servletContext
1. servletConfig
servletConfig:servlet的配置对象
一个servlet可以由多个servletConfig对象
servlet的初始化参数(web.xml servlet的配置信息去设置)
<init-param>
<param-name>path</param-name>
<param-value>e:/a.txt</param-value>
</init-param>
获取初始化参数:
- getInitParameter(String name);
- getInitParameterNames();
servlet 的加载时机:
<load-on-startup> 数字越大,优先级越大。
服务器再启动的时候,servlet对象就被创建了。
servlet是一个单实例多线程的。
再内存中servlet对象指挥创建一次,由多线程的安全问题。
解决方法:使用同步代码块/同步方法
- 非静态的同步:锁对象:this
- 静态的同步方法:类名.class
应用:
package com.bite.servlet.d_config;
import javax.servlet.ServletConfig;
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.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/*
* ServletConfig对象:Servlet配置对象
* 一个servlet中可以由多个ServletConfig对象
*
* doGet方法里如何获取
*/
@WebServlet(name = "ConfigDemo")
public class ConfigDemo extends HttpServlet {
// 声明一个ServletConfig对象
private ServletConfig config;
String path = null;
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
path = config.getInitParameter("path");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 业务中内容----> 频繁更改业务中的方法 ---> 放入到servlet的配置信息中作为初始化梣属
*/
/*
* HttpServlet的父类GenericSerlvet源码:
* private transient ServletConfig config;
* public ServletConfig getServletConfig() {
* return config;
* }
*/
// 有一个需求:读取c盘下的test.txt文件的内容,将内容输出
BufferedReader br = new BufferedReader(new FileReader(path));
String line = null;
while ((line=br.readLine()) != null) {
System.out.println(line);
}
// 释放资源
br.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
package com.bite.servlet.d_config;
import javax.servlet.ServletConfig;
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.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/*
* ServletConfig对象:Servlet配置对象
* 一个servlet中可以由多个ServletConfig对象
*
* doGet方法里如何获取
*/
@WebServlet(name = "ConfigDemo")
public class ConfigDemo extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 业务中内容----> 频繁更改业务中的方法 ---> 放入到servlet的配置信息中作为初始化梣属
*/
/*
* HttpServlet的父类GenericSerlvet源码:
* private transient ServletConfig config;
* public ServletConfig getServletConfig() {
* return config;
* }
*/
// 获取servletConfig对象
ServletConfig config = this.getServletConfig();
String path = config.getInitParameter("path");
// 有一个需求:读取c盘下的test.txt文件的内容,将内容输出
BufferedReader br = new BufferedReader(new FileReader(path));
String line = null;
while ((line=br.readLine()) != null) {
System.out.println(line);
}
// 释放资源
br.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
2. servletContext
servletContext:全局管理者对象(一个web application 只有一个servletContext对象)
- 获取上下文路径:/项目名称/url-pattern。方法:getContextPath();
- 可以获取全局参数
- 可以请求转发。方法:request.getRequestDispatcher("/xx.jsp/html").forward(request,response);(如果后期跳转页面的时候,如果还需要用到request里的参数,请求转发)
- 可以作为域对象使用:request、servletContext
- 获取某个文件真实路径
- 如果不借助于 servletContext对象,要获取 classes 目录文件路径(只要使用类加载器:classLoader)
- 作为域对象:
在不同的servlet之间(包含jsp)可以保持数据,获取数据(数据共享)
request.setRequestAttribute(“名称”, 内容(String/ Map/ List));
request / ServletContext.getAttribute(“保持的名称”); -----> Object
特点:一个项目中代表一个ServletContext对象(全局管理者对象)
获取上下文路径:/web application 项目名称/请求的 url-pattern
获取全局参数:
web.xml 中:
<context-param>
<param-name>AAA</param-name>
<param-value>AAA'value</param-value>
</context-param>
应用:
1)servletContext 获取上下文路径
package com.bite.servlet.e_context;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
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;
/*
* ServletContext的作用1:获取上下文路径
*/
@WebServlet(name = "ContextDemo1")
public class ContextDemo1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* GenericServlet的 getServletContext 的源码:
public ServletContext getServletContext() {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
} else {
return sc.getServletContext();
}
}
*/
// 方法1:获取ServletConfig对象
// ServletConfig config = this.getServletConfig();
// ServletContext servletContext = config.getServletContext();
// 方法2:直接获取(this可以省略)
ServletContext servletContext = this.getServletContext();
// getContextPath():获取上下文路径
String contextPath = servletContext.getContextPath();
// 输出:contextPath:/ServletLife
System.out.println("contextPath:"+contextPath);
// 重定向:到底服务器行为,还是浏览器行为:location+302
// web application 的项目名称 / 跳转的页面
response.sendRedirect(request.getContextPath()+"/hello.html");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
获取到的上下文路径:
2)ServletContext获取全局参数
package com.bite.servlet.e_context;
import javax.servlet.ServletContext;
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;
/*
* 一个下项目(web application)有且仅有一个
* ServletContext的作用
* 作用2:获取全局参数
*/
@WebServlet(name = "ContextDemo2")
public class ContextDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = this.getServletContext();
// 获取上下文参数的初始化参数
String value1 = context.getInitParameter("AAA");
System.out.println(value1);
// getInitParameterNames() ---> 迭代器
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
获取到的数据:
3)servletContext 作为域对象去使用,保存数据,获取数据(共享数据)
package com.bite.servlet.a_scope;
import javax.servlet.ServletContext;
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;
import java.util.ArrayList;
import java.util.List;
/*
* servletContext作用:
* 作为域对象去使用,保存数据,获取数据(共享数据)
*/
@WebServlet(name = "ScopeDemo1")
public class ScopeDemo1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置编码
response.setContentType("text/html;charset=utf-8");
// 直接可以获取servletContext对象
// 获取全局管理者对象
ServletContext servletContext = this.getServletContext();
// public void setAttribute(String name, Object object)
// 给与对象中添加数据,同时设置属性名称
/* // 1
servletContext.setAttribute("name","eric");
*/
// 2.
// 创建一个list集合对象
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("javaee");
// 将list集合存储到域对象中
servletContext.setAttribute("list",list);
// 提示
response.getWriter().write("保存数据成功了...");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
4)从servletContext域中获取数据
package com.bite.servlet.a_scope;
import javax.servlet.ServletContext;
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;
import java.util.List;
/*
* 从servletContext域中获取数据
*/
@WebServlet(name = "ScopeDemo2")
public class ScopeDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 获取全局管理者对象
// public Object getAttribe();
ServletContext context = getServletContext();
// 从域中获取数据,通过域中存储的属性名称
/*// 1.
String name = (String)context.getAttribute("name");
System.out.println("name:"+name);*/
// 2.
List list = (List)context.getAttribute("list");
System.out.println("list:"+list);
response.getWriter().write("ScopeDemo2获取到了域中的数据");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
5)servletContext 的主要的作用:域对象,作为请求转发使用
package com.bite.servlet.b_path;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
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;
/*
* 获取文件真实路径(用类加载器的getpath())
*
* servletContext:主要的作用:域对象
* 作为请求转发使用
*/
@WebServlet(name = "PathDemo")
public class PathDemo extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取全局管理者对象
ServletContext servletContext = this.getServletContext();
// public String getRealPath(String path):获取真实路径
// 如果不使用 servletContext
String path = PathDemo.class.getClassLoader().getResource("a.txt").getPath();
// /C:/Data/Code/Web/Bit/servlet_cookie/target/servlet_cookie/WEB-INF/classes/a.txt
System.out.println(path);
// 请求转发技术
// public RequestDispatcher getRequestDispatcher(String path)
RequestDispatcher rd = servletContext.getRequestDispatcher("/hello.html");
// forward
rd.forward(request,response);
// 特点:整个过程:request请求对象只有一个
// 简写方式
request.getRequestDispatcher("/hello.html").forward(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
6)附:hello.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
hello.html 页面跳转成功...
</body>
</html>