Servlet
大家好呀,我是小笙,我和大家分享下我学习Javaweb的笔记
Servlet
概述
概述:Servlet(Server Applet),全称Java Servlet。是用Java编写的服务器端程序,其主要功能在于交互式地浏览和修改数据,生成动态Web内容
Servlet的特点
-
浏览器的多次请求Servlet资源 ,通常情况下,服务器只会创建一个 Servlet 实例对象, 也就是说 Servlet 实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至 web 容器退出或者 redeploy web 应用,servlet 实例对象才会销毁
-
是由服务器调用和执行的Java 程序 ,不能独立运行
-
按照Servlet规范开发的(实现了Servlet接口)
-
在Servlet 的整个生命周期内,init 方法只被调用一次。而对每次请求都调用一次service 方法
Servlet 基本使用
servlet3.0 前使用 web.xml , servlet3.0 版本以后(包括 3.0)支持注解, 同时支持 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">
<!--web.xml主要用于配置该web应用使用到的的Servlet-->
<!--配置HelloServlet-->
<!--
servlet-class: Servlet所在的全类名路径
url-pattern: 浏览器访问该Servlet的路径
servlet-name: 启到桥梁的作用,名字可以自己定义,但是必须唯一
-->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.al_tair.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
</web-app>
/**
* 开发一个Servlet需要实现该接口
*/
public class HelloServlet implements Servlet {
/**
* 初始化Servlet
* 当Tomcat创建HelloServlet示例时,会调用init方法
* 该方法只能被嗲用一次
*
*/
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
/**
* 返回Servlet的配置
*/
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* Service方法 处理浏览器的请求(get或者post)
* 当浏览器每次请求Servlet时候,就会调用该方法
* 当tomcat调用该方法时,会把http请求的数据封装成实现了ServletRequest接口的request对象
* @param servletRequest 通过servletRequest获取用户提交的数据
* @param servletResponse 用于返回数据给tomcat,再返回给浏览器
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
/**
* 返回Servlet的信息
*/
@Override
public String getServletInfo() {
return null;
}
/**
* 该方法是在servlet销毁的时候的调用
* 只能被调用一次
*/
@Override
public void destroy() {
}
}
Servlet 生命周期
示意图
init()初始化阶段
Servlet 容器(比如: Tomcat)加载 Servlet,加载完成后,Servlet 容器会创建一个 Servlet 实例 并调用 init()方法,init()方法只会调用一次,
Tomcat服务器在下面的情况装载 Servlet实例:
-
Servlet 容器(Tomcat)启动时自动装载某些 servlet,实现这个需要在 web.xml 文件中添加 1
<servlet> <servlet-name>helloServlet</servlet-name> <servlet-class>com.al_tair.servlet.HelloServlet</servlet-class> <!-- 1 表示装载的顺序,默认为-1不会自动装载 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>helloServlet</servlet-name> <url-pattern>/helloServlet</url-pattern> </servlet-mapping>
-
在 Servlet 容器(Tomcat)启动后,浏览器首次向 Servlet资源发送http请求
service()处理浏览器请求阶段
-
Tomcat每收到一个http请求,将会产生一个新的线程去处理servlet实例
-
创建一个用于封装http请求消息的ServletRequest对象和一个代表http响应消息的ServletResponse对象
@Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {}
destroy()终止阶段
当Servlet 容器终止运行,或者Servlet类重新装载时,会调用destroy() 方法
HttpServlet
框架图
代码示例
<?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>hiHttpServlet</servlet-name>
<servlet-class>com.al_tair.servlet.HiHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hiHttpServlet</servlet-name>
<url-pattern>/hiHttpServlet</url-pattern>
</servlet-mapping>
</web-app>
public class HiHttpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HttpServletRequest doGet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HttpServletRequest doPost");
}
}
// 源码分析到底是如何调用doGet和doPost方法
// HttpServlet类重写了Servlet接口中的Service方法
// 本质还是调用Service方法,只不过底层封装了该方法
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
// 根据动态绑定机制,会调用HiHttpServlet类中的doGet方法
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
// 如果我们不重写doGet和doPost方法,就会去调用HttpServlet类中的这两个方法,显示效果如下
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_put_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(405, msg);
} else {
resp.sendError(400, msg);
}
}
Servlet 注解方式
@WebServlet
示例代码
// 可以配置多个访问地址urlPatterns = {"/annotationServlet","/annotationServlet2"}
// urlPatterns 对应web.xml文件中的url-pattern
@WebServlet(urlPatterns = {"/annotationServlet"})
public class AnnotationServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
// @WebServlet注解源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
String name() default "";
String[] value() default {};
String[] urlPatterns() default {};
int loadOnStartup() default -1;
WebInitParam[] initParams() default {};
boolean asyncSupported() default false;
String smallIcon() default "";
String largeIcon() default "";
String description() default "";
String displayName() default "";
}
/**
* 可以通过配置web.xml找到该Servlet,同样也可以通过注解来实现
* 模拟Tomcat通过反射来得到注解的数据,进而匹配Servlet
*/
public class TestAnnotation {
public static void main(String[] args) throws ClassNotFoundException {
// 首先通过扫描包的形式,得到Servlet类的全路径
String filePath = "com.al_tair.servlet.annotation.AnnotationServlet";
// 反射得到注解并获取注解中的urlPatterns的值
Class cls = Class.forName(filePath);
WebServlet webServlet = (WebServlet)cls.getAnnotation(WebServlet.class);
String[] urls = webServlet.urlPatterns();
// 遍历urlPatterns的值,与http请求资源路径进行匹配
for (String url:urls
) {
System.out.println(url); /// annotationServlet
}
}
}
urlPattern 配置
精准匹配
@WebServlet(urlPatterns = {"/annotationServlet"})
目录匹配
// /annotationServlet/后添加任何字母都可以访问到
@WebServlet(urlPatterns = {"/annotationServlet/*"})
扩展名匹配
// 以annotationServlet为后缀的可以匹配
@WebServlet(urlPatterns = {"*.annotationServlet"})
任意匹配
// 任意匹配
@WebServlet(urlPatterns = {"/*"})
@WebServlet(urlPatterns = {"/"})
// 当Servlet配置了"/"或者"/*", 会覆盖tomcat的DefaultServlet,当其他的utl-pattern都匹配不上时,都会走DefaultServlet,一旦拦截,静态资源不能处理
<!-- DefaultServlet 在Tomcat/conf/web.xml中配置 -->
<!-- The default servlet for all web applications, that serves static resources -->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<!-- 默认自启动 -->
<load-on-startup>1</load-on-startup>
</servlet>
优先级
精准匹配 > 目录匹配 > 扩展名匹配 > 任意匹配 > /* > / > 默认匹配(DefaultServlet)
ServletConfig
ServletConfig类是为Servlet程序配置信息的类,ServletConfig对象由Tomcat创建
// GenericServlet父类
// 如果该init方法没有被重写,就会默认调用父类GenericServlet的该方法
// 这个时候Tomcat在初始化的时候传入了ServletConfig对象
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
测试代码
假设我们要读取配置文件中的数据库数据
<?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>DBServlet</servlet-name>
<servlet-class>com.al_tair.servletConfig.DBServlet</servlet-class>
<!--配置连接数据库的用户名和密码-->
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>pwd</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DBServlet</servlet-name>
<url-pattern>/dbServlet</url-pattern>
</servlet-mapping>
</web-app>
public class DBServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletConfig servletConfig = getServletConfig();
String username = servletConfig.getInitParameter("username");
System.out.println(username);
String pwd = servletConfig.getInitParameter("pwd");
System.out.println(pwd);
}
}
// getServletConfig()源码分析
// 初始化的时候默认传入了ServletConfig对象,并让属性config获取该对象地址的引用
// 然后通过get方法供子类调用获取该配置对象进而获取配置对象的数据
private transient ServletConfig config;
public ServletConfig getServletConfig() {
return this.config;
}
ServletContext
基本介绍
-
ServletContext是一个接口,用来解决Servlet对象之间的数据交互,因此也被称作域对象
-
一个web工程,只有一个 ServletContext 对象实例,ServletContext 对象是在 web 工程启动的时候创建,在 web 工程停止的时销毁
-
ServletContext 对象可以通过 ServletConfig.getServletContext 方法获得对 ServletContext 对象的引用
// 父类GenericServlet有该对象的引用 // 因此也可以通过 this.getServletContext()来获得其对象的引用 public ServletContext getServletContext() { return this.getServletConfig().getServletContext(); }
应用实例-获取工程相关信息
- 获取 web.xml 中配置的上下文参数 context-param
- 获取当前的工程路径,格式: /工程路径
- 获取工程部署后在服务器硬盘上的绝对路径
<?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">
<!--ServletContext-->
<servlet>
<servlet-name>ServletContextDemo</servlet-name>
<servlet-class>com.al_tair.servletContext.ServletContextDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletContextDemo</servlet-name>
<url-pattern>/servletContext</url-pattern>
</servlet-mapping>
<!-- 配置整个网站的信息 -->
<context-param>
<param-name>website</param-name>
<param-value>https://github.com/steven-beep</param-value>
</context-param>
<context-param>
<param-name>school</param-name>
<param-value>XXXXXXX</param-value>
</context-param>
</web-app>
public class ServletContextDemo extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
// 1.获取 web.xml 中配置的上下文参数 context-param
String website = servletContext.getInitParameter("website");
String school = servletContext.getInitParameter("school");
System.out.println(website);
System.out.println(school);
// 2.获取当前的工程路径,格式: /工程路径
String contextPath = servletContext.getContextPath();
System.out.println(contextPath);
// 3.获取工程部署后在服务器硬盘上的绝对路径
String realPath = servletContext.getRealPath("/");
System.out.println(realPath);
}
}
应用实例 2-简单的网站访问次数计数器
<?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>
<servlet-name>Servlet1</servlet-name>
<servlet-class>com.al_tair.servletContext.Servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet1</servlet-name>
<url-pattern>/servlet1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Servlet2</servlet-name>
<servlet-class>com.al_tair.servletContext.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet2</servlet-name>
<url-pattern>/servlet2</url-pattern>
</servlet-mapping>
</web-app>
// Servlet1 和 Servlet2的代码相同
public class Servlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
Integer count = (Integer) servletContext.getAttribute("count");
if(count == null){
servletContext.setAttribute("count",1);
count = 1;
}else{
servletContext.setAttribute("count",++count);
}
System.out.println("Servlet1访问,共访问次数: " + count);
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("<h1>共访问次数: "+ count + "</h1>");
writer.flush();
writer.close();
}
}
HttpServletRequest
当客户端/浏览器通过 HTTP 协议访问服务器时,HTTP 请求头中的所有信息都封装在这个对象
常用方法
测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="http://localhost:9999/servlet/requestMethod" method="get">
<div align="center">
<h1 align="center">表单</h1>
用户名<input type="text" name="username"/><br>
密 码<input type="password" name="pwd"/><br>
<input type="checkbox" name="hobby" value="zq">足球
<input type="checkbox" name="hobby" value="lq">篮球
<input type="checkbox" name="hobby" value="pq">排球<br/>
<button type="submit">提交表单</button>
</div>
</form>
</body>
</html>
@WebServlet(urlPatterns = {"/requestMethod"})
public class RequestMethod extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// getRequestURI() 获取请求的资源路径
String requestURI = req.getRequestURI();
System.out.println(requestURI); // /servlet/requestMethod
// getRequestURL()获取请求的统一资源定位符(绝对路径)
StringBuffer requestURL = req.getRequestURL();
System.out.println(requestURL); // http://localhost:9999/servlet/requestMethod
// getRemoteHost()获取客户端/浏览器的主机
String remoteHost = req.getRemoteHost();
System.out.println(remoteHost ); // 127.0.0.1
// getHeader()获取请求头
String header = req.getHeader("Accept");
// text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,
// image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
System.out.println(header);
// getParameter()获取请求的参数
// 注意解码url编码,不会会出现中文乱码(并且要写在接受数据前)
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String pwd = req.getParameter("pwd");
System.out.println(username); // Al_tair
System.out.println(pwd); // 123456
// getParameterValues()获取请求的参数(多个值的时候使用), 比如checkbox,返回数组
String[] hobbies = req.getParameterValues("hobby");
for (String hobby: hobbies
) {
System.out.println(hobby); // zq lq
}
// getMethod()获取请求的参数
System.out.println(req.getMethod()); // GET
// setAttribute(key, value)设置域数据
req.setAttribute("count",2);
// getAttribute(key)获取域数据
Integer count = (Integer)req.getAttribute("count");
System.out.println(count); // 2
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
请求转发
概述:请求转发指一个 web 资源收到客户端请求后,通知服务器去调用另外一个 web 资源进行处理
- HttpServletRequest 对象提供了一个 getRequestDispatcher 方法,该方法返回一个 RequestDispatcher 对象,调用这个对象的 forward 方法可以实现请求转发
- HttpServletRequest 对象是一个域对象(共享对象),可以通过 HttpServletRequest 对象在实现转发时,把数据通过 HttpServletRequest 对象带给其它 web 资源处理,可以使用如下方法
- setAttribute方法
- getAttribute方法
- removeAttribute方法
- getAttributeNames方法
请求转发原理
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:9999/servlet/checkServlet" method="get">
<h1>检查是否该用户为管理员</h1>
用户名<input type="text" name="username"><br/>
<button type="submit">按钮</button>
</form>
</body>
</html>
<?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>CheckServlet</servlet-name>
<servlet-class>com.al_tair.HttpServletRequest.CheckServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CheckServlet</servlet-name>
<url-pattern>/checkServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ManageServlet</servlet-name>
<servlet-class>com.al_tair.HttpServletRequest.ManageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ManageServlet</servlet-name>
<url-pattern>/manageServlet</url-pattern>
</servlet-mapping>
</web-app>
// CheckServlet
public class CheckServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
if(username.equals("tom")){
request.setAttribute("role", "管理员");
}else{
request.setAttribute("role", "普通用户");
}
// 获取分发器
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/manageServlet");
// 表示把当前CheckServlet的request对象和response对象,传递给ManageServlet使用
requestDispatcher.forward(request, response);
}
}
// ManageServlet
public class ManageServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String role = (String)request.getAttribute("role");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("用户名: " + username + "<br/>");
writer.print("角色 : " + role);
writer.flush();
writer.close();
}
}
注意事项
- 浏览器访问资源地址不会变化(都是第一个资源的url)
- 因为浏览器地址栏会停止在第一个资源地址,如果你刷新页面,会再次发出请求(并且会带数据), 所以在支付页面的时候,不要使用请求转发,否则会造成重复支付的问题
- 在同一次 HTTP 请求中,进行多次转发,多个 Servlet 可以共享 request 域/对象的数据(因为始终是同一个 request 对象)
- 可以转发到 WEB-INF 目录下的资源(该目录资源无法通过浏览器直接访问)
- 不能访问当前 WEB 工程外的资源
HttpServletResponse
概念:每次 HTTP 请求,Tomcat 会创建一个 HttpServletResponse 对象传递给Servlet
作用:主要用于响应浏览器,返回数据给浏览器
常用方法
// 父接口ServletResponse的方法
// 字节流,常用于下载文件
ServletOutputStream getOutputStream() throws IOException;
// 字符流,常用于传输字符串
PrintWriter getWriter() throws IOException;
// 注意:字节流和字符流在同一个时间段只能使用其中一个
// 用于处理中文乱码(本质没有区别)
// 方法一
response.setCharacterEncoding("utf-8"); // 设置服务器字符集为utf-8
response.setHeader("ContentType","text/html;charset=utf-8"); // 设置浏览器使用该字符集
// 方法二
response.setContentType("text/html;charset=utf-8");
请求重定向
概念:一个 web 资源收到客户端请求后,通知客户端去访问另外一个 web 资源
重定向的两种方式
// 方式1
response.sendRedirect("/servlet/xxServlet");
// 方式2
response.setStatus(302);
response.setHeader("Location","/servlet/xxServlet");
示例代码
-
编写一个 MyPayServlet , 能够接收到提交的数据
-
编写一个简单的支付页面 pay.html
-
如果支付金额大于 100, 则重定向到 payok.html, 否则重定向到原来的 pay.html
<!-- pay.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>支付页面</title></head>
<body>
<h1>支付页面</h1> <!--注意:这里 action="/servlet/myPayServlet"的第一/被浏览器解析从浏览器地址栏的 主机-->
<form action="/homework/myPayServlet" method="get">
用户编号: <input type="text" name="userid"><br/>
支付金额: <input type="text" name="money"><br/>
<input type="submit" value="点击支付"></form>
</body>
</html>
<!-- payok.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>支付成功</title></head>
<body><h1>恭喜你,支付成功~</h1></body>
</html>
@WebServlet(name = "HttpServletResponse",urlPatterns = {"/myPayServlet"})
public class myPayServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws ServletException, IOException {
String money = request.getParameter("money");
String contextPath = getServletContext().getContextPath();
if(Integer.parseInt(money) > 100){
response.sendRedirect(contextPath + "/payok.html");
}else{
response.sendRedirect(contextPath + "/pay.html");
}
}
}
注意细节
-
最佳应用场景:网站迁移,比如原域名是 XXX.com 迁移到 XXX.cn ,但是百度抓取的还是原来网址
-
浏览器地址会发生变化,不能共享 Request 域中的数据,本质是两次 http 请求
-
不能重定向到 /WEB-INF 下的资源
-
可以重定向到 Web 工程以外的资源