以下内容是我学习Servlet的一些笔记,用于方便自己复习
Servlet学习1.IDEA社区版创建Servlet2.Servlet生命周期3.HttpServlet类4.ServletConfig类5.ServletContext类6.HTTP协议的请求和响应7.HttpServletRequest类8.请求的转发9.base标签10.HttpServletResponse类11.请求重定向
1.IDEA社区版创建Servletidea的社区版与专业版相比,被阉割了许多功能,它没有web,spring等功能,这对我们进行web开发有很大的限制,不过,我们可以通过Maven来创建一个web项目,下面演示如何使用Maven创建web项目并访问servlet
1.点击新建,选择项目,然后点击Maven,选择从archetype创建中的webapp
2.点击下一步,然后可以修改项目名称和组ID
3.再点击下一步,修改用户设置文件和本地仓库,点击完成
4.我们创建完后的项目结构如下图,如果有欠缺目录的话,也按下面的目录格式补全所需的目录(target目录不需要,编译后会自动生成)
5.打开web.xml,进行修改,修改为以下代码
Archetype Created Web Application Test Test Test /hello
其中下面这段代码描述了Servlet类和路径的对照关系
Test Test Test /hello
如果下面这段代码爆红,可以右键,然后选择忽略外部资源
打开pom.xml,然后添加下列依赖,添加的依赖不完全相同,要看你使用的Tomcat版本,我这里使用的是Tomcat10
jakarta.servlet.jsp jakarta.servlet.jsp-api 3.0.0 provided jakarta.servlet jakarta.servlet-api 5.0.0 provided
6.编写main目录下的java目录下的Test.java
import jakarta.servlet.*;
import java.io.IOException;
public class Test implements Servlet{
public static void main(String[]args){
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello world");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
因为我使用的是Tomcat10版本,所以引入的包是jakatra,如果是其他的Tomcat版本,引入的包可能是javax,这里插句题外话,javaEE目前最高版本问javaEE8,javaEE被Oracle捐献给了Apache了,Apache将javaEE该名为jakartaEE,javaEE8版本升级之后的javaEE9不再是javaEE9这个名字,而叫作jakartaEE9。javaEE8时对应的Servlet类名为:javax.servlet.Servlet,而jakartaEE9时 Servlet类名为:jakarta.servlet.Servlet,如果之前的项目还是使用javax.servlet.Servlet,那么该项目无法部署到Tomcat10版本,只能部署到Tomcat9版本上,在Tomcat9以及Tomcat9之前的版本中还是能够识别到javax.servlet.Servlet这个包。
7.配置Tomcat
点击右上角的编辑配置
选择右上角的+号,选择Smart Servlet
然后修改名称和配置
完成后点击确定,打开文件的项目结构选项
选择库,然后点击中间的+号,添加Tomcat目录下的servlet-api和jsp-api,然后点击右边的+好,将Tomcat目录下的servlet-api添加到类中,点击确定
8.运行该项目
点击图片中的连接,结果如下
在浏览器中输入以下内容:
http://localhost:8080/Maven1/hello
在控制台看到如下信息
Servlet类有init(),geetServletConfig(),service(),getServletInfo(),destroy()五个方法,最为核心的是init(),service()和destroy()方法
我们编写如下代码:
public class Test implements Servlet{
public Test(){
System.out.println("1,构造器方法");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2.init初始化方法");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3.--Test 被访问了");
//类型转换(因为HttpServletRequest有getMethod方法
HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequest;
//获取请求的方法
String method=httpServletRequest.getMethod();
if("GET".equals(method)){
//System.out.println("get请求");
doGet();
}else if("POST".equals(method)){
//System.out.println("POST请求");
doPost();
}
System.out.println(method);
}
//做get请求的操作
public void doGet(){
System.out.println("get请求");
System.out.println("get请求");
}
//做post请求的操作
public void doPost(){
System.out.println("post请求");
System.out.println("post请求");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4.destroy销毁方法");
}
}
web.xml的配置和最开始的一样,然后我们在WEB-INF目录下创建index.html,代码如下
Title
hello
运行Tomcat,得到如下页面
点击提交,得到如下结果
1.构造器方法 2.init初始化方法 3.--Test被访问了 post请求 post请求
此时先不要关闭Tomcat,在重新提交,结果如下
1.构造器方法 2.init初始化方法 3.--Test被访问了 post请求 post请求 3.--Test被访问了 post请求 post请求
因此,我们得到如下结论:
第一次调用时,将执行初始化方法init(ServletConfig),然后在每一次调用时,都会执行service方法,当服务器关闭时,会执行destroy方法
绝大多数情况下,我们使用的都是Servlet的子类HttpServlet类,我们在表单提交时,根据提交的类型不同,创建不同的接受方法。HttpServlet类有两个方法,一个是doGet()方法,用来接受GET类型的表单,一个是doPOST()方法,用来接受POST类型的表单
我们创建HelloServlet2.java,代码内容如下
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet2 extends HttpServlet {
//doGET()在get请求的时候调用
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
// super.doGet(req,resp);
System.out.println("HelloServlet2的doGet方法");
}
//doPost()在post请求的时候调用
@Override
protected void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException{
//super.doPost(req,resp);
System.out.println("HelloServlet2的doPost方法");
}
}
将web.xml内容修改如下
Archetype Created Web Application Test Test Test /hello HelloServlet2 HelloServlet2 HelloServlet2 /hello2
然后修改index.html
Title
hello
hello2
运行Tomcat,页面如下:
点击第二个提交,结果如下
HelloServlet2的doPost方法4.ServletConfig类
ServletConfig类从类名上来看,就知道是Servlet程序的配置信息类,Servlet程序和ServletConfig对象都是有Tomcat负责创建,我们负责使用,Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象
ServletConfig类的三大作用
1.可以获取Servlet程序的别名servlet-name的值
2.获取初始化参数init-param
3.获取ServletContext对象
我们修改一下web.xml的配置
Archetype Created Web Application Test Test url jdbc:mysql://localhost:3306/test Test /hello HelloServlet2 HelloServlet2 HelloServlet2 /hello2
然后修改一下Text.java的init方法
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2.init初始化方法");
//1.可以获取Servlet程序的别名servlet-name的值
System.out.println("Tes程序的别名是:"+servletConfig.getServletName());
//2.获取初始化参数init-param
System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("username"));
System.out.println("初始化参数url的值是:"+servletConfig.getInitParameter("url"));
//3.获取ServletContext对象
System.out.println(servletConfig.getServletContext());
}
运行Tomcat,结果如下
1,构造器方法 2.init初始化方法 Tes程序的别名是:Test 初始化参数username的值是:null 初始化参数url的值是:jdbc:mysql://localhost:3306/test org.apache.catalina.core.ApplicationContextFacade@f470e81 3.--Test 被访问了 post请求 post请求 POST
刚才的代码展示的是Servlet类,但是我们平时使用的都是HttpServlet类,我们修改我们的HelloServlet2.java,修改代码如下
public class HelloServlet2 extends HttpServlet {
//doGET()在get请求的时候调用
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
// super.doGet(req,resp);
System.out.println("HelloServlet2的doGet方法");
ServletConfig servletConfig=getServletConfig();
System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("username"));
System.out.println("初始化参数url的值是:"+servletConfig.getInitParameter("url"));
}
//doPost()在post请求的时候调用
@Override
protected void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException{
//super.doPost(req,resp);
System.out.println("HelloServlet2的doPost方法");
ServletConfig servletConfig=getServletConfig();
System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("username"));
System.out.println("初始化参数url的值是:"+servletConfig.getInitParameter("url"));
}
}
然后在修改一下web.xml
Archetype Created Web Application Test Test url jdbc:mysql://localhost:3306/test Test /hello HelloServlet2 HelloServlet2 username root2 url jdbc:mysql://localhost:3306/test HelloServlet2 /hello2
结果如下
ServletContext是一个接口,它表示Servlet上下文对象,一个web工程,只有一个ServletContext对象实例,还有,ServletContext是一个域对象
域对象:可以像map一样存取数据的对象,叫作域对象。这里的域指的是存取数据的操作范围
存数据 取数据 删除数据 Map put get remove ServletContext setAttribute getAttribute removeAttribute
ServletContext类的四个作用
1.获取web.xml中配置的上下文参数context-param
2.获取当前的工程路径,格式:/工程路径
3.获取工程部署后再服务器硬盘上的绝对路径
4.像Map一样存取数据
我们创建一个ContextServlet.java类,代码如下
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ContextServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
ServletContext context=getServletConfig().getServletContext();
//1.获取web.xml中配置的上下文参数context-param
String username=context.getInitParameter("username");
String password=context.getInitParameter("password");
System.out.println("context-param参数username的值是:"+username);
System.out.println("context-param参数password的值是:"+password);
//2.获取当前的工程路径,格式/工程路径
System.out.println("当前工程路径是:"+context.getContextPath());
//3.获取工程部署后在服务器硬盘上的绝对路径
//'/'斜杆被服务器解析地址为:http://ip:port/工程名/映射到IDEA代码的webapp目录
System.out.println("工程部署的路径是:"+context.getRealPath("/"));
System.out.println("工程下css目录的绝对路径是:"+context.getRealPath("/css"));
System.out.println("工程下image目录下的1.jpg的绝对路径是:"+context.getRealPath("/image/1.jpg"));
}
@Override
protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
ServletContext context=getServletConfig().getServletContext();
String username=context.getInitParameter("username");
String password=context.getInitParameter("password");
System.out.println("context-param参数username的值是:"+username);
System.out.println("context-param参数password的值是:"+password);
}
}
在XML修改配置,添加了上下文配置和ContextServlet的对照关系,如下
Archetype Created Web Application username context password root Test Test url jdbc:mysql://localhost:3306/test Test /hello HelloServlet2 HelloServlet2 username root2 url jdbc:mysql://localhost:3306/test HelloServlet2 /hello2 HelloServlet3 HelloServlet3 HelloServlet3 /hello3 ContextServlet ContextServlet ContextServlet /contextServlet
修改index.html,其实不修改也好,只是修改后,在页面访问Servlet更方便,不然要一直在浏览器输入Servlet的访问路径
Title
hello
hello2
hello3 ContextServlet
在webapp下,再创建一个css目录和image目录,方便等一下测试
运行结果如下
context-param参数username的值是:context context-param参数password的值是:root 当前工程路径是:/Maven1 工程部署的路径是:D:courseIdeaProjectMaven1srcmainwebapp 工程下css目录的绝对路径是:D:courseIdeaProjectMaven1srcmainwebappcss 工程下image目录下的1.jpg的绝对路径是:D:courseIdeaProjectMaven1srcmainwebappimage1.jpg
我们创建两个Java类,一个为ContextServlet1.java,一个为ContextServlet2.java,两个类的代码分别如下:
//ContextServlet1.java
public class ContextServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
//获取ServletContext对象
ServletContext context=getServletContext();
System.out.println("保存之前:Context1中获取域数据key1的值是:"+context.getAttribute("key1"));
context.setAttribute("key1","value1");
System.out.println("Context1中获取域数据key1的值是:"+context.getAttribute("key1"));
}
@Override
protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
}
}
//ContextServlet2.java
public class ContextServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
ServletContext context=getServletContext();
System.out.println("context2中获取域数据key1的值是:"+context.getAttribute("key1"));
}
@Override
protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
}
}
然后配置web.xml和index.html,配置内容和前面那些基本一样,这里就不多说了
我们运行Tomcat,在浏览器上先输入
http://localhost:8080/Maven1/context2,
然后输入
http://localhost:8080/Maven1/context1,
最后在输入
http://localhost:8080/Maven1/context2,
结果如下
为什么会出现上面这种情况?因为ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁。之前提到,ServletContext类似于一个Map,因此,最开始的时候,我们调用context2,没有存储数据,故结果为null,而后我们调用context1,存储数据了,故结果为value1,再调用contex2,因为已经存储数据,故结果也为value1
协议:指双方或多方相互约定好,大家都需要遵守的规则
HTTP协议:指客户端和服务器之间通信时,发送的数据需要遵守的规则
HTTP协议中的数据又叫报文
客户端给服务器发送数据叫请求;服务器给客户端回传数据叫响应。
请求分为GET请求和POST请求
GET请求:
1.请求行 (1)请求的方法 GET (2)请求的资源路径[+?+请求参数] (3)请求的协议的版本号 HTTP/1.1 2.请求头 key:value 组成不同的键值对,表示不同的含义。
POST请求
1.请求行 (1)请求方式 POST (2)请求的资源路径[+?+请求参数] (3)请求的协议的版本号 2.请求头 (1)key:value 不同的请求头,有不同的含义 空行 3.请求体 ===>>>就是发送给服务器的数据
常用的请求头说明:
Accept:表示客户端可以接收的数据类型 Accept-Language:表示客户端可以接收的语言类型 User-Agent:表示客户端浏览器的信息 Host:表示请求时的服务器ip和端口号
GET请求有哪些:
1.form标签 method=get 2.a标签 3.link标签引入css 4.script标签引入js文件 5.img标签引入图片 6.iframe引入html页面 7.在浏览器地址栏中输入地址后敲回车
POST请求有哪些:
1.form标签method=post
响应的HTTP协议格式
1.响应行 (1)响应的协议和版本号 HTTP/1.1 (2)响应状态码 (3)响应状态描述符 2.响应头 (1)key:value 不同响应头,有不同的含义 空行 3.响应体 ===>>>就是回传给客户端的数据
常见的响应码说明:
200 表示请求成功 302 表示请求重定向 404 表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误) 500 表示服务器已经收到请求,但是服务器内部错误(代码错误)
MIME类型说明
MIME是HTTP协议中的数据类型
MIME的英文全称是"Multipurpose Internet Mail Extensions"多功能Internet邮件扩充服务,MIME类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应
HttpServletRequest类的作用:每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中。然后传递给service方法(doGet和doPost)中给我们使用。我们可以通过HttpServletRequest对象,获取到所有请求的信息
HttpServletRequest常用方法
1.getRequestURI(); 获取请求的资源路径 2.getRequestURL(); 获取请求的统一资源定位符(绝对路径) 3.getRemoteHost(); 获取客户端的IP地址 4.getHeader(); 获取请求头 5.getParameter(); 获取请求的参数 6.getParameterValues(); 获取请求的参数(多个值的时候使用) 7.getMethod(); 获取请求的方式(GET或POST) 8.setAttribute(key,value); 设置域数据 9.getAttribute(key); 获取域数据 10.getRequestDispatcher(); 获取请求转发对象
我们新创建一个web工程来演示什么的功能,具体创建方法见目录1.IDEA社区版创建Servlet
我们在Test.java中,编写如下代码
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Test extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException,IOException{
//1.getRequestURI(); 获取请求的资源路径
System.out.println("URI->"+request.getRequestURI());
//2.getRequestURL(); 获取请求的统一资源定位符(绝对路径)
System.out.println("URL->"+request.getRequestURL());
//3.getRemoteHost(); 获取客户端的IP地址
//在IDEA中,使用localhost访问时,得到的客户端ip地址是:127.0.0.1
//使用127.0.0.1访问时,得到的客户端ip地址是:127.0.0.1
//使用真实IP访问时,得到的客户端IP地址是:真实的客户端IP地址
System.out.println("客户端ip地址:"+request.getRemoteHost());
//4.getHeader(); 获取请求头
System.out.println("请求头User-Agent:"+request.getHeader("User-Agent"));
//7.getMethod(); 获取请求的方式(GET或POST)
System.out.println("请求的方式:"+request.getMethod());
}
@Override
protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
}
}
结果如下:
URI->/Maven2/hello URL->http://localhost:8080/Maven2/hello 客户端ip地址:0:0:0:0:0:0:0:1 请求头User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 请求的方式:GET
我们创建一个ParameterServlet.java类,代码内容如下:
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
//获取请求参数
String username=request.getParameter("username");
String password=request.getParameter("password");
String[] hobby=request.getParameterValues("hobby");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
System.out.println("兴趣爱好:"+ Arrays.asList(hobby));
}
@Override
protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
}
}
我们配置web.xml如下:
Archetype Created Web Application Test Test Test /hello ParameterServlet ParameterServlet ParameterServlet /parameterServlet
创建form.html,添加一些表单项,内容如下:
Title
运行Tomcat,在浏览器上浏览栏输入http://localhost:8080/Maven1/form.html,页面如下:
输入内容,假设输入用户名为username,密码为root,兴趣爱好全选,然后点击提交,结果如下:
用户名:username 密码:root 兴趣爱好:[cpp,java,js]
我们将form.html的提交方式改为"post",然后修改parameterServlet.java内容如下:
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
//获取请求参数
System.out.println("----doGet----");
String username=request.getParameter("username");
String password=request.getParameter("password");
String[] hobby=request.getParameterValues("hobby");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
System.out.println("兴趣爱好:"+ Arrays.asList(hobby));
}
@Override
protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
//设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题
request.setCharacterEncoding("UTF-8");
System.out.println("----doPost----");
String username=request.getParameter("username");
String password=request.getParameter("password");
String[] hobby=request.getParameterValues("hobby");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
System.out.println("兴趣爱好:"+ Arrays.asList(hobby));
}
}
如果没有以下代码:
//设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题
request.setCharacterEncoding("UTF-8");
当我们的用户名输入中文时,结果中会出现中文乱码,因此我们必须加上以下代码
//设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题
request.setCharacterEncoding("UTF-8");
输入内容,提交,结果如下:
用户名:光改为个 密码:35462524 兴趣爱好:[cpp, java, js]8.请求的转发
请求的转发:服务器收到请求后,从一个资源跳转到另一个资源的操作叫作请求转发
请求转发的特点:
1.浏览器地址栏没有变化
2.他们是一次请求
3.他们共享Request域中的数据
4.可以转发到Web-INF目录下
请求的转发有点类似于我们去柜台办理业务,在柜台1办理业务,带起材料后盖章,然后柜台1通知我们去柜台2办理剩余的业务,到达柜台2检查我们的材料是否齐全,然后再检查是否有柜台1的盖章,一切正常后为我们办理剩余的业务。我们已该场景为例,编写下列的代码,首先,我们创建两个类,Servlet1.java和Servlet2.java
代码分别如下:
//Servlet1
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
//获取请求的参数(办事的材料)查看
String username=request.getParameter("username");
System.out.println("在Servlet1(柜台1)中查看参数(材料):"+username);
//将参数传递到Servlet2,并查看
request.setAttribute("key1","柜台1的章");
//问路:Servlet2(柜台2)怎么走
//请求转发必须要以斜杆打头,斜杆表示地址为:http://ip:port/工程名/,映射到IDEA代码的web目录
RequestDispatcher requestDispatcher=request.getRequestDispatcher("/servlet2");
//走向Servlet2(柜台2)
requestDispatcher.forward(request,response);
}
}
//Servlet2
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
//获取请求的参数(办事的材料)查看
String username=request.getParameter("username");
System.out.println("在Servlet2(柜台2)中查看参数(材料):"+username);
//查看柜台1是否有盖章
Object key1=request.getAttribute("key1");
System.out.println("柜台1是否有章:"+key1);
//处理自己的业务
System.out.println("Servlet2自己的业务");
}
}
在web.xml添加相应的配置,运行Tomcat,在浏览栏上输入:
http://localhost:8080/Maven2/servlet1?username=123456,(?后面的内容就是我们的配置信息)结果如下
假设我们现在想做一个页面,然后从这个页面跳转到另一个页面,在从当前页面返回到最开始的页面,我们很自然地想到a标签,我们先在webapp目录下创建一个a目录,然后在a目录下创建b目录,在b目录下创建c.html,代码如下:
Title
这是a下的b下的c.html页面
跳回首页
然后我们在webapp目录下创建一个index.html,代码如下:
首页
这是web下的index.html
a/b/c.html
运行Tomcat,结果如下:
点击链接,跳转的页面如下:
点击链接,又返回首页。
以上是习惯的做法,我们下面用请求转发来实现同样的功能
我们创建一个ForwardC.java,代码如下:
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ForwardC extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
System.out.println("经过了ForwardC程序");
request.getRequestDispatcher("/a/b/c.html").forward(request,response);
}
}
修改c.html和index.html,代码如下
Title
这是a下的b下的c.html页面
跳回首页
首页
这是web下的index.html
a/b/c.html
请求转发:a/b/c.html
配置web.xml,运行Tomcat,结果如下:
点击第二个连接,跳转页面
可是当我们点击跳回首页这个连接时,却无法跳转到首页
原因在于:当我们点击a标签进行跳转时,浏览器地址中的地址是:http://localhost:8080/Maven2/a/b/c.html,跳转回去的a标签路径是:…/…/index.html
所有相对路径在工作时都会参照当前浏览器地址栏中的地址来进行跳转,那么参照后得到的地址是:
http://localhost:8080/Maven/index.html,这是我们刚才分析的第一种情况,结果正确。
但当我们使用请求转发来进行跳转时,浏览器地址栏中的地址是:
http://localhost:8080/Maven2/forwardC
跳转回去的a标签路径是:…/…/index.html
通过参照,得到的地址是:
http://localhost:8080/index.html,这很明显是错误的路径,因此无法跳转回首页
这时我们可以采用base标签,它可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转
我们修改c.html,代码如下:
Title
这是a下的b下的c.html页面
跳回首页
现在都可以成功的跳转了
补充:在JavaWeb中,路径分为相对路径和绝对路径两种
相对路径: . 表示当前目录 .. 表示上一级目录 资源名 表示当前目录/资源名 绝对路径: http://ip:port/工程路径/资源路径
在web中/斜杆的不同意义
在web中,斜杆是一种绝对路径
斜杆如果被浏览器解析,得到的地址是:http://ip:port/
斜杆被服务器解析,得到的地址是:
http://ip:port/工程路径/
特殊情况:response.sendRedirect("/");把斜杆发送给浏览器解析,得到http://ip:port/
HttpServletResponse类的作用:和HttpServletRequest类一样,每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用,HttpServletRequest表示请求过来的信息,HttpServletResponse表示所用响应的信息,我们如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置
响应通过流来传递,包括两个流:
1.字节流:getOutputStream(); 常用于下载(传递二进制数据) 2.字符流: getWriter(); 常用于回传字符串(常用)
两个流同时只能使用一个
我们创建一个ResponseIOServlet.java类验证两个流是否可以同时使用,代码如下:
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
response.getWriter();
response.getOutputStream();
}
}
配置web.xml,然后运行Tomcat,在浏览器地址栏输入:http://localhost:8080/Maven2/responseIOServlet,结果如下
在实际开发中,常需要往客户端回传字符串数据,我们修改ResponseIOServlet.java,代码如下:
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
//response.getWriter();
//response.getOutputStream();
//往客户端回传字符串数据
PrintWriter printWriter=response.getWriter();
printWriter.println("response's context!!!");
}
}
运行Tomcat,结果如下:
我们将回传的数据修改为中文,如下:
//往客户端回传字符串数据
PrintWriter printWriter=response.getWriter();
printWriter.println("华南理工大学");
重新部署Tomcat,结果可能是中文乱码,解决中文乱码的第一种方法,我们修改ResponseIOServlet.java,代码如下:
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
//response.getWriter();
//response.getOutputStream();
//显示当前服务器使用的字符集
System.out.println(response.getCharacterEncoding());
//设置服务器字符集为UTF-8
response.setCharacterEncoding("UTF-8");
//通过响应,设置浏览器也使用UTF-8
response.setHeader("Context-Type","text/html;charset=UTF-8");
//往客户端回传字符串数据
PrintWriter printWriter=response.getWriter();
printWriter.println("华南理工大学");
}
}
结果如下:
解决方法2:修改ResponseIOServlet.java
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
//它会同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头
//此方法一定要在获取流对象之前调用才有效
response.setContentType("text/html;charset=UTF-8");
//往客户端回传字符串数据
PrintWriter printWriter=response.getWriter();
printWriter.println("华南理工大学");
}
}
重新部署后结果如下:
请求重定向:值客户端给服务器发请求,然后服务器告诉客户端说,我给你一个新地址,你去新地址访问(因为之前的地址可能已经被废弃)
我们创建Response1.java和Response2.java,代码如下:
//Response1.java
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
System.out.println("曾到此一游--response1");
request.setAttribute("key1","value1");
//设置响应状态码,表示重定向(已搬迁)
response.setStatus(302);
//设置响应头,说明新的地址在哪里
response.setHeader("Location","http://localhost:8080/Maven2/response2");
}
}
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
System.out.println(request.getAttribute("key1"));
response.getWriter().write("response2's result");
}
}
配置web.xml,运行Tomcat,结果如下
我们在输入地址前,可以先打开该网页的网络状态,输入地址后,如下图
由此可见请求重定向的特点。
请求重定向的特点:
1.浏览器地址栏会发生变化
2.两次请求
3.不共享Response域中的数据
4.不能访问WEB-INF下的资源
5.可以访问工程外的资源
请求重定向的第二种方法(推荐使用)
我们修改Response1.java
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
System.out.println("曾到此一游--response1");
request.setAttribute("key1","value1"); response.sendRedirect("http://localhost:8080/Maven2/response2");
}
}



