开发工具专栏
上篇接tomcat
历史简单篇tomcat,servlet
Servlet介绍
Servlet是Server Applet的简称,称为服务端小程序,是JavaEE平台下的技术标准,基于Java语言编写的服务端程序。Web容器或应用服务器实现了Servlet标准所以Servlet需运行在Web容器或应用服务器中。Servlet主要功能在于能在服务器中执行并生成数据。
Servlet技术特点
Servlet使用单进程多线程方式运行。
Servlet在应用程序中的位置
两个图来展示,帮助我们理解
静态资源和动态资源区分
静态资源:每次访问都不需要运算,直接就可以返回的资源,如HTML CSS JS多媒体文件等等,每次访问获得的资源都是一样的
动态资源:每次访问都需要运算代码生成的资源,如Servlet JSP ,每次访问获得的结果可能都是不一样的
Servlet作为一种动态资源技术,是我们后续学习框架的基础
Servlet在程序中到底处于一个什么地位?
Servlet是可以接受Http请求并作出相应的一种技术,是JAVA语言编写的一种动态资源
Servlet是前后端衔接的一种技术,不是所有的JAVA类都可以接收请求和作出相应,Servlet可以
在MVC模式中,Servlet作为Controller层(控制层)主要技术,用于和浏览器完成数据交互,控制交互逻辑
案例:
在后台随机生成一个整数当浏览器请求一个Servlet时 如果生成的是奇数,返回"happy new year"如果生成的是偶数,返回"happy birthday"1创建一个JAVAWEB项目,并在项目中开发一个自己的Servlet ,继承HttpServlet类
一定要查看External Libraries中有Tomcat中的两个JAR jsp-api servlet-api
如果我们想获得请求中的信息,就要通过HttpServetRequest对象获得
如果我们想给浏览器响应一些信息,就要通过HttpServletResponse对象响应
4在web.xml中配置Servlet的映射路径
上述图片我们设置的访问路径为localhost:/xxx
当我们访问项目名的时候为什么默认访问的是index.html呢?我们找到tomcat目录下conf/web.xml文件最后面可以看到,他帮我默认配置了输入了项目名访问的路径
假如我们想自定义默认路径可以在项目中的web.xml文件中进行配置
查找顺序是从上往下进行查找
案例开发需求
准备一个登录页,可以输入用户名和密码
输入完毕后向后台Servlet提交用户名和密码
Servlet接收到用户名和密码之后,校验是否正确
如果正确响应Success
如果不正确响应Fail
开发过程如下
在webapp文件夹下创建login.xml
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form method="get" action="loginServlet.do">
<table style="margin: 0px auto" width="300px" cellpadding="0px" cellspacing="0px" border="1px">
<tr><td>用户名td><td><input type="text" name="username">td>tr>
<tr><td>密码td><td><input type="password" name="pwd">td>tr>
<tr align="center"><td colspan="2"><input type="submit" value="登录">td>tr>
table>
form>
body>
html>
我们在web.xml文件中配置login.xml为根目录
<welcome-file-list>
<welcome-file>login.htmlwelcome-file>
welcome-file-list>
创建LoginServlet 类继承HttpServlet并重写service方法
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.err.println("进入了servlet");
//获取请求中的数据
String username = req.getParameter("username");
String pwd = req.getParameter("pwd");
//判断数据
String message = null;
if(username.equals("123") && pwd.equals("123")){
message = "Success";
}else{
message = "Fail";
}
//作出响应
resp.getWriter().write(message);
}
}
from表单中的action属性需要配置访问路径
我们在web.xml中配置LoginServlet 访问路径"/loginServlet.do"
<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>loginServletservlet-name>
<servlet-class>com.msr.demo_servlet.servlet.LoginServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>loginServletservlet-name>
<url-pattern>/loginServlet.dourl-pattern>
servlet-mapping>
<welcome-file-list>
<welcome-file>login.htmlwelcome-file>
welcome-file-list>
web-app>
运行测试
http://localhost:9008/demo_servlet_war_exploded/
get方式提交的请求数据通过地址栏提交没有请求体
post方式提交请求数据单独放到请求体中,
请求时所携带的数据(post方式)
post和get方式提交请求的差别(面试重要)
HttpServletRequest对象代表客户端浏览器的请求,当客户端浏览器通过HTTP协议访问服务器时,HTTP请求中的所有信息都
会被Tomcat所解析并封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。
测试代码
System.out.println("完整的URL:"+req.getRequestURL());//返回客户端浏览器发出请求时的完整URL。
System.out.println("请求的指定资源:"+req.getRequestURI());//返回请求行中指定资源部分。
System.out.println("客户端的IP:"+req.getRemoteAddr());//返回发出清求的客户机的IP地址。
System.out.println("WEB服务器IP:"+req.getLocalAddr());//返回WEB服务器的IP地址。
System.out.println("服务器端处理HTTP请求的端口:"+req.getLocalPort());//返回WEB服务器处理Http协议的连接器所监听的端口。
System.out.println("主机名:"+req.getLocalName());
System.out.println("客户端PORT:"+req.getRemotePort());
System.out.println("当前项目部署名:"+req.getContextPath());
System.out.println("协议名:"+req.getScheme());
System.out.println("请求方式:"+req.getMethod());
打印结果
完整的URL:http://localhost:9008/demo_servlet_war_exploded/loginServlet.do
请求的指定资源:/demo_servlet_war_exploded/loginServlet.do
客户端的IP:0:0:0:0:0:0:0:1
WEB服务器IP:0:0:0:0:0:0:0:1
服务器端处理HTTP请求的端口:9008
主机名:0:0:0:0:0:0:0:1
客户端PORT:49648
当前项目部署名:/demo_servlet_war_exploded
协议名:http
请求方式:GET
测试代码
String headerValue = req.getHeader("accept-encoding");//根据请求头中的key获取对应的value。
System.out.println(headerValue);
//早期的Iterator
Enumeration<String> headerNames = req.getHeaderNames();//获取请求头中所有的key,该方法返回枚举类型。
while(headerNames.hasMoreElements()){
String headerName = headerNames.nextElement();
System.out.println(headerName+":"+req.getHeader(headerName));
}
打印结果
gzip, deflate, br
host:localhost:9008
connection:keep-alive
pragma:no-cache
cache-control:no-cache
sec-ch-ua:"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"
sec-ch-ua-mobile:?0
sec-ch-ua-platform:"Windows"
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36
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.7
sec-fetch-site:same-origin
sec-fetch-mode:navigate
sec-fetch-user:?1
sec-fetch-dest:document
referer:http://localhost:9008/demo_servlet_war_exploded/
accept-encoding:gzip, deflate, br
accept-language:zh-CN,zh;q=0.9
进入了servlet
在Servlet获取请求数据的方式
req.getParameter(“key” );//根据key获取指定value。
String str = req.getParameter(“key”);
获取复选框(checkbox组件)中的值
eq.getParameterValues("checkboxkey );//获取复选框(checkbox组件)中的值,返回- -个String[I。
String[] userlikes = req.getParameterValues(“checkboxkey”);
获取所有提交数据的key
req.getParameterNames0);//获取请求中所有数据的key,该方法返回一个枚举类型。
Enumeration parameterNames = req.getParameterNames()
使用Map结构获取提交数据
req.getParameterMap0://获取请求中所有的数据并存放到一 个Map结构中,该方法返回一个Map,其中key为String类
型value为String[]类型。
Map
设置请求编码
req.setCharacterEncoding(“utf-8”)
请求的数据包基于字节在网络上传输,Tomcat接收到请求的数据包后会将数据包中的字节转换为字符。在Tomcat中使用的
是ISO-8859-1的单字节编码完成字节与字符的转换,所以数据中含有中文就会出现乱码,可以通req.setCharacterEncoding(“utf-8” )方法来对提交的数据根据指定的编码方式重新做编码处理。
测试代码
前段
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form method="get" action="myServlet">
<table style="margin: 0px auto" width="300px" cellpadding="0px" cellspacing="0px" border="1px">
<tr><td>用户名td><td><input type="text" name="username">td>tr>
<tr><td>密码td><td><input type="password" name="pwd">td>tr>
<tr><td>性别td>
<td>
男<input type="radio" name="gender" value="1" checked>
女<input type="radio" name="gender" value="0">
td>
tr>
<tr><td>爱好td>
<td>
<input type="checkbox" name="hobby" value="1">篮球
<input type="checkbox" name="hobby" value="2">足球
<input type="checkbox" name="hobby" value="3">羽毛球
<input type="checkbox" name="hobby" value="4">乒乓球
td>
tr>
<tr><td>个人简介td>
<td>
<textarea name="introduce">textarea>
td>
tr>
<tr>
<td>籍贯td>
<td>
<select name="provience">
<option value="1">京option>
<option value="2">津option>
<option value="3">冀option>
select>
td>
tr>
<tr align="center"><td colspan="2"><input type="submit" value="提交数据">td>tr>
table>
form>
body>
html>
web.html
<servlet>
<servlet-name>myServletservlet-name>
<servlet-class>com.msr.demo_servlet.servlet.MyServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>myServletservlet-name>
<url-pattern>/myServleturl-pattern>
servlet-mapping>
后端
public class MyServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// req获取参数
//如果前端发过米的数据由教构名但是没有值,getParameter 返回的是一个空字符申 ""
//获取的参数在提交的数据中名都没有,getParameter返回的是null
String username = req.getParameter("username");
System.out.println("username:"+username);
System.out.println("password:"+req.getParameter("pwd"));
System.out.println("gender:"+req.getParameter("gender"));
//hobby=1&hobby=2&hobby=3 想要获得多个同名的参数 getParameterValues返回的是一个String数组
//获取的参数在提交的数据中名都没有,getParameterValues返回的是null
String[] hobbies = req.getParameterValues("hobby");
System.out.println("hobbies:"+ Arrays.toString(hobbies));
//textarea
System.out.println("introduce:"+req.getParameter("introduce"));
//select
System.out.println("provience:"+req.getParameter("provience"));
System.out.println("-----------------------------------------");
//如果不知道参数的名字?
//获取所有的参数名
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()){
String pname = parameterNames.nextElement();
String[] parameterValues = req.getParameterValues(pname);
System.out.println(pname+":"+Arrays.toString(parameterValues));
}
System.out.println("---------------------------------------");
Map<String, String[]> parameterMap = req.getParameterMap();
Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
for (Map.Entry<String, String[]> entry : entries) {
System.out.println(entry.getKey()+":"+Arrays.toString(entry.getValue()));
}
}
}
输出
username:aaa
password:123
gender:1
hobbies:[1, 2, 3]
introduce:111
provience:2
-----------------------------------------
username:[aaa]
pwd:[123]
gender:[1]
hobby:[1, 2, 3]
introduce:[111]
provience:[2]
---------------------------------------
username:[aaa]
pwd:[123]
gender:[1]
hobby:[1, 2, 3]
introduce:[111]
provience:[2]
响应行
响应状态码列表如下
响应头
Content-Type:响应内容的类型(MIME)
响应实体
服务器响应回来的内容
HttpServletResponse对象代表服务器的响应。这个对象中封装了响应客户端浏览器的流对象,以及向客户端浏览器响应的响应头、响应数据、响应状态码等信息。
响应的设置
ContentType响应头
resp.setContentType(“MIME”);//该方法可通过MIME-Type设置响应类型。
MIME的全称是Multipurpose Internet Mail Extensions,即多用途互联网邮件扩展类型。
这是HTTP协议中用来定义文档性质及格式的标准。对HTTP传输内容类型进行了全面定义。
服务器通过MIME告知响应内容类型,而浏览器则通过MIME类型来确定如何处理文档。
代码
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//行相关信息
resp.setStatus(500);
//头相关信息
resp.setHeader("Date","2022-2-2");
resp.setHeader("aaa","xxx");
//Content-Type响应头 响应给浏览器的MIME类型
// 如果想知道都可以响应什么类型可以去tomcat的web.xml文件中查看 大概650行开始,有很多
resp.setHeader("Content-Type","text/html");
//体相关信息
PrintWriter writer = resp.getWriter();
writer.write("this is tag h1"
);
}
tomcat有三个打印日志的地方
Server乱码
修改
找到tomcat中的日志配置文件编码改为GBK
需要手动进行编码解码,或者设置tomcat中的server.xml中的URL编码,tomcat9已经解决了该问题
1.init(),创建Servlet对象后立即调用该方法完成其他初始化工作。
2.getServletConfig(),ServletConfig是容器向servlet传递参数的载体。
3.service(),处理客户端请求,执行业务操作,利用响应对象响应客户端请求。
4.getServletlnfo(),获取servlet相关信息
5.destroy(),在销毁Servlet对象之前调用该方法,释放资源。
Servlet运行期间,需要一些辅助信息,这些信息可以在web.xml文件中,使用一个或多个元素,进行配置。当Tomcat初始化一个Servlet时,会将该Servlet的配置信息,封装到一个ServletConfig对象中,通过调用init(ServletConfig config)方法,将ServletConfig对称传递给Servlet
GenericServlet是实现了Servlet接口的抽象类。在GenericServlet中进一步的定义了Servlet接口的具体实现,其设计的目的是为了和应用层协议解耦,在GenericServlet中包含一个Service抽象方法。我们也可以通过继承GenericServlet并实现Service方法实现请求的处理,但是需要将ServletReuqest和ServletResponse转为HttpServletRequest和HttpServletResponse。
继承自GercSenvlt.针对于处理HTP协议的青求所定制。在Httpendeb的sevcel)方法中已经把Se veReucet和Se verRspone转为HtperveBleuest和Htpservrtrkesponse。直按使甲用HtoSenveEkeqest和HttpServletResponse,不再需要强转。实际开发中,直接继承HttpServlet,并根据请求方式复写doXx()方法即可。
在我们自定义的Servlet中,如果想区分请求方式不同的请求方式使用不同的代码处理,那么我么重写doGet doPost即可如果我们没有必要区分请求方式的差异,那么我们直接重写service方法即可
Servlet的生命周期是由容器管理的,分别经历四各阶段:
>阶段 次数 时机
>创建 1次 第一次请求
>初始化 1次 实例化之后
>执行服务 多次 每次请求
>销毁 一次 停止服务
当客户端浏览器第一次请求Servlet时,容器会实例化这个Servlet,然后调用一次init方法,并在新的线程中执行service方法处理请
求。service方法执行完毕后容器不会销毁这个Servlet而是做缓存处理,当客户端浏览器再次请求这个Servlet时,容器会从缓存中直接找到这个Servlet对象,并再一次在新的线程中执行Service方法。当容器在销毁Servlet之前对调用一次destory方法。
注意:
在Serlvet中我们一般不要轻易使用成员变量!!! 可能会造成线程安全问题
如果要使用的话,应该尽量避免对成员变量产生影响修改
如果要产生影响我们应该注意线程安全问题
如果我们自己添加线程安全编码处理,会严重影响效率
综上所述:原则,能不用成员变量就不用!!!
假如servlet的初始化时间比较长,这就会导致我们第一次访问页面的时候会等待较长的时间,这样我们可以在web.xml文件中配置servlet自动初始化,这样他就会在tomcat启动的时候进行初始化
设置初始化顺序从6开始,前五个被tomcat使用了
<servlet>
<servlet-name>myServletservlet-name>
<servlet-class>com.msr.demo_servlet.servlet.MyServletservlet-class>
<load-on-startup>6load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>myServletservlet-name>
<url-pattern>/myServleturl-pattern>
servlet-mapping>
ServletContext官方叫Servlet上下文。服务器会为每一个Web应用创建一个ServletContext对象。这个对象全局唯一,而且Web应用中的所有Servlet都共享这个对象。所以叫全局应用程序共享对象
获取项目的部署名
context.getContextPath()
相对路径转绝对路径(文件上传下载时需要注意)
context.getRealPath(“path”)
该方法可以将一个相对路径转换为绝对路径,在文件上传与下载时需要用到该方法做路径的转换。获取容器的附加信息
servletContext.getServerlnfo()
返回Servlet容器的名称和版本号
servletContext.getMajorVersion()
返回Servlet容器所支持Servlet的主版本号servletContext.getMinorVersion()
返回Servlet容器所支持Servlet的副版本号。
代码
public class Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取Servlet对象的方式
//通过req对象
ServletContext servletContext1 = req.getServletContext();
//通过继承的方式
ServletContext servletContext2 = this.getServletContext();
System.out.println(servletContext1 ==servletContext2);
//获取当前项目的部署名
String contextPath= servletContext1.getContextPath();
System.out.println("contextPath"+contextPath);
//将一个相对路径转化为项目的绝对路径
String fileupload = servletContext1.getRealPath( "fileupload");
System.out.println(fileupload);
String serverInfo = servletContext1.getServerInfo();
System.out.println( "servletInfo"+serverInfo);
int majorversion = servletContext1.getMajorVersion();
int minorVersion = servletContext1.getMinorVersion();
System.out. println(majorversion+":"+minorVersion);
}
}
输出
true
contextPath/demo_servlet_war_exploded
D:\word\demo_servlet\target\demo_servlet-1.0-SNAPSHOT\fileupload
servletInfoApache Tomcat/8.5.45
3:1
web.xml文件
<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>Servlet1servlet-name>
<servlet-class>com.msr.demo_servlet.servlet.Servlet1servlet-class>
servlet>
<servlet-mapping>
<servlet-name>Servlet1servlet-name>
<url-pattern>/servlet1.dourl-pattern>
servlet-mapping>
web-app>
servletContext.getlnitParameter(“key”)
该方法可以读取web.xml文件中标签中的配置信息。servletContext.getInitParameterNames()
该方法可以读取web.xml文件中所有param-name标签中的值。
在web.xml中设置共享的数据
<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>usernameparam-name>
<param-value>123param-value>
context-param>
<context-param>
<param-name>passwordparam-name>
<param-value>456param-value>
context-param>
web-app>
通过servletContext获取web.xml中的数据
web.xml中数据会保存到ServletContext ,通过HttpServletRequest可以拿到上下文对象ServletContext
public class Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext1 = req.getServletContext();
String username = servletContext1.getInitParameter("username");
String password = servletContext1.getInitParameter("password");
System.out.println(username+":"+password);
}
}
servletContext.setAttribute(“key” ,ObjectValue)向全局容器中存放数据。
servletContext.getAttribute(“key”)从全局容器中获取数据。
servletContext.removeAttribute(“key”)根据key删除全局容器中的value。
ArrayList<Object> data = new ArrayList<>();
Collections.addAll(data,"张三","李四","王五");
servletContext1.setAttribute("list",data);
然后可以通过不同的servlet进行读取
ServletContext servletContext2 = req.getServletContext();
String username = servletContext2.getInitParameter("username");
String password = servletContext2.getInitParameter("password");
System.out.println(username+":"+password);
List<String> list =(List<String>) servletContext2.getAttribute("list");
System.out.println(list);
ServletConfig对象对应web.xml文件中的节点。当Tomcat初始化一个Servlet时,会将该Servlet的配置信息,封个ServletConfia对象中。我们可以通过该对象读取节点中的配置信息
servletConfig.getlnitParameter(“key”);
该方法可以读取web.xml文件中标签中标签中的配置信息。servletConfig.getInitParameterNames();
该方法可以读取web.xml文件中当前标签中所有标签中的值。
web.xml文件
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = this.getServletConfig();
System.out.println(servletConfig.getInitParameter("brand"));
}
精确匹配是指中配置的值必须与url完全精确匹配。
http://localhost:8080/demo/demo.do 匹配
http://localhost:8080/demo/suibian/demo.do 不匹配
在允许使用统配符“”作为匹配规则,“”表示匹配任意字符。在扩展名匹配中只要扩展名相同都会被匹配和路径无关。注意,在使用扩展名匹配时在中不能使用“r”,否则容器启动就会抛出异常。
http://localhost:8080/demo/demo.do 匹配
http://localhost:8080/demo/suibian/demo.do 匹配
根据请求路径进行匹配,在请求中只要包含该路径都匹配。"*"表示任意路径以及子路径。
http://localhost:8080/demo/suibian/demo.do 匹配
http://localhost:8080/demo/suibian/hehe/demo.do 匹配
http://localhost:8080/demo/hehe/demo.do 不匹配
匹配"/".匹配所有但不包含JSP页面
http://localhost:8080/demo/suibian.do 匹配
http://localhost:8080/demo/suibian.html 匹配
http://localhost:8080/demo/123/suibian.css 匹配
http://localhost:8080/demo/123/suibian.jsp 不匹配
http://localhost:8080/demo/suibian.do 匹配
http://localhost:8080/demo/suibian.html 匹配
http://localhost:8080/demo/123/suibian.css 匹配
http://localhost:8080/demo/123/suibian.jsp 匹配
当一个url与多个Servlet的匹配规则可以匹配时,则按照“精确路径>最长路径>扩展名”这样的优先级匹配到对应的Servlet。
案例分析
这里不做过多解释(与目录9.ServletContext和servletConfig原理一样)
//@WebServlet(urlPatterns = "Servlet1.do")
@WebServlet(urlPatterns = {"Servlet1.do","12.do"},
loadOnStartup = 6,
initParams = {@WebInitParam(name = "brand1",value = "123"),
@WebInitParam(name = "brand2",value = "321")
})
public class Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
1清空Response存放响应正文数据的缓冲区。
2如果目标资源为Servlet或JSP,就调用它们的service()方法,把该方法产生的响应结果发送到客户端;如果目标资源文件系统中的静态HTML文档,就读取文档中的数据把它发送到客户端。
forword处理特点:
1由于forword()方法先清空用于存放响应正文的缓冲区,因此源Servlet生成的响应结果不会被发送到客户端,只有目标资源生成的响应结果才会被发送到客户端。
2如果源Servlet在进行请求转发之前,已经提交了响应结(flushBuffer(),close()方法),那么forward()方法抛出lllegalStateException。为了避免该异常,不应该在源Servlet中提交响应结果。
代码
Servlet1
@WebServlet(name = "servlet1", value = "/servlet1.do")
public class Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet1.do");
String money = req.getParameter("money");
System.out.println("money:"+money);
resp.getWriter().println("asdasd");//响应无效 后边进行了转发
//请求转发给另一个组件
//获取请求转发器
RequestDispatcher requestDispatcher = req.getRequestDispatcher("servlet2.do");
//由请求转发器作出转发
requestDispatcher.forward(req,resp);
//在forward转发模式下,请求应该完全交给目标资源去处理,我们在源组件中,不要作出任何的响应处理
//在forward方法调用之后,也不要在使用req和resp对象做其他操作了
}
}
Servlet2
@WebServlet(name = "servlet2", value = "/servlet2.do")
public class Servlet2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet2.do");
String money = req.getParameter("money");
System.out.println("money:"+money);
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.println("支付宝到账:"+money+"元");
}
}
访问接口:http://localhost:9008/demo_servlet_war_exploded/servlet1.do?money=100
1如果目标资源为Servlet或JSP,就调用他们的相应的service()方法,把该方法产生的响应正文添加到源Servlet的响应结果中;如果目标组件为HTML文档,就直接把文档的内容添加到源Servlet的响应结果中。
2返回到源Servlet的服务方法中,继续执行后续代码块。
include()处理特点
include与forward转发相比,包含有以下特点:
1源Servlet与被包含的目标资源的输出数据都会被添加到响应结果中。2在目标资源中对响应状态码或者响应头所做的修改都会被忽略。
代码
Servlet1
@WebServlet(name = "servlet1", value = "/servlet1.do")
public class Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet1.do");
String money = req.getParameter("money");
System.out.println("money:"+money);
设置响应类型和编码(include模式下)
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//增加响应内容(include)
resp.getWriter().println("servlet1在转发之前做出相应内容");
//请求转发给另一个组件
//获取请求转发器
RequestDispatcher requestDispatcher = req.getRequestDispatcher("servlet2.do");
//由请求转发器作出转发
//equestDispatcher.forward(req,resp);
requestDispatcher.include(req,resp);
//继续增加响应内容(include)
resp.getWriter().println("servlet1在转发之后做出相应内容");
}
}
Servlet2
@WebServlet(name = "servlet2", value = "/servlet2.do")
public class Servlet2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet2.do");
String money = req.getParameter("money");
System.out.println("money:"+money);
//设置响应类型和编码(forward模式下)
// resp.setCharacterEncoding("UTF-8");
// resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println("支付宝到账:"+money+"元");
}
}
访问接口:http://localhost:9008/demo_servlet_war_exploded/servlet1.do?money=100
//在forward转发模式下,请求应该完全交给目标资源去处理,我们在源组件中,不要作出任何的响应处理
//在forward方法调用之后,也不要在使用req和resp对象做其他操作了
//在incLude较发模式下,设置响应可以在转发之前,也可以在转发之后
/*
*1请求转发是一种服务器的行为,是对浏览嚣器屏蔽
*2浏览器的地址栏不会发生变化
*3请求的参数是可以从源组件传递到目标组件的
*4请求对象和响应对象没有重新创建,而是传递给了目标组件*5请求转发可以帮助我们完成页面的跳转
*6请求转发可以转发至wEB-工NF里
*7请求转发只能转发给当前项目的内部资源,不能转发至外部资源
*8常用forward
**/
代码
Servlet3
@WebServlet(name = "servlet3", value = "/servlet3.do")
public class Servlet3 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet3");
String money = req.getParameter("money");
System.out.println("money:"+money);
//响应重定向
resp.sendRedirect("servlet4.do");
}
}
Servlet4
@WebServlet(name = "servlet4", value = "/servlet4.do")
public class Servlet4 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet4");
}
}
访问接口:http://localhost:9008/demo_servlet_war_exploded/servlet3.do?money=100
//响应重定向
resp.sendRedirect(s:"servlet4.do?money="+money);
//resp.sendRedirect("wEB-INF/bbb.htmL");
// resp.sendRedirect("https://www.baidu.com");
/*
*响应重定向总结
*1重定向是服务器给浏览器重新指定请求方向是一种浏览器行为地址栏会发生变化
* 2重定向时,请求对象和响应对象都会再次产生,请求中的参数是不会携带
*3重定向也可以帮助我们完成页面跳转
*4重定向不能帮助我们访问wEB-INF中的资源
*5重定向可以定向到外部资源
待编写
待编写
待编写