目录
2.1 案例需求:编写一个普通的java类,通过浏览器可以访问
一 Servlet概述
servlet= server+applet :运行在服务器端的java程序。
Servlet是一个接口,一个类要想通过浏览器被访问到,那么这个类就必须直接或间接的实现Servlet接口
作用
接收请求,处理逻辑,响应结果
二 Servlet快速入门
2.1 案例需求:编写一个普通的java类,通过浏览器可以访问
步骤分析:
① 创建web项目
② 编写普通java类,实现servlet接口
③ 在web.xml配置url-pattern
④ 部署web项目
⑤ 启动测试
编写java类
package com.lg.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
* @author CH
* @date 2020/11/19 10:51
*/
public class QuickServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/*
对外提供服务的方法, tomcat会调用servlet中的service方法, 执行具体的业务逻辑
servletRequest: 请求对象, 借助该对象获取请求参数
servletResponse: 响应对象, 借助该对象向浏览器响应一些数据
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("servlet入门成功了...");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
编写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">
<!--配置QuickSerlvet
servlet-name : 当前配置的servlet起一个别名(名称)
servlet-class: 编写的就是配置的servlet的全限定类名
-->
<servlet>
<servlet-name>QuickServlet</servlet-name>
<servlet-class>com.lg.servlet.QuickServlet</servlet-class>
</servlet>
<!--
servlet-mapping:给servlet设置一个映射地址
servlet-name:给指定名称的servlet来配置映射地址
url-pattern:具体该serlvet的映射地址(访问路径) *必须以/开头
-->
<servlet-mapping>
<servlet-name>QuickServlet</servlet-name>
<url-pattern>/quickServlet</url-pattern>
</servlet-mapping>
</web-app>
项目部署后访问网址idea的tomcat控制台会打印
2.2 servlet执行原理
三 Servlet生命周期
3.1 生命周期相关
3.1.1 思想介绍
生命周期:指的是 一个对象从生(创建)到死(销毁)的一个过程
// 1. servlet对象创建时,调用此方法
public void init(ServletConfig servletConfig);
// 2. 用户访问servlet时,调用此方法
public void service(ServletRequest servletRequest, ServletResponse
servletResponse);
// 3. servlet对象销毁时,调用此方法
public void destroy();
3.1.2 代码演示
① LifeServlet
package com.lg.life;
import javax.servlet.*;
import java.io.IOException;
/**
* @author CH
* @date 2020/11/19 12:46
*/
public class LifeServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("LifeServlet的init方法执行了,该对象被创建完成了...");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("LifeServlet的service方法执行了,执行了具体的业务逻辑...");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("LifeServlet的destroy方法执行了,该对象被销毁了...");
}
}
② 配置web.xml
<!--LifeSerlvet-->
<servlet>
<servlet-name>LifeSerlvet</servlet-name>
<servlet-class>com.lg.life.LifeServlet</servlet-class>
<!--配置上该标签,serlvet就会在启动服务器的时候去完成实例化,并进行初始化操作
标签内部需要写数值 正整数 1-3在tomcat的web.xml被使用了,所以建议从4开始使用
-->
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>LifeSerlvet</servlet-name>
<url-pattern>/LifeSerlvet</url-pattern>
</servlet-mapping>
<!--配置上该标签,serlvet就会在启动服务器的时候去完成实例化,并进行初始化操作
标签内部需要写数值 正整数 1-3在tomcat的web.xml被使用了,所以建议从4开始使用
-->
<load-on-startup>4</load-on-startup>
* 创建
1)默认情况下
用户第一次访问时,创建servlet,执行init方法2)修改创建时机
<load-on-startup></load-onstartup>
正数:4-N 【服务器启动时,创建】
补充:Tomcat的web.xml里有1,3 所以推荐4-n
负数(默认值):-1 【用户第一次访问时,创建】* 运行(提供服务)
用户每次访问时,都执行service方法* 销毁
服务器正常关闭时,销毁servlet,执行destroy方法
```笔试题:请描述下servlet的生命周期:
答案:servlet是一个单实例多线程的,默认情况下,第一次请求来的时候,才会对该servlet进行实例化,并执行初始化init方法,随后再执行service方法完成业务处理,当每一次请求发送过来,都会重新开启一个线程,来执行servlet中的service方法,当服务器关闭或者servlet被移除的时候,会执行destory方法
四 Servlet体系结构
4.1 GenericServlet
① 编写普通java类,继承GenericServlet抽象类
package com.lagou.servlet;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
public class ServletDemo1 extends GenericServlet {
@Override
public void init() throws ServletException {
super.init();
System.out.println("ServletDemo1的初始化方法执行了..");
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("ServletDemo1 extends GenericServlet...");
}
@Override
public void destroy() {
super.destroy();
System.out.println("ServletDemo1的销毁方法执行了");
}
}
② 配置web.xml
<!--ServletDemo1-->
<servlet>
<servlet-name>ServletDemo1</servlet-name>
<servlet-class>com.lagou.servlet.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/servletDemo1</url-pattern>
</servlet-mapping>
4.2 HttpServlet
① 编写前端html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<h3>用户登录</h3>
<form action="http://localhost:8080/servlet_demo/servletDemo2" method="get">
<input type="submit" value="提交表单..">
</form>
</body>
</html>
② 编写普通java类,继承HttpServlet抽象类, 重写doGet和doPost
package com.lagou.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletDemo2中的doGet方法执行了...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletDemo2中的doPost方法执行了...");
}
}
③ 配置web.xml
<!--ServletDemo2-->
<servlet>
<servlet-name>ServletDemo2</servlet-name>
<servlet-class>com.lagou.servlet.ServletDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo2</servlet-name>
<url-pattern>/servletDemo2</url-pattern>
</servlet-mapping>
五 url-pattern的配置方式
5.1 Servlet映射多个url
5.2 url映射模式
配置 url地址取值可以是:
1. 精确匹配(掌握)
/servletDemo3 如: localhost:8080/项目路径/servletDemo32. 目录匹配
/aa/* 只要是aa目录下的都可以访问3. 后缀匹配
*.xxx 例如:*.do 是要后缀名是 .do 都可以访问
<!--
只要浏览器符合目录匹配规则,都可以访问到这个servlet:
/aa/abc
/aa/asadfasdf
-->
<servlet>
<servlet-name>ServletDemo4</servlet-name>
<servlet-class>com.lagou.servlet.QuickServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo4</servlet-name>
<url-pattern>/aa/*</url-pattern>
</servlet-mapping>
<!--
只要浏览器符合后缀匹配规则,都可以访问到这个servlet
aa.do
bb.do
xx.do
-->
<servlet>
<servlet-name>ServletDemo5</servlet-name>
<servlet-class>com.lagou.servlet.QuickServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo5</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
六 Request对象
6.1 request对象概述
- 用户通过浏览器访问服务器时,Tomcat将HTTP请求中所有的信息都封装在Request对象中
- 作用:开发人员可以通过request对象方法,来获取浏览器发送的所有信息.
6.2 获取请求行信息
* 例如:
GET /servlet_demo/requestDemo1 HTTP/1.1
* 相关API:
1. 获取请求方式 GET【掌握】
String getMethod()2. 获取项目虚拟路径(项目名) /servlet_demo【掌握】
String getContextPath()3. 获取URL http://localhost:8080/servlet_demo/requestDemo1
统一资源定位符(确定某一个地址) 中华人民共和国
StringBuffer getRequestURL()4. 获取协议和版本号 HTTP/1.1
String getProtocol()5. 获取客户端ip
String getRemoteAddr()
package com.lagou.request;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 演示request对象获取请求行信息
System.out.println("请求方式:" + request.getMethod());
System.out.println("虚拟路径:" + request.getContextPath());
System.out.println("URL:" + request.getRequestURL());
System.out.println("协议和版本:" + request.getProtocol());
System.out.println("客户端IP地址:"+ request.getRemoteAddr());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
6.3 获取请求头信息
* 例如:
Host: 127.0.0.1:8080
* 相关API:
1. 获取知道请求头名称对应的值,注:名称不区分大小写
String getHeader(String name)
2. 获取所有请求头的名称
Enumeration<String> getHeaderNames()
注:是Iterator前身
package com.lagou.request;
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.util.Enumeration;
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求头信息
// 获取指定的头信息 Host
String host = request.getHeader("Host");
System.out.println("指定的请求头信息Host是: " + host);
// 先获取到所有的请求头名称
Enumeration<String> headerNames = request.getHeaderNames();
//遍历
while (headerNames.hasMoreElements()){
// 请求头名称
String name = headerNames.nextElement();
// 根据名称获取值
String value = request.getHeader(name);
System.out.println("请求头" + name + "的信息是: " + value);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.4 获取请求体信息(请求参数)【重点....】
不论get还是post请求方式,都可以使用下列方法来获取请求参数
* 参数
username=jack&password=123&hobby=drink&hobby=perm* API
1. 获取指定参数名的值 username=jack
String getParameter(String name)2. 获取指定参数名的值数组 hobby=drink&hobby=perm
String[] getParameterValues(String name)3. 获取所有参数名和对应值数组,参数名 name(key),值数组 value,封装map集合
Map<String,String[]> getParameterMap()* 中文乱码【重点】
get:在tomcat8及以上版本,内部URL编码(UTF-8)
post:编码解码不一致,造成乱码现象
客户端(浏览器)编码:UTF-8
服务器默认 解码:ISO-8859-1 拉丁文指定解码:void setCharacterEncoding(String env)
注:这哥们必须在方法内,行首
①创建一个表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h3>get方式提交表单:</h3>
<form action="/servlet_demo/requestDemo3" method="get">
用户:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
爱好:
<input type="checkbox" name="hobby" value="smoking"/> 抽烟
<input type="checkbox" name="hobby" value="drink"/> 喝酒
<input type="checkbox" name="hobby" value="perm"/> 烫头
<input type="submit" value="get提交">
</form>
<h3>post方式提交表单:</h3>
<form action="/servlet_demo/requestDemo3" method="post">
用户:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
爱好:
<input type="checkbox" name="hobby" value="smoking"/> 抽烟
<input type="checkbox" name="hobby" value="drink"/> 喝酒
<input type="checkbox" name="hobby" value="perm"/> 烫头
<input type="submit" value="post提交">
</form>
</body>
</html>
② 编写java 的HttpServlet, 重写doGet doPost
package com.lagou.request;
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.util.Arrays;
import java.util.Map;
public class RequestDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
// 获取表单提交的请求参数
String username = request.getParameter("username");
System.out.println("用户名:" + username);
// 获取爱好这样的多个value的数组类型
String[] hobbies = request.getParameterValues("hobby");
System.out.println( Arrays.toString(hobbies));
// 获取所有的请求参数的key和value String:表单中的name属性值 String[]:请求参数的value值
Map<String, String[]> parameterMap = request.getParameterMap();
parameterMap.forEach((k,v)->{
System.out.println(k + "=" + Arrays.toString(v));
});
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
// 设置解码为UTF-8 ,解决post中文乱码问题
// 下面的语句必须放在首行
request.setCharacterEncoding("UTF-8"); //可以放到get中
doGet(request, resp); //让doGet方法中业务逻辑执行
}
}
6.5 请求转发
一种在服务器内部的资源跳转方式
* API
1. 通过reqeust对象,获得转发器对象
RequestDispatcher getRequestDispatcher(String path) //要跳转到的z2. 通过转发器对象,实现转发功能
void forward(ServletRequest request, ServletResponse response)* 请求转发特点
浏览器:发了一次请求
地址栏:没有发生改变
只能转发到服务器内部资源....* 链式编程
request.getRequestDispatcher("/bServlet").forward(reqeust,response)
① 编写AServlet转发信息给BServlet , getRequestDispatcher,
package com.lagou.request;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("AServlet中功能上执行了");
// 请求转发到Bservelt String path: 写的就是要跳转的资源路径
/* // 1.获取到转发器对象
RequestDispatcher requestDispatcher = request.getRequestDispatcher("https://www.baidu.com/");
// 2.借助转发器对象进行真正的请求转发
requestDispatcher.forward(request,resp);*/
// 链式编程
request.getRequestDispatcher("/bServlet").forward(request,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
② 编写BServlet接收AServlet转发的信息
package com.lagou.request;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class BServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 从request域中取出数据
String hanbao = (String) req.getAttribute("hanbao");
System.out.println(hanbao);
// 向request域中设置数据
request.setAttribute("hanbao","香辣鸡腿堡");
System.out.println("BServlet中功能下执行了");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
③ 配置xml文件
<!--ASerlvet-->
<servlet>
<servlet-name>ASerlvet</servlet-name>
<servlet-class>com.lagou.request.AServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ASerlvet</servlet-name>
<url-pattern>/aServlet</url-pattern>
</servlet-mapping>
<!--BSerlvet-->
<servlet>
<servlet-name>BSerlvet</servlet-name>
<servlet-class>com.lagou.request.BServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BSerlvet</servlet-name>
<url-pattern>/bServlet</url-pattern>
</servlet-mapping>
6.6 域对象(共享数据)
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于一次请求中转发的多个资源中共享数据
package com.lagou.request;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("AServlet中功能上执行了");
// 向request域中设置数据
request.setAttribute("hanbao","香辣鸡腿堡");
// 链式编程
request.getRequestDispatcher("/bServlet").forward(request,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
package com.lagou.request;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class BServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 从request域中取出数据
String hanbao = (String) req.getAttribute("hanbao");
System.out.println(hanbao);
System.out.println("BServlet中功能下执行了");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
七 Response对象
7.1 概述
response对象表示web服务器给浏览器返回的响应信息
作用:开发人员可以使用response对象的方法,设置要返回给浏览器的响应信息
Response体系结构
ServletResponse 接口
|
HttpServletResponse 接口
|
org.apache.catalina.connector.ResponseFacade 实现类(由tomcat提供的)
7.2 设置Http响应消息
响应行
响应头
响应体【重点】
7.3 响应重定向
需求:用户访问AServlet后,服务器告诉浏览器重定向到BServlet
步骤分析
* 方式一
// 1.设置状态码
response.setStatus(302);
// 2.设置响应头 Location
response.setHeader("Location","重定向网络地址");
* 方式二
// 1.response这哥们封装专门处理重定向的方法
response.sendRedirect("重定向网络地址");
重定向特点
1. 地址栏会发生改变
2. 重定向是二次请求, 每次请求都会创建request对象
3. 重定向是客户端(浏览器)行为,可以跳转到服务器外部资源...
4. 不能使用request域共享数据
package com.lagou.response;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("访问到了CSerlvet,接下来重定向到DServlet");
// 设置重定向
/* resp.setStatus(302);
resp.setHeader("Location","dServlet");*/
// 设置重定向 方式二:常用, 重点掌握
resp.sendRedirect("https://www.lagou.com/");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.lagou.response;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class DServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("DServlet执行了.....");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--CSerlvet-->
<servlet>
<servlet-name>CServlet</servlet-name>
<servlet-class>com.lagou.response.CServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CServlet</servlet-name>
<url-pattern>/cServlet</url-pattern>
</servlet-mapping>
<!--DSerlvet-->
<servlet>
<servlet-name>DSerlvet</servlet-name>
<servlet-class>com.lagou.response.DServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DSerlvet</servlet-name>
<url-pattern>/dServlet</url-pattern>
</servlet-mapping>
请求转发与重定向的区别
1. 哪个对象
转发(request对象的方法)
request. getRequestDispatcher("/bServlet"). forward(request,response);重定向(response对象的方法)
response. sendRedirect("/day10_response/bServlet ");2. 几次请求
转发
地址栏: 没有改变
浏览器: 发了一次请求
服务器: 只有一对请求和响应对象
发生的位置: 服务器重定向
地址栏: 发生了改变
浏览器: 发了两次请求
服务器: 有两对请求和响应对象
发生的位置: 浏览器
3. 小结
写法
转发("/servlet资源路径") 服务器内部行为
重定向 ("/虚拟路径(项目名)/servlet资源路径") 浏览器外部行为使用场景(重点掌握)
如果需要传递数据(request域),使用转发
如果不需要传递数据(request域),使用重定向
7.4 响应中文
需求
向页面输出中文数据没有乱码
步骤分析
1. 通过response获取字符输出流
PrintWriter pw = response.getWriter();2. 通过字符输出输出文本
pw.write("中文....");
解决中文乱码
1. 指定服务器响应编码方式
response.setCharacterEncoding("GBK");2. 统一浏览器和服务器编码
response.setContentType("text/html;charset=utf-8");
package com.lagou.response;
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;
public class EncodeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置编码时,一定要写在首行
//resp.setCharacterEncoding("GBK");
// 统一浏览器和服务器编码
resp.setContentType("text/html;charset=utf-8");
// 向页面输出中文
PrintWriter writer = resp.getWriter();
writer.write("中文..");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--EncodeServlet-->
<servlet>
<servlet-name>EncodeServlet</servlet-name>
<servlet-class>com.lagou.response.EncodeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EncodeServlet</servlet-name>
<url-pattern>/encodeServlet</url-pattern>
</servlet-mapping>
八 ServletContext
8.1 概述
web容器(tomcat)在启动时,它会为每个web项目承建一个对应的ServletContext对象
它代表:当前web项目
主要作用
1. 域对象(共享数据)
2. 获取资源在服务器的真实地址
3. 获取全局的配置参数
4. 获取文件MIME类型
获取ServletContext对象
1. 通过request对象获得
ServletContext sc = request.getServletContext();
2. 继承HttpServlet后,可以直接调用
ServletContext sc = this.getServletContext();
8.2 域对象(共享数据)
在当前项目范围内,共享数据(多个servlet都可以获取)
1. 存储数据
void setAttribute(String name,Object value)
2. 获取数据
Object getAttribute(String name)
3. 删除数据
void removeAttribute(String name)
package com.lagou.servletContext;
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;
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 向servletContext域对象中存入数据
// ServletContext servletContext1 = this.getServletContext(); 因为继承了HttpServlet, 所以下面的也可
ServletContext servletContext = req.getServletContext();
servletContext.setAttribute("user","jack"); // 如果two比one先执行, 那么two中获取user时结果为null
System.out.println("OneServlet中存入了数据....");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.lagou.servletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 从servletContext域中取出数据
String user = (String) req.getServletContext().getAttribute("user");
System.out.println("TwoServlet中取出的数据为" + user); // 如果two比one先执行, 那么two中获取user时结果为null
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--OneSerlvet-->
<servlet>
<servlet-name>OneServlet</servlet-name>
<servlet-class>com.lagou.servletContext.OneServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>OneServlet</servlet-name>
<url-pattern>/oneServlet</url-pattern>
</servlet-mapping>
<!--TwoSerlvet-->
<servlet>
<servlet-name>TwoServlet</servlet-name>
<servlet-class>com.lagou.servletContext.TwoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TwoServlet</servlet-name>
<url-pattern>/twoServlet</url-pattern>
</servlet-mapping>
生命周期
1. 何时创建?
项目加载时,创建2. 何时销毁?
项目卸载时,销毁3. 作用范围?
与项目共存亡(多个servlet都可以操作它)
8.3 获取资源在服务器的真实地址
可以实现web项目的移植性...动态获取文件真实路径
package com.lagou.servletContext;
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;
public class RealpathServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取lagou.jpg文件的真实路径
ServletContext servletContext = req.getServletContext();
// 使用getRealPath方法
String realPath = servletContext.getRealPath("/img/lagou.jpg");
System.out.println(realPath);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--RealpathServlet-->
<servlet>
<servlet-name>RealpathServlet</servlet-name>
<servlet-class>com.lagou.servletContext.RealpathServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RealpathServlet</servlet-name>
<url-pattern>/realpathServlet</url-pattern>
</servlet-mapping>
8.4 获取全局的配置参数
读取web.xml配置文件中标签信息,实现参数和代码的解耦(多个servlet都可以获取)
<!--全局配置参数:所有的servlet都可以读取...-->
<context-param>
<param-name>encode</param-name>
<param-value>UTF-8</param-value>
</context-param>
package com.lagou.servletContext;
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;
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// servletContext获取到全局配置参数
String encode = req.getServletContext().getInitParameter("encode");
System.out.println("获取到的全局配置参数-"+ encode);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.lagou.servletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String encode = req.getServletContext().getInitParameter("encode");
System.out.println("获取到的全局配置参数-"+ encode);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
8.5 获取文件MIME类型
在互联网通信过程中定义的一种文件数据类型格式
格式: 大类型/小类型 例如: text/html image/jpeg
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/servlet_demo/mimeServlet?fileName=a.jpg">获取文件的mime类型</a>
</body>
</html>
package com.lagou.servletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MimeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取指定文件的mime类型
// servlet_demo/mimeServlet?fileName=a.jpg
// 获取请求参数
String fileName = req.getParameter("fileName");
// 获取文件的mime类型
String mimeType = req.getServletContext().getMimeType(fileName);
resp.getWriter().write(fileName + "----" + mimeType);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--MimeServlet-->
<servlet>
<servlet-name>MimeServlet</servlet-name>
<servlet-class>com.lagou.servletContext.MimeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MimeServlet</servlet-name>
<url-pattern>/mimeServlet</url-pattern>
</servlet-mapping>
8.6 案例:统计网站的访问次数
需求 显示你是第几位访问此网站..
package com.lagou.servletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CountServlet extends HttpServlet {
@Override
public void init() throws ServletException {
// 向servletContext域中存入变量count,并且初始值为0
// 必须在web.xml中设置启动服务器就自动实例化的 load-on-startup 标签
this.getServletContext().setAttribute("count",0);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 设置响应编码
resp.setContentType("text/html;charset=utf-8");
//2. 向页面响应信息
resp.getWriter().write("<h1>拉勾博客</h1>");
//3.进行servletContext域中的取值 取 加 存 0
// 取
Integer count = (Integer) this.getServletContext().getAttribute("count");
// 加
count++;
resp.getWriter().write("<dev>你是,第"+ count + "位访问此网站的人....</dev>");
// 存
this.getServletContext().setAttribute("count",count);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--CountServlet-->
<servlet>
<servlet-name>CountServlet</servlet-name>
<servlet-class>com.lagou.servletContext.CountServlet</servlet-class>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CountServlet</servlet-name>
<url-pattern>/countServlet</url-pattern>
</servlet-mapping>