目录
一位大佬的博客:https://www.cnblogs.com/fjdingsd/
Servlet的介绍
问题:服务器在接受到浏览器请求后,他会自动调用对应的逻辑代码进行请求处理,但是逻辑代码是由程序员编写并放在浏览器里面的,那么服务器怎么知道该怎么调用并调用哪个类或者方法来进行请求的处理?
解决:程序员在编写逻辑代码时候按照浏览器能够识别的规则进行编写,浏览器会按照指定的规制进行发送请求,那么服务器就可以调用并响应逻辑代码来处理请求;
实现:Servlet技术
概念:狭义的 Servlet 是指 Java 语言实现的一个接口,广义的 Servlet 是指 任何实现了这个 Servlet 接口的类,一般情况下,人们将 Servlet 理解为后者。 Servlet 运行于支持 Java 的应用服务器中。从原理上讲,Servlet 可以响应任何 类型的请求,但绝大多数情况下 Servlet 只用来扩展基于 HTTP 协议的 Web 服 务器
特点:
- 运行在支持java的应用服务器上
- Servlet的实现遵循了服务器能够识别的规则,也就是服务器会自动 的根据请求调用对应的servlet进行请求处理。
- 简单方便,可移植性强
使用:
- 创建普通的java 类并继承HttpServlet
- 覆写service方法
- 在service方法中书写逻辑代码即可
- 在webRoot下的WEB-INF文件夹下的web.xml 文件中配置servlet
运行流程:
url:http://localhost:8080/project/my2
组成: 服务器地址:端口号/虚拟项目名 /servlet的别名
uri:虚拟项目名 /servlet的别名
浏览器发送请求到服务器,服务器根据请求URL地址 中的URI信息在webapps目录下找到对应的项目文件夹, 然后在web.xml中检索对应的servlet,找到后调用并执行 Servlet。
Servlet的生命周期
从第一次调用,到服务器关闭。如果在web.xml 中配置了load-on-startup则是从服务器开启到服务器关闭。
package com.bjsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet的生命周期:
* 1、从第一次调用到服务器关闭。
* 2、如果Servlet在web.xml中配置了load-on-startup(里面的数组为初始化的次序),生命周期为
从服务器启动到服务器关闭
* 注意:
* init方法是对Servlet进行初始化的一个方法,会在Servlet第一次
加载进行存储时执行
* destory方法是在servlet被销毁时执行,也就服务器关闭时。
*
*/
public class ServletLife extends HttpServlet {
//初始化方法,在servlet第一次加载内容的时候被调用
@Override
public void init() throws ServletException {
System.out.println("servlet初始化完成");
}
//service方法,真正处理请求的方法
@Override
protected void service(HttpServletRequest req,HttpServletResponse resp)throwsServletException, IOException {
resp.getWriter().write("servlet life");
System.out.println("servlet life");
}
@Override
public void destroy() {
System.out.println("我被销毁了...");
}
}
web.xml设置
<servlet>
<description>This is the description of my J2EE
component</description>
<display-name>This is the display name of my J2EE
component</display-name>
<servlet-name>ServletLife</servlet-name>
<servlet-class>com.bjsxt.servlet.ServletLife</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>my</servlet-name>
<url-pattern>/my</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletLife</servlet-name>
<url-pattern>/life</url-pattern>
</servlet-mapping>
Service和doGet和doPost方法的区别
- Service方法:不管是get方法还是post方法的请求,如何类中有Service则优先执行Service
- doGet方法:在没有Service的情况下,如果是get方法的请求所调用的处理请求方法
- doPost方法:在没有Service的情况下,如果是post方法的请求所调用的处理请求方法
Service的常见错误总结
- Servlet的常见错误:
- 404错误:资源未找到
- 原因一:在请求地址中的servlet的别名书写错误。
- 原因二:虚拟项目名称拼写错误
- 500错误:内部服务器错误
- 错误一: java.lang.ClassNotFoundException: com.bjsxt.servlet.ServletMothod
- 解决: 在web.xml中校验servlet类的全限定路径是否拼写错误。
- 错误二: 因为service方法体的代码执行错误导致
- 解决: 根据错误提示对service方法体中的代码进行错误更改。
- 错误一: java.lang.ClassNotFoundException: com.bjsxt.servlet.ServletMothod
- 405错误:请求方式不支持
- 原因: 请求方式和servlet中的方法不匹配所造成的。
- 解决: 尽量使用 service 方法进行请求处理,并且不要再 service 方法中调用父类的
- 404错误:资源未找到
注意:如果Service的方法中调用了父类的Service方法(super.service(arg0,arg1))Service处理玩后会根据请求方式响应的doGet方法和doPost方法执行,所以一般情况下,我们不在覆写 Service方法中调用父类的Service方法,避免405错误
package com.servlet.one;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption : Service方法和doGet和doPost的区别
* @date :2019-3-26 下午8:21:38
* @author :田坤
*/
public class One extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("我的全面的");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("我可以执行get方法");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("我可以执行post方法");
}
}
Request对象
问题: 浏览器发起请求到服务器,会遵循HTTP协议将请求数据发送给服务器。 那么服务器接受到请求的数据改怎么存储呢?不但要存,而且要保证完成性。
解决: 使用对象进行存储,服务器每接受一个请求,就创建一个对象专门的存 储此次请求的请求数据。
实现:Request对象
解释:服务器接收到浏览器的请求后,会创建一个Request对象,对象中 存储了此次请求相关的请求数据。服务器在调用Servlet时会将创建的 Request对象作为实参传递给Servlet的方法,比如:service方法。
使用:获取请求头数据 、获取请求行数据 、 获取用户数据
package com.servlet.one;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :Request对象获取数据
* @date :2019-3-26 下午9:16:19
* @author :田坤
*/
public class Request extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 获取请求头数据:
System.out.println("获取请求头数据:");
// 获取请求方法
System.out.println(req.getMethod());
// 获取请求的URL
System.out.println(req.getRequestURL());
// 获取请求的URI
System.out.println(req.getRequestURI());
// 获取请求的协议
System.out.println(req.getScheme());
// 获取请求行数据
System.out.println("获取请求行数据:");
// 获取指定的请求行信息
System.out.println(req.getHeader("User-Agent"));
// 获取所有请求行的键的枚举
Enumeration e = req.getHeaderNames();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
String value = req.getHeader(name);
System.out.println(name + ":" + value);
}
// 获取用户信息
System.out.println("获取用户信息");
String name = req.getParameter("num");
String password = req.getParameter("pwd");
System.out.println(name + "--" + password);
//req.getParameterValues(“键名”) 返回同键不同值的请求数据(多选),返回的数组
//req.getParameterNames(); 返回所有用户请求数据的枚举集合
}
}
获取请求头数据:
POST
http://localhost:8080/newproject/Request
/newproject/Request
http
获取请求行数据:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
host:localhost:8080
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
accept-language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
accept-encoding:gzip, deflate
referer:http://localhost:8080/newproject/MyJsp.jsp
content-type:application/x-www-form-urlencoded
content-length:25
connection:keep-alive
cookie:JSESSIONID=70AB1304971FF438296871CCD774DD00; Pycharm-ab6eb338=0f1c29eb-c033-404f-905f-73964fbc2665; Pycharm-134fe017=6a4fd521-686f-4450-a917-d0124760806b
upgrade-insecure-requests:1
获取用户信息
songxudong--111111
注意:如果获取的数据不存在,不会报错,返回的是NULL
Respose对象
问题: 在使用Request对象获取了请求数据并进行处理后,处理的结果如何显 示到浏览器中呢?
解决:使用Response对象
解释: 服务器在调用指定的Servlet进行请求处理的时候,会给Servlet的方 法传递两个实参request和response。其中request中封存了请求相关的 请求数据,而response则是用来进行响应的一个对象。
使用: 设置响应头 、设置响应编码格式、置响应实体
package com.servlet.one;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Desciption :Respose的使用
* @date :2019-3-26 下午10:34:52
* @author :田坤
*/
public class Respose extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 相应处理结果
// 设置响应头
resp.addHeader("mouse", "mumaren");
resp.setHeader("keyboard", "mumaren"); // set和add add可以重复加,set会覆盖
// 设置响应编码格式
// resp.setHeader("content-type", "text/html;charset=utf-8");
resp.setContentType("text/html;charset=utf-8");
// 设置响应码的状态
// resp.sendError(405, "nou found!");
resp.getWriter().write("<b>Respose!</b>");
}
}
Service请求处理代码流程:
- 设置响应编码格式
- 获取请求数据
- 处理请求数据
- 数据库操作(MVC思想)
- 处理响应结果
关于MIME类型(Multipurpose Internet Mail Extensions)
请求乱码解决
- 使用String进行数据重新编码
- String name = new String(uname.getBytes("iso8859-1"),"utf-8") // iso8859-1 浏览器(火狐)默认字符编码集
- 使用公共配置
- post方法:req.setCharacterEncoding("utf-8");
- get方法
- 步骤一:在Tomcat的conf目录下的server.xml文件中,在connector标签中增加属性 useBodyEncodingForURI="true"
- 步骤二:req.setCharacterEncoding("utf-8");
Servlet流程总结:
- 浏览器发起请求到服务器
- 服务器接受浏览器请求,进行解析,创建request对象存储数据
- 服务器调用对应的Servelt进行请求处理,并将request对象作为实参传给Servlet方法;
- servlet方法执行请求处理
- 设置请求编码格式
- 设置响应编码格式
- 获取请求信息
- 处理请求信息
- 创建业务层
- 调用业务层对象的方法
- 响应处理结果
数据流转流程:
浏览器——>服务器——>数据库——>服务器——>浏览器
请求转发:
- 作用:实现多个servlet联动操作处理请求,这样避免代码冗余,让servlet的职责更加明显
- 使用:req.getRequestDispatcher(“要转发的地址”).forward(request,respose);
- 地址是相对路径,直接写别名
- 特点:一次请求,浏览器地址栏信息不变
- 注意:请求转发后直接return结束即可;
Request对象作用域
问题:使用请求转发后,不同的 Servlet 之间怎么进行数据的共享呢?或者说数据怎么从一个 servlet 流转给另外一个 Servlet 呢?
解决:使用 request 对象的作用域
使用: request.setAttribute(objectname,Objectvalue);
request.getAttribute(Objectobj)
作用:解决了一次请求内的不同 Servlet 的数据(请求数据+其他数据)共享问题。
作用域: 基于请求转发,一次请求中所有的servlet共享(一个给一个)
注意:使用request对象进行数据流转,数据只能在一次请求中有效(一个请求一个request)
特点:服务器创建的、每次请求都会创建、生命周期是一个请求
package com.servlet.two;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.service.LoginService;
import com.service.impl.LoginServiceImpl;
/**
*
* @Desciption :servlet处理登录请求 Login的相对路径为 login
* @date :2019-3-27 下午4:35:06
* @author :田坤
*/
public class Login extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
// 设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
// 获取请求信息
String id = req.getParameter("uname");
String password = req.getParameter("pwd");
// String pwd = new String(password.getBytes("iso8859-1"), "utf-8");
System.out.println(id + "--" + password);
// 处理请求信息(操作数据库)
// 获取业务层对象:
LoginService ls = new LoginServiceImpl();
User u = ls.checkLoginService(Integer.valueOf(id), password);
if (u != null) {
resp.getWriter().write("成功");
} else {
// 使用request对象实现不同servlet的数据流转
req.setAttribute("str", "账号或者密码输入错误");
// 使用请求转发
req.getRequestDispatcher("page1").forward(req, resp);
return;
}
}
}
package com.servlet.two;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :响应出登录的页面
* @date :2019-3-27 下午4:55:25
* @author :田坤
*/
public class PageServlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
// 获取请求信息
// 处理请求
// 响应处理结果
// 获取request对象作用域
String str = (String) (req.getAttribute("str") == null ? "" : req
.getAttribute("str"));
resp.getWriter().write("<html>");
resp.getWriter().write("<head>");
resp.getWriter().write("</head>");
resp.getWriter().write("<body>");
resp.getWriter().write(
"<font color='red' size='20px'>" + str + "</font>");
resp.getWriter().write("<form action='login' method='get'>");
resp.getWriter().write(
"用户名:<input type='text' name='uname' value='' /><br/>");
resp.getWriter().write(
"密码:<input type='text' name='pwd' value='' /><br/>");
resp.getWriter().write("<input type='submit' value='登录'><br/>");
resp.getWriter().write("</form>");
resp.getWriter().write("</body>");
resp.getWriter().write("</html>");
}
}
重定向
解决了表单重复提交的问题,以及当前servlet无法处理的请求问题
用法:resp.sendRedirect("路径"); 本地路径为:URI 、网路路径为:定向资源的URL信息
特点:俩次请求,俩个request对象、浏览器地址栏信息改变
时机:
- 如果请求中含有表单数据,而数据又比较重要,不能重复提交,建议使用重定向
- 如果请求被servlet接受,但无法进行处理,建议使用重定向定位到可以处理的资源
Cookie
解释:Cookie 技术其实是浏览器端的数据存储技术,解决了不同请求需要使用相同的请求数据的问题。我们把请求需要共享的请求数据,存储在浏览器端,避免用户进行重复的书写请求数据。但是哪些数据需要使用 Cookie 技术存储起来是一个主观问题,需要在后台进行响应的时候来告诉浏览器,有些数据其他请求还会使用,需要存储起来。
作用:解决了发送的不同请求的数据共享问题
使用:
- 创建Cookie对象
- Cookie cookie = new Cookie(String name, String value);
- 设计Cookie(可选)
- 有效期:
- c.setMaxAge(int seconds);
- 设置有效路径
- c.setPath(String uri)
- 有效期:
- 响应Cookie信息给客户端
- resp.addCookie(cookie);
- 获取Cookie信息
- 获取Cookie信息数组
- 遍历Cookie信息数组(for)需要进行非空判断
注意:一个cookie只能存储一条数据
特点:
- 浏览器端的数据存储技术
- 存储的数据声明在服务器端
- 存储类型
- 临时存储(默认):存储在浏览器的运行内存中,关闭浏览器即失效
- 定时存储:设置了Cookie的有效期,存储在客户端的硬盘上,在有效期内符合路径要求的请求都会附带该信息
- 默认Cookie信息存储好后,每次请求都会附带,除非设置有效路径
- 适合少量数据,不安全
package com.cookie.one;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :创建和设置Cookie
* @date :2019-3-27 下午6:34:05
* @author :田坤
*/
public class CookieServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 请求对象编码格式
req.setCharacterEncoding("utf-8");
// 响应对象编码格式
resp.setContentType("text/html;charset=utf-8");
//获取请求信息
//处理请求信息
//响应处理结果
//使用Cookie进行浏览器的存储
//创建对象
Cookie c = new Cookie("nan", "huge") ;
Cookie c1 = new Cookie("nv", "liushishi");
//设置Cookie
//设置Cookie的有效期
c1.setMaxAge(3*24*3600); //3天
//设置Cookie的有效路径
c1.setPath("/Cookie/gcs"); //只在此路径下可可以附带Cookie信息
//响应Cookie信息
resp.addCookie(c); //临时存储
resp.addCookie(c1); //定时存储
//直接响应
//请求响应
//重定向
}
}
package com.cookie.one;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :获取Cookie
* @date :2019-3-27 下午7:40:02
* @author :田坤
*/
public class GetCookies extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//获取请求信息
//获取Cookie信息
Cookie[] cookie = req.getCookies();
String name = ""; //cookie的键名
String value = ""; //cookie的值
if(cookie != null){
for(Cookie c:cookie){
name = c.getName();
value = c.getValue();
System.out.println(name+" : "+value);
}
}
}
}
Session
问题:Request 对象解决了一次请求内的不同 Servlet 的数据共享问 题,那么一个用户的不同请求的处理需要使用相同的数据怎么办呢?
解决:使用Session技术
原理:用户使用浏览器第一次向服务器发送请求,服务器在接受到请求后,调用对应的 Servlet 进行处理。在处理过程中会给用户创建 一个 session 对象,用来存储用户请求处理相关的公共数据,并将 此 session 对象的 JSESSIONID 以 Cookie 的形式存储在浏览器中 (临时存储,浏览器关闭即失效)。用户在发起第二次请求及后续请 求时,请求信息中会附带 JSESSIONID,服务器在接收到请求后, 调用对应的 Servlet 进行请求处理,同时根据 JSESSIONID 返回其 对应的 session 对象。
特点:
- Sessions技术是依赖于cookie技术服务器端的存储数据技术
- 由服务器创建
- 每个用户会拥有一个独立的Session
- 作用域:一个会话
- 默认生存时间:30分钟
作用:解决一个用户不同请求的数据共享问题
使用:
- 创建Session对象和获取Session对象
- HttpSession hs = req.getSession();
- 如果请求中拥有Session标识符也就是JSESSIONID,则返回对应的Session对象
- 如果请求中不拥有Session标识符也就是JSESSIONID,则创建一个新的Session对象,并将JSESSIONID以cookie数据存储到浏览器中
- 如果Session对象消失了,也会重新创建一个Session对象,并将JSESSIONID存储在浏览器内存中
- 设置Session的存储时间
- hs.setMaxInactiveInterval(int seconds);
- 在指定的时间内没有使用则销毁,反之则重新计时
- hs.setMaxInactiveInterval(int seconds);
- 设置Session强制失效
- hs.invalidate();
- 存储或获取数据
- 存储:hs.setAttribute(String name,Object value);
- 获取:hs.getAttribute(String name);
- 注意:存储和取出动作发生在不同的请求中,存储要先于获取
- 使用时机:一般用户在登录web项目中,将用户的个人信息存储在Session中(用户的对象),用于其他请求使用
- 总结:Session是解决一个用户不同请求的数据共享问题,只要JSESSIONID和session对象不失效的情况下,用户的任意请求都可以获取到同一个Session对象;
/**
*
* @Desciption :Session的使用
* @date :2019-3-27 下午11:32:07
* @author :田坤
*/
public class SessionServlet1 extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//请求信息编码格式
req.setCharacterEncoding("utf-8");
//响应信息编码格式
resp.setContentType("text/html;charset=utf-8");
//获取请求信息
String name = "田坤";
//处理请求信息
//创建Session对象
HttpSession hs = req.getSession();
//设置Session生存时间(默认30分钟)
// hs.setMaxInactiveInterval(5); //设置存储时间为5秒
//Session销毁
// hs.invalidate();
//响应处理结果
//加入Session数据
hs.setAttribute("name", name);
//输出JSESSIONID
System.out.println(hs.getId());
//直接响应
resp.getWriter().write("Session学习");
}
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
HttpSession hs = req.getSession();
String name = (String) hs.getAttribute("name");
//获取JSESSIONID
String sessionid = "";
Cookie[] ck = req.getCookies();
for(Cookie c : ck){
if(c.getName().equals("JSESSIONID"))
sessionid = c.getValue();
}
if(sessionid.equals(hs.getId())){
System.out.println(sessionid);
System.out.println(hs.getId());
resp.getWriter().write("俩个Session是同一个Session");
}
}
除了可以用hs.setMaxInactiveInterval(int seconds)的方法还可以在Tomcat的web.xml的公共属性session-config标签进行修改,但不推荐这样修改
<session-config>
<session-timeout>30</session-timeout>
</session-config>
ServletContext
问题:不同用户使用相同的对象
作用:解决了不同用户的数据共享问题
原理:ServletContext 对象由服务器进行创建,一个项目只有一个对象。不管在项目的任意位置进行获取得到的都是同一个对象,那么不同用户发起的请求获取到的也就是同一个对象了,该对象由用户共同拥有。
特点:服务器创建、用户共享、一个项目一个ServletContext
作用域:一个项目
生命周期:一个项目开始到一个项目结束
使用:
- 获取ServletContext对象(主要用一三种)
- 第一种方法:ServletContext sc = this.getServletContext();
- 第二种方法:ServletContext sc = this.getSevletConfig().getServletContext();
- 第三种方法:ServletContext sc = req.getSession().getServletContext();
- 使用ServletContext对象完成数据共享
- 数据存储:sc.setAttribute(String name,Object value)
- 数据获取:sc.getAttribute(String name)
- 不同的用户可以对相同的ServletContext对象进行存储,如果获取 数据不存在则返回NULL
- 获取项目中web.xml文件中的全局配置数据
- sc.getInitParameter(String name)
- 根据键的名字返回web.xml中配置全局数据的值,返回String类型,数据不存在则返回NULL
- sc.getInitParameterNames();
- 返回键名的枚举
- web.xml文件全局数据的配置方式
- 一组<context-param>标签只能存储一组键值对数据
- 作用:将静态数据与代码进行解耦
- sc.getInitParameter(String name)
- 获取项目WebRoot下的资源的绝对路径
- String path = sc.getRealPath(String path);
- 获取的路径为项目根路径,path参数为项目根目录中的路径
- 获取webroot下的资源流对象
- InputStream is = sc.getRecoureAsStream(String path)
- 注意:此种方式只能获取项目根目录路径下的资源流对象,class文件的流对象需要使用类加载⑦获取
- path参数为项目根路径下的路径
package com.servlet.one;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption : ServletContext的使用
* @date :2019-3-28 下午8:57:58
* @author :田坤
*/
public class ServletContext1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
// 獲取ServletContext对象
// 第一种方式
ServletContext sc = this.getServletContext();
// 第二种方式
ServletContext sc1 = this.getServletConfig().getServletContext();
// 第三种方式
ServletContext sc2 = req.getSession().getServletContext();
ServletContext sc3 = req.getServletContext();
System.out.println(sc == sc1);
System.out.println(sc == sc2);
System.out.println(sc == sc3);
// 使用ServletContext完成数据的共享
// 存储数据
sc.setAttribute("name", "我爱学习");
// 获取项目web.xml的全局配置数据
String data = sc.getInitParameter("name");
System.out.println("全局配置参数" + data);
// 获取项目根路径下的资源的绝对路径
// String path =
// " C:/Program Files/Apache Software Foundation/Tomcat 7.0/webapps/ServletContext/META-INF/1.txt";
String path = sc.getRealPath("1.txt");
System.out.println(path);
// 获得项目目录下的资源的流对象
InputStream is = sc.getResourceAsStream("1.txt");
}
}
package com.servlet.one;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletContext2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
ServletContext sc = this.getServletContext();
String name = (String) sc.getAttribute("name");
System.out.println(name);
}
}
true
true
true
全局配置参数tiankun
C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\ServletContext\1.txt
我爱学习
ServletConfig
问题:使用ServletContext对象可以获取web.xml中的全局配置文件,在 web.xml 中每个 Servlet 也可以进行单独的配置,那么该怎么获取配置信息呢?
作用:ServletConfig 对象是 Servlet 的专属配置对象,每个 Servlet 都单独拥有一个 ServletConfig 对象,用来获取 web.xml 中的配置信
息。
使用:获取 ServletConfig 对象、获取 web.xml 中 servlet 的配置信息
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>ServletConfigServlet</servlet-name>
<servlet-class>com.servlet.one.ServletConfigServlet</servlet-class>
<init-param> <!--局部变量,在相对应的servlet中-->
<param-name>code</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
package com.servlet.one;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :ServletConfig学习
* @date :2019-3-29 下午1:45:10
* @author :田坤
*/
public class ServletConfigServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
ServletConfig sc = this.getServletConfig();
// 获取在web.xml中写的局部变量
String code = sc.getInitParameter("code");
System.out.println(code);
}
}
web.xml文件
作用:存储项目的相关的配置信息,保护Servlet,解耦一些数据对程序的依赖。
使用位置:
- 每个web项目中
- 局部变量,针对的是本项目;
- Tomcat服务器中(在服务器目录的config中)
- 全局变量,配置公共信息
内容(核心组件)
- 全局上下文配置(全局配置参数)
- Servlet配置
- 过滤器配置
- 监听器配置
加载顺序:Web 容器会按 ServletContext -> context-param -> listener ->filter-> servlet 这个顺序加载组件,这些元素可配置在 web.xml
文件中的任意位置。
加载时机:服务器启动时。
Serve.xml文件
问题:浏览器发起请求后,服务器根据请求在 webapps 目下调用对应的 Servlet 进行请求处理。那么为什么是 webapps 目录难道不能是
其他的目录吗?
解决:了解 server.xml 文件的配置信息
Server.xml 文件核心组件:
<Server>
<Service>
<Connector/>
<Connector/>
<Engine>
<Host>
<Context/>
</Host>
</Engine>
</Service>
</Server>
热部署: <Context path="/Pet" reloadable="true" docBase="F:/PetWeb" />
只要文件有修改就可以直接部署在服务器上,而我们正常使用的是冷部署,只要在启动服务器后才可以将修改的文件部署到服务器上