Servlet 超全面教程,学习 Servlet 看这篇就够了!

Servlet 基本使用

本文介绍了Servlet的基本使用,适合初学者学习时参考,相信初学者看完一定有收获~

还可看看博主的其他文章,超全面总结:

MySQL必知必会,传送地址:MySQL的使用,看这篇就够了
JavaScript必知必会,传送地址:JavaScript小白必看

一、Servlet介绍

  1. Servlet是JavaEE规范(接口)之一
  2. Servlet是JavaWeb三大组件之一,三大组件分别是Servlet程序、Filter过滤器、Listener监听器
  3. Servlet是运行在服务器上的一个Java程序,可以接收客户端发来的请求,并响应数据给客户端

二、手动实现Servlet程序

  1. 编写一个类实现Servlet接口,并重写service方法处理请求、响应数据
  2. 在WEB-INF文件夹中的web.xml文件中配置Servlet程序的访问地址

代码演示:1. 在src下创建一个TestServlet类

public class TestServlet implements Servlet {
    
    
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    
    
        System.out.println("TestServlet被访问了!");
    }
}

代码演示:2. 在web.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">
    <!--内容写在<web-app></web-app>中-->
    <!--servlet标签给Tomcat配置Servlet程序-->
    <servlet>
        <!--servlet-name标签给Servlet程序起一个别名(一般是类名)-->
        <servlet-name>TestServlet</servlet-name>
        <!--servlet-class标签是Servlet程序的全类名-->
        <servlet-class>com.qizegao.servlet.TestServlet</servlet-class>
    </servlet>
    <!--servlet-mapping标签是servlet的映射,给Servlet程序配置访问地址-->
    <servlet-mapping>
        <!--此时servlet-name标签要与上一个servlet-name标签中相同-->
        <servlet-name>TestServlet</servlet-name>
        <!--url-pattern标签配置访问地址:
            /在服务器解析时表示为Tomcat的工程路径(在Edit Configurations中修改),
            /Test代表默认路径/Test,即http://localhost:8080/MyTest/Test,
            也就是说在浏览器的地址栏中输入上述路径访问到的是TestServlet类-->
        <url-pattern>/Test</url-pattern> //任意起名,用这个名字来访问指定类
    </servlet-mapping>
</web-app>
运行结果:
点击绿色按钮开启Tomcat服务器之后,会自动打开默认的地址http://localhost:8080/MyTest,
在地址栏继续输入/Test,会执行指定类的service方法,控制台输出:TestServlet被访问了!

三、Servlet程序的访问原理

在这里插入图片描述

四、Servlet程序的常见错误

1. url-pattern中配置的路径没有以斜杠打头

在这里插入图片描述

2. servlet-name中的两个映射值不一致

在这里插入图片描述

3. servlet-class标签的全类名配置错误

在这里插入图片描述

五、Servlet的生命周期

Servlet程序被访问以后按以下顺序执行:

  1. 执行Servlet程序的构造方法
  2. 执行init方法
  3. 执行service方法
  4. 执行destroy方法
    其中1和2是在初次访问并创建Servlet程序时会执行(每次启动服务只执行一次),第3步每次刷新 (访问)都会执行,第4步点击停止时会执行一次

六、GET和POST请求的不同处理

代码演示:1. 在src目录下创建此类

public class TestServlet implements Servlet {
    
    
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    
    
        //转换的原因:HttpServletRequest有getMethod方法,可以得到请求的类型
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String method = httpServletRequest.getMethod();
        //method值为GET或POST,取决于表单提交的method
        if (method.equals("POST")){
    
    
            System.out.println("POST方式");
        } else if (method.equals("GET")) {
    
    
            System.out.println("GET方式");
        }
    }

代码演示:2. 在web目录下创建Test.html页面

<body>
    <form action="http://localhost:8080/MyTest/Test" method="post">
        <!--action属性值与web.xml中的<url-pattern>标签内容一致,用于访问到service方法-->
        <input type="submit">
    </form>
</body>

运行结果:服务器启动之后,在浏览器的地址栏中的后缀加上Test.html,即可访问此页面,点击提交标签,即可跳转到http://localhost:8080/MyTest/Test,执行service方法,控制台输出:POST方式

七、继承HttpServlet类实现Servlet程序

在实际的项目开发中,都是使用继承HttpServlet类实现Servlet程序的方式,步骤如下:

  1. 编写一个类继承HttpServlet类
  2. 根据需求重写doGet或doPost方法,由service方法根据表单的method属性值调用二者之一
  3. 到web.xml中配置Servlet程序的访问地址

代码演示:1. 在src目录下创建此类

public class TestServlet2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        System.out.println("doGet方法执行");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        System.out.println("doPost方法执行");
    }
}
//HttpServlet的service方法会根据method方式调用二者之一

代码演示:2. 在web.xml中继续写配置

<!--不用删除原来的servlet标签,在<web-app>标签中继续写servlet标签-->
<servlet>
    <servlet-name>TestServlet2</servlet-name>
    <servlet-class>com.qizegao.servlet.TestServlet2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>TestServlet2</servlet-name>
    <url-pattern>/Test2</url-pattern>
</servlet-mapping>

代码演示:3. 在web中创建Test.html页面

<body>
    <form action="http://localhost:8080/MyTest/Test2" method="post">
        <!--action属性值与web.xml中的<url-pattern>标签内容一致,用于访问到service方法-->
        <input type="submit">
    </form>
</body>

运行结果:服务器启动之后,在浏览器的地址栏中的后缀加上Test.html,即可访问此页面,点击提交标签, 即可跳转到http://localhost:8080/MyTest/Test2,执行service方法,进而执行doPost方法

八、使用IDEA创建Servlet程序

在这里插入图片描述
在这里插入图片描述

创建之后,会在包下创建此类(类名为全类名中的类名),此类继承于HttpServlet类,其中有doGet和doPost方法(无函数体),并自动的在web.xml 文件中补充新的标签,但无标签,需自己补充

九、Servlet接口的继承体系

在这里插入图片描述

十、ServletConfig接口

  1. 从名字来看,得知此接口中是Servlet程序的配置信息:
    (1) Servlet程序和ServletConfig对象都是由Tomcat负责创建,编程人员负责使用
    (2) Servlet程序默认是第一次访问时创建,每个Servlet程序创建时对应的创建ServletConfig对 象,二者相互对应,某个Servlet程序只可以获得他对应的ServletConfig对象,无法获得别的 Servlet程序的ServletConfig对象

  2. ServletConfig接口的三大作用:
    (1) 可以获取Servlet程序的别名(即web.xml的的内容)
    (2) 可以获取web.xml的初始化参数的值
    (3) 可以获取ServletContext对象

代码演示:1. 在web.xml中继续写配置(写在标签中)

<servlet>
    <servlet-name>TestServlet4</servlet-name>
    <servlet-class>com.qizegao.servlet.TestServlet4</servlet-class>
    <!--<init-param>是初始化参数,每个servlet标签中都可以有,一个servlet标签中可以有多个-->
    <init-param>
        <!--参数名-->
        <param-name>username</param-name>
        <!--参数值-->
        <param-value>root</param-value>
    </init-param>
    <init-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql:localhost:3306/test</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>TestServlet4</servlet-name>
    <url-pattern>/Test4</url-pattern>
</servlet-mapping>

代码演示:2. 在src目录下创建此类

public class TestServlet4 extends HttpServlet {
    
    
    @Override  //使用init方法的原因:1.一定会执行 2.参数中有ServletConfig对象
    public void init(ServletConfig config) throws ServletException {
    
    
        super.init(config);
        //1.获取Servlet程序的别名
        System.out.println("此程序的别名是:" + config.getServletName());
        //2.获取初始化参数init-param,该方法获取指定的参数名的值
        System.out.println("初始化参数username的值是:" + config.getInitParameter("username"));
        System.out.println("初始化参数url的值是:" + config.getInitParameter("url"));
        //3.获取ServletContext对象
        System.out.println(config.getServletContext());
    }
    /*运行结果(浏览器地址栏输入http://localhost:8080/MyTest/Test4):
      此程序的别名是:TestServlet4
      初始化参数username的值是:root
      初始化参数url的值是:jdbc:mysql:localhost:3306/test
      org.apache.catalina.core.ApplicationContextFacade@64d62c61 */
} 

注意:重写init方法时,必须要在函数体内写:super.init(config);
原因:父类GenericServlet中的init方法将参数config保存起来,子类若不调用则无法保存

十一、ServletContext接口

  1. ServletContext接口表示Servlet上下文对象
  2. 一个web工程只有一个ServletContext对象实例
  3. ServletContext是在web工程启动时创建,在web工程停止时销毁
  4. ServletContext对象是一个域对象
    域对象:像Map一样存取数据的对象称为域对象,域指的是存取数据的操作范围,
    ServletContext的域是整个web工程
    在这里插入图片描述
  5. ServletContext接口的四个作用:
    (1) 获取web.xml中配置的上下文参数标签中的值
    (2) 获取当前工程的路径,格式:/工程路径,也就是Edit Configurations中Deployment中的 Application context的内容(即地址中8080之后,具体的打开的页面之前的内容)
    (3) 获取工程部署后在硬盘上的绝对路径
    (4) 像Map一样存取数据

代码演示:1. 在web.xml中继续写配置(在标签中)

<!--<context-param>标签中是上下文参数,属于整个web工程-->
<!--可以有多个,写在第一个<servlet>标签之外(之上)-->
<context-param>
    <param-name>username</param-name>
    <param-value>root</param-value>
</context-param>
<context-param>
    <param-name>password</param-name>
    <param-value>root</param-value>
</context-param>
<!--并写出下方的类对应的<servlet标签>-->

代码演示:2. 在src目录下创建此类

public class MyContextServlet extends HttpServlet {
    
    
    //默认执行doGet方法,故只重写doGet方法
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //GenericServlet类中有public ServletConfig getServletConfig()方法,返回this.config
        ServletContext servletContext = getServletConfig().getServletContext();
        //1.获取web.xml中配置的上下文参数<context-param>标签中的值
        String username = servletContext.getInitParameter("username");
        System.out.println("context-param参数的username值是" + username);
        /* 运行结果:context-param参数的username值是root */
        System.out.println("context-param参数的password值是" + servletContext.getInitParameter("password"));
        /* 运行结果:context-param参数的password值是root */
        //2.获取当前工程的路径
        System.out.println("当前工程路径:" + servletContext.getContextPath());
        /* 运行结果:当前工程路径:/MyTest */
        //3.获取工程部署后在硬盘上的绝对路径
        /* /斜杠(默认路径)对应IDEA代码的web目录 */
        System.out.println("工程部署的路径是:" + servletContext.getRealPath("/"));
        /* 运行结果:E:\IDEA WorkSpace\FirstWeb\out\artifacts\FirstWeb_war_exploded\ */
        //在web目录下创建一个css文件夹
        System.out.println("工程下css目录的绝对路径是:" + servletContext.getRealPath("/css"));
        /* 运行结果:E:\IDEA WorkSpace\FirstWeb\out\artifacts\FirstWeb_war_exploded\css */
        //在web目录下创建一个img文件夹,里面放1.gif文件
        System.out.println("工程下img目录1.gif的绝对路径是:" + servletContext.getRealPath("/img/1.gif"));
        /* 输出:E:\IDEA WorkSpace\FirstWeb\out\artifacts\FirstWeb_war_exploded\img\1.gif */
    }
}
//记得要在浏览器的地址栏输入http://localhost:8080/MyTest/MyContextServlet才可访问到此类

代码演示:3. 在src中创建此类,并在web.xml中写对应的配置信息

public class Servlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //GenericServlet类中有public ServletContext getServletContext()方法,return this.getServletConfig().getServletContext();
        ServletContext servletContext = getServletContext();
        System.out.println(servletContext);
        /* 输出:org.apache.catalina.core.ApplicationContextFacade@2711c490 */
        servletContext.setAttribute("key1","value1");
        System.out.println(servletContext.getAttribute("key1"));
        /* 输出:value1 */
    }
}

注意:一个web工程只会创建一个ServletContext对象实例,换其他类输出servletContext得到的结果与上述相同,且一旦给此对象赋值,即使换另一个类getAttribute(key1),得到的结果也是value1

十二、HTTP协议

1. 含义

所谓协议指的是双方或多方相互约定好,都要遵守的规则,而HTTP协议指的是客户端和 服务器之间通信时发送的数据需要遵守的规则,HTTP协议中的数据又称为报文

2. 请求的HTTP协议格式

请求分为GET请求和POST请求两种:

(1) GET请求:由请求行、请求头两部分组成,如下图所示:
在这里插入图片描述
内容分析:
请求行:
①请求的方式:GET
②请求的资源路径:/06_servlet/a.html
③请求的协议的版本号:HTTP/1.1

请求头:
①Accept:告诉服务器,客户端可以接收的数据类型
②Accept-Language:告诉服务器,客户端可以接收的语言类型:
zh_CN:中文中国
en_US:英文美国
③User-Agent:代表客户端浏览器的信息
④Accept-Encoding:告诉服务器,客户端可以接收的数据编码(压缩)格式
⑤Host:表示请求时的服务器ip和端口号
⑥Connection:告诉服务器,当前连接如何处理:
Keep-Alive:回传完数据不要马上关闭,保持一小段时间的连接
Closed:回传完数据马上关闭

(2) POST请求:由请求行、请求头、空行、请求体组成,如下图所示:
在这里插入图片描述
内容分析(仅分析与GET请求的不同之处):
请求头:
①Referer:表示请求发起时,浏览器地址栏中的地址
②Content-Type:表示发送的数据的类型:
i. application/x-www-form-ur lencoded:表示提交的数据的格式是 name=value&name=value,然后对其进行url编码,url编码是把非英文内容转换为:%xx%xx
ii. multipart/form-data:表示以多段的形式提交数据给服务器,即以流的形式提交,用于上传
③Content-Length:表示发送的数据的长度
④Cache-Control:表示如何控制缓存,no-cache不缓存

3. 响应的HTTP协议格式

在这里插入图片描述

4. 常见的响应码

200 表示请求成功
302 表示请求重定向
404 表示服务器收到请求,但是请求的数据不存在(请求地址错误)
500 表示服务器收到请求,但是服务器内部错误(代码错误)

5. MIME类型说明

MIME是HTTP协议中的数据类型,格式是:大类型/小类型,并与某一种文件的扩展名相对应:
在这里插入图片描述

十三、谷歌浏览器查看HTTP协议

首先点击F12:
在这里插入图片描述
注意点:

  1. 到目前为止除了form标签中method=post之外,其余均为GET请求
  2. 标签不一定与标签相邻,只要根据能对应上即可
  3. 默认地址值与工程路径是两个概念,上述只是将默认地址值修改为工程路径,即上述斜杠 等代表访问到的是工程路径:http://localhost:8080/工程名,而非默认路径

十四、HttpServletRequest类

  1. HttpServletRequest类的作用:
    每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求发来的HTTP协议信息解析好封装到Request对象中,然后传递到service方法中(调用doGet或doPost方法)供编程人员使用,编程人员通过HttpServletRequest对象,可以获取到请求的所有信息

  2. HttpServletRequest类的常用方法:
    getRequestURI():获取请求的资源路径
    getRequestURL():获取请求的绝对路径
    getRemoteHost():获取客户端的ip地址
    getHeader():获取请求头
    getParameter():获取请求的参数
    getParameterValues():获取请求的参数(多个值时使用)
    getMethod():获取请求的方式(GET或POST)
    setAttribute(key, value):设置域数据
    getAttribute(key):获取域数据
    getRequestDispatcher():获取请求转发对象

代码示例(在src下创建此类):

public class RequestAPI extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //1.获取请求的资源路径
        String requestURI = request.getRequestURI();
        //2.获取请求的绝对路径
        StringBuffer requestURL = request.getRequestURL();
        //3.获取客户端的ip地址
        String requestRemoteHost = request.getRemoteHost();
        //4.获取请求头
        String requestHeader = request.getHeader("User-Agent");
        //5.获取请求的方式
        String requestMethod = request.getMethod();
        //输出
        System.out.println(requestURI); /* /MyTest/RequestAPI */
        System.out.println(requestURL); /* http://localhost:8080/MyTest/RequestAPI */
        System.out.println(requestHeader); //Mozilla/5.0 (Windows NT 10.0; Win64; x64)...
        System.out.println(requestMethod); //GET
        System.out.println(requestRemoteHost); //127.0.0.1
        /*在IDEA中,使用localhost访问时得到的客户端ip地址是127.0.0.1
                   使用真实ip访问时,得到的客户端地址是真实的客户端ip地址 */
    }
}
  1. 获取请求参数
    代码示例:1. 在web目录下创建form.html页面(不可在WEB-INF中创建,无法访问到):
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>form</title>
</head>
<body>
    <form action="http://localhost:8080/MyTest/RequestAPI2" method="post">
        用户名:<input type="text" name="username"><br/>
        密码:<input type="password" name="password"><br/>
        兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++
                 <input type="checkbox" name="hobby" value="Java">Java
                 <input type="checkbox" name="hobby" value="JS">JavaScript<br/>
                 <input type="submit">
    </form>
</body>
</html>

在这里插入图片描述
代码示例:2. 在src下创建此类

public class RequestAPI2 extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //doPost方法会出现中文请求乱码问题
        //需要在获取任何参数之前修改字符编码集,而不仅仅获取中文参数时才修改:
        request.setCharacterEncoding("UTF-8");
        //获取请求的参数(此方法参数中放name属性值,得到value属性值)
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //获取请求的参数的多个值
        String[] hobbies = request.getParameterValues("hobby");
        //输出
        System.out.println("用户名:" + username);
        System.out.println("密码:" + password);
        //将数组转换为集合输出
        System.out.println("兴趣爱好:" + Arrays.asList(hobbies));
    }
}

运行结果:
(在web.xml文件中创建对应的配置,在浏览器的地址栏输http://localhost:8080/MyTest/form.html)
在这里插入图片描述在这里插入图片描述
注意:doGet请求的中文乱码问题的解决:
在这里插入图片描述

十五、请求转发

请求转发指的是服务器收到请求之后,从一个资源跳转到另一个资源的操作,如图所示:
在这里插入图片描述
代码示例:1. 在src下创建此类,并在web.xml中配置相应的数据

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);
        //给材料盖章
        request.setAttribute("key1","柜台1的章");
        //获得通向Servlet2的路径(请求转发对象)
        //参数必须以斜杠打头,斜杠代表http://localhost:8080/工程名/,对应IDEA代码的web目录
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Servlet2");
        //可以转发到WEB-INF目录下:request.getRequestDispatcher("/WEB-INF/xxx");
        //通过得到的路径走向Servlet2(柜台2)
        //forward方法将当前资源的request和response转发到该requestDispatcher指定的资源
        requestDispatcher.forward(request, response);
        //使得Servlet2中的request和response与Servlet1一致
    }
}

代码示例:2. 在src下创建此类,并在web.xml中配置相应的数据

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处理业务");
    }
}

运行结果:
(在浏览器的地址栏中输入:http://localhost:8080/MyTest/Servlet1?username=jaychou)
在这里插入图片描述
可以得出地址栏的内容不发生变化,但页面自动跳转(访问)
到了请求转发对象Servlet2中,即显示
http://localhost:8080/MyTest/Servlet2的页面

十六、base标签的作用

代码示例:1. 在web目录下创建a文件夹下创建b文件夹下创建c.html

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    这是a下的b下的c.html<br/>
    <a href="../../index.html">跳到web下的index.html</a>
</body>

在这里插入图片描述
代码示例:2. 在web目录下创建index.html

<head>							
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    这是web下的index.html页面<br/>
    <a href="a/b/c.html">跳转到a下的b下的c.html</a>
</body>

运行结果:两个页面可以来回跳转
在这里插入图片描述
分析:当在c.html页面准备点击进行跳转时浏览器的地址栏是http://localhost:63342/FirstWeb/MyTest/web/a/b/c.html,
跳转到index.html页面时的a标签路径是…/…/index.html,所有相对路径在跳转时都会参照当前浏览器地址栏中的地址来进行跳转,此时跳转的路径是http://localhost:63342/FirstWeb/MyTest/web/a/b/c.html…/…/index.html,进行抵消之后,剩余的路径是http://localhost:63342/FirstWeb/MyTest/web/index.html,路径正确,跳转成功。

代码示例:1. 在web目录下创建a文件夹下创建b文件夹下创建c.html

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    这是a下的b下的c.html<br/>
    <a href="../../index.html">跳到web下的index.html</a>
</body>

在这里插入图片描述
代码示例:2. 在src下创建此类,并在web.xml中配置

public class Forward extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        request.getRequestDispatcher("a/b/c.html").forward(request,response);
    }
}

代码示例:3. 在web目录下创建index.html

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    这是web下的index.html页面<br/>
    <a href= http://localhost:8080/MyTest/Forward>请求转发:a/b/c.html</a>
</body>

在这里插入图片描述
分析:在地址栏输入http://localhost:63342/FirstWeb/MyTest/web/index.html,点击后成功跳转到 http://localhost:8080/MyTest/Forward,此时的页面是:
在这里插入图片描述
点击之后无法跳转,根据以上原因,要跳转的地址是http://localhost:8080/MyTest/Forward…/…/index.html,抵消之后为http://localhost:8080/…/index.html,这是错误的路径,因此跳转失败。解决方案如下:

base标签可以设置当前页面中所有相对路径跳转时参照指定的路径来进行跳转,在href属性中设置指定路径

代码示例:4. 将上述c.html文件修改为如下即可成功跳转

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--base标签写在<title>标签之后-->
    <base href="http://localhost:8080/MyTest/a/b/">
</head>
<body>
    这是a下的b下的c.html<br/>
    <a href="../../index.html">跳到web下的index.html</a>
</body>

注:实际开发中都使用绝对路径,而不简单的使用相对路径

十七、”/”在不同情况下的不同意义

  1. “/”若被浏览器解析,得到的地址是:http://ip:port/
    (1) 斜杠
  2. “/”若被服务器解析,得到的地址是:http://ip:port/工程路径
    (1) /servlet1
    (2) servletContext.getRealPath(“/”);
    (3) request.getRequestDispatcher(“/”);
  3. 特殊情况:response.sendRedirect(“/”); 把斜杠发送到浏览器解析,得到http://ip:port/

十八、HttpServletResponse类

  1. HttpServletResponse类的作用:
    每次只要有请求进入Tomcat服务器,Tomcat服务器就会创建一个Response对象传递给Servlet程序。HttpServletResponse表示所有响应的信息(HttpServletRequest表示请求发来的信息),可以通过HttpServletResponse对象设置返回给客户端的信息
  2. 两个输出流的说明:
    字节流 getOutputStream(); 常用于下载(传递)二进制数据
    字符流 getWriter(); 常用于回传字符串
    注:同一个HttpServletResponse对象两个流不可同时使用,只可二选一,否则报错:
    在这里插入图片描述
  3. 从服务器往客户端(浏览器)回传字符串数据

代码示例:在src下创建此类并在web.xml中进行配置

public class ResponseIO extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //防止中文乱码问题,在获取流对象之前调用此方法:
        //同时设置服务器和客户端都使用UTF-8字符集
        response.setContentType("text/html; charset=UTF-8");
        //获取流对象
        PrintWriter writer = response.getWriter();
        writer.write("I Love China!");
    }
}

运行结果:
在这里插入图片描述

十九、请求重定向

请求重定向指的是客户端给服务器发送请求,然后服务器通知客户端去访问自己的新地址(之前的地址可能被废弃)叫请求重定向
在这里插入图片描述
代码示例:1. 在src下创建此类并在web.xml中进行配置

public class Response1 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("会访问到Response1");
        //1.设置响应状态码302
        response.setStatus(302);
        //2.设置响应头说明新的地址在哪里
        response.setHeader("Location","http://localhost:8080/MyTest/Response2");
    }
}

代码示例:2. 在src下创建此类并在web.xml中进行配置

public class Response2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        response.getWriter().write("Response2's result!");
    }
}

运行结果:在地址栏输入http://localhost:8080/MyTest/Response1,得到:
在这里插入图片描述
并在控制台输出:会访问到Response1

注:

  1. 在Response1中使用以下代码替代两个步骤可得到同样的效果(推荐使用此方法):
    response.sendRedirect(“http://localhost:8080/MyTest/Response2”);
  2. 在Response1中request.setAttribute(“key1”, “value1”);
    在Response2中req.getAttribute(“key1”); 无法得到key1的值,结果为null

总结不易,点赞收藏~~~

猜你喜欢

转载自blog.csdn.net/weixin_49343190/article/details/107878144