Java Web Servlet (Part C)- HttpServletRequest & HttpServletResponse

"Offer arrives, dig friends to pick up! I am participating in the 2022 Spring Recruitment Check-in Event, click to view the details of the event ."

一、HttpServletRequest

Whenever a request enters Tomcat, the Tomcat server will parse and encapsulate the requested HTTP protocol information into the HttpServletRequest object, and then pass it to the service method. The information in the request sent by the client can be obtained through the HttpServletRequest object.

Common methods of HttpServletRequest

  • getRequestURI(), get the requested resource path
  • gerRequestURL(), get the requested Uniform Resource Locator
  • getRemoteHost(), get the client IP
  • getHeader(), get the request header
  • getParameter(), get the parameters of the request
  • getParameterValues(), get the values ​​of multiple parameters in the request
  • getMethod(), get the request method, GET or POST
  • setAttribute(key,value), set domain data
  • getAttribute(key), get domain data
  • getRequestDispatcher(), get the request forwarding object

Add HiServlet in the controller package

public class HiServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 1. 获取请求的资源路径
        System.out.println("请求资源路径为:" + req.getRequestURI());
        // 2. 获取请求的URL地址
        System.out.println("请求的URL地址为:" + req.getRequestURL());
        // 3. 获取请求的客户端IP地址
        System.out.println("客户端IP地址为:" + req.getRemoteHost());
        // 4. 获取请求头
        System.out.println("请求头为:" + req.getHeader("User-Agent"));
        // 5. 获取请求方式
        System.out.println("请求方式为:" + req.getMethod());
    }
}
复制代码

Configure the access path of the servlet in web.xml

<servlet>
    <servlet-name>HiServlet</servlet-name>
    <servlet-class>com.lilith.servlet.HiServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>HiServlet</servlet-name>
    <url-pattern>/hi</url-pattern>
</servlet-mapping>
复制代码

Restart Tomcat, and the browser access http://localhost:8080/hi

image.png

Add a form.html page to the web directory and add a new form

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Form</title>
</head>
<body>
<form action="/param" method="get">
    用户名:<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="python"> Python <br>
    <input type="submit" value="提交">
</form>
</body>
</html>
复制代码

Added ParamServlet class to get the data submitted by the form

public class ParamServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求中的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String hobby = req.getParameter("hobby");
        System.out.println("请求中username参数的值为:" + username);
        System.out.println("请求中password参数的值为:" + password);
        System.out.println("请求中hobby参数的值为:" + hobby);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}
复制代码

Add the access configuration of ParamServlet in web.xml

<servlet>
    <servlet-name>ParamServlet</servlet-name>
    <servlet-class>com.lilith.servlet.ParamServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>ParamServlet</servlet-name>
    <url-pattern>/param</url-pattern>
</servlet-mapping>
复制代码

Restart Tomcat, enter http://localhost:8080/form.html in the browser, and click submit after entering data in the form

image.png

当参数有多个值时,需要使用getParameterValues来获取,getParameter只能获取参数的第一个值

// 获取请求中的参数(有多个值)
String[] hobbies = req.getParameterValues("hobby");
System.out.println("请求中hobby参数的所有值:" + Arrays.asList(hobbies));
复制代码

中文乱码问题

表单中输入中文,点击提交

image.png

当请求方式为GET请求时,中文可以正常显示

更改form.html中请求方式为post,将goGet方法中的代码拷贝至doPost方法中,在表单中再次提交中文信息

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("doPost方法被调用!");
    // 获取请求中的参数
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    String hobby = req.getParameter("hobby");
    System.out.println("请求中username参数的值为:" + username);
    System.out.println("请求中password参数的值为:" + password);
    System.out.println("请求中hobby参数的值为:" + hobby);

    // 获取请求中的参数(有多个值)
    String[] hobbies = req.getParameterValues("hobby");
    System.out.println("请求中hobby参数的所有值:" + Arrays.asList(hobbies));
}
复制代码

image.png 根据控制台的输出,POST提方式提交时中文乱码了。

doPost方法中增加编码设置

req.setCharacterEncoding("UTF-8");
复制代码

再次提交表单

image.png

中文乱码问题已解决

Servlet的请求转发

请求转发是指服务器收到请求后,从一个资源跳转到另一个资源的操作。

在controller包中新建两个Servlet类AlphaServlet和BravoServlet,用作实现请求转发

public class AlphaServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求参数
        String username = req.getParameter("username");
        System.out.println("alpha请求中参数username的值为:" + username);

        // 要转发到BravoServlet的地址
        // 请求转发的地址必须要以/开头
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/bravo");
        // 转发到BravoServlet
        requestDispatcher.forward(req,resp);
    }
}
复制代码
public class BravoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String username = req.getParameter("username");
        System.out.println("bravo请求中参数username的值为:" + username);

        System.out.println("BravoServlet业务处理");
    }
}
复制代码

在web.xml中配置AlphaServlet和BravoServlet的访问路径

<servlet>
    <servlet-name>AlphaServlet</servlet-name>
    <servlet-class>com.lilith.servlet.AlphaServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>AlphaServlet</servlet-name>
    <url-pattern>/alpha</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>BravoServlet</servlet-name>
    <servlet-class>com.lilith.servlet.BravoServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>BravoServlet</servlet-name>
    <url-pattern>/barvo</url-pattern>
</servlet-mapping>
复制代码

重新启动Tomcat,在浏览器中输入 http://localhost:8080/alpha?username=peter, 点击回车 image.png

F12打开浏览器的检查页面,查看网络可以确定从请求AlphaServlet然后转发到BravoServlet只发了一次请求,也就是说请求AlphaServlet和AlphaServlet转发到BravoServlet是同一个请求,所以在两个Servlet中都可以获取到username参数的值 image.png 并且浏览器的地址栏没有变化。

请求转发可以访问WEB-INF下的文件

在WEB-INF下新建success.html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>SUCCESS</title>
</head>
<body>
<h1>成功转发到WEB-INF目录下</h1>
</body>
</html>
复制代码

修改AlphaServlet,使其转发到success.html页面

RequestDispatcher requestDispatcher = req.getRequestDispatcher("/WEB-INF/success.html");
复制代码

重新启动应用

image.png 浏览器输出了success页面的内容,转发可以访问WEB-INF下的文件

请求转发的特点

  • 浏览器地址栏没有变化
  • 是同一次请求
  • 共享Request域中的数据
  • 可以转发到WEB-INF目录下
  • 不可以访问工程以外的资源

Web中的相对路径和绝对路径

在JavaWeb中,路径分为相对路径和绝对路径 相对路径

  • .:表示当前目录
  • ..:表示上一级目录
  • 资源名:表示当前目录/资源

绝对路径

Web中 “/” 的不同意义

在Web中 “/” 是一种绝对路径

二、HttpServletResponse

HttpServletResponse和HttpServletRequest类一样,每次请求进来Tomcat都会创建一个Response对象传递给Servlet程序使用,HttpServletRequest表示请求传过来的信息,HttpServletResponse表示所有响应的信息;如果需要返回给客户端消息,可以使用HttpServletResponse对象来进行设置

HttpServletResponse使用输出流来给客户端发送消息

  • 字节流,getOutputStream(); 常用于下载(传递二进制数据)
  • 字符流,getWriter();常用与回传字符串(常用)

另个流只能同时使用一个。

在controller包中创建一个SteamServlet类,同时使用字符流和字节流

public class StreamServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.getWriter();
        resp.getOutputStream();
    }
}
复制代码

在web.xml中配置Servlet的访问路径

<servlet>
    <servlet-name>SteamServlet</servlet-name>
    <servlet-class>com.lilith.servlet.StreamServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>SteamServlet</servlet-name>
    <url-pattern>/stream</url-pattern>
</servlet-mapping>
复制代码

重启Tomcat,浏览器输入 http://localhost:8080/stream

image.png 页面出现报错

修改StreamServlet,只使用字符流

public class StreamServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        PrintWriter writer = resp.getWriter();
        // resp.getOutputStream();
        writer.write("Response Content");
    }
}
复制代码

重启Tomcat,浏览器输入 http://localhost:8080/stream image.png 浏览器返回response信息

响应中文乱码问题解决方案一

设置StreamServlet中返回的内容是中文格式,并重启Tomcat,浏览器输入同一地址 image.png 页面输出的中文出现乱码现象

在代码中获取字符编码,重启Tomcat,访问同一地址 image.png

在代码中设置响应的编码格式

public class StreamServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 设置UTF-8编码
        resp.setCharacterEncoding("UTF-8");
        PrintWriter writer = resp.getWriter();
        // resp.getOutputStream();
        String characterEncoding = resp.getCharacterEncoding();
        System.out.println("字符编码给为:" + characterEncoding);
        
        writer.write("这是响应内容");

    }
}
复制代码

重启Tomcat,访问/stream image.png 还是出现乱码现象

应为还需要通过请求头设置浏览器字符集

public class StreamServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 设置UTF-8编码
        resp.setCharacterEncoding("UTF-8");
        // 响应头设置UTF-8字符集
        resp.setHeader("Content-Type","text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        // resp.getOutputStream();
        String characterEncoding = resp.getCharacterEncoding();
        System.out.println("字符编码给为:" + characterEncoding);

        writer.write("这是响应内容");

    }
}
复制代码

重启Tomcat,访问/stream image.png 中文可以正常显示

响应中文乱码问题解决方案二

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    // 设置UTF-8编码
    // resp.setCharacterEncoding("UTF-8");
    // 响应头设置UTF-8字符集
    // resp.setHeader("Content-Type","text/html;charset=UTF-8");

    // 一句代码解决
    resp.setContentType("text/html;charset=UTF-8");
    PrintWriter writer = resp.getWriter();
    // resp.getOutputStream();
    String characterEncoding = resp.getCharacterEncoding();
    System.out.println("字符编码给为:" + characterEncoding);

    writer.write("这是响应内容");

}
复制代码

使用resp.setContentType("text/html;charset=UTF-8") 可以同时设置服务器和客户端都是用UTF-8编码,同时设置了响应头,并且该方法一定要在获取流对象之前调用才会生效

重启Tomcat,再次访问/stream image.png

请求重定向

请求重定向,指的是客户端发送给服务器请求后,服务端返回一个新的地址,客户端重新访问这个新的地址,称为请求的重定向。

在controller包中新建两个Servlet,用于实现请求的重定向

public class DeltaServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println(this.getClass().getName());

        resp.setStatus(302);
        resp.setHeader("Location","http://localhost:8080/echo");
    }
}
复制代码
public class EchoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println(this.getClass().getName());
        resp.getWriter().write(this.getClass().getName());
    }
}
复制代码

在web.xml配置两个Servlet的访问路径

<servlet>
    <servlet-name>DeltaServlet</servlet-name>
    <servlet-class>com.lilith.servlet.DeltaServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>DeltaServlet</servlet-name>
    <url-pattern>/delta</url-pattern>
</servlet-mapping>
<servlet>
    <servlet-name>EchoServlet</servlet-name>
    <servlet-class>com.lilith.servlet.EchoServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>EchoServlet</servlet-name>
    <url-pattern>/echo</url-pattern>
</servlet-mapping>
复制代码

重启Tomcat,并在浏览器中输入http://localhost:8080/delta image.png

根据浏览器的显示的内容可以确定请求重定向的一些特点

  • 请求重定向发生后浏览器地址栏会发生变化
  • 请求重定向实际发生了两次请求
  • 请求重定向不共享Request域中的数据

测试重定向是否能够跳转到WEB-INF下面的页面中

resp.setHeader("Location","http://localhost:8080/WEB-INF/success.html");
复制代码

重新启动应用

image.png 访问失败,重定向不可以访问WEB-INF下的资源,但是重定向可以反问工程外的资源

请求重定向第二种实现方式(推荐使用)

resp.sendRedirect("http://localhost:8080/echo");
复制代码

Instead of setting the response code and header

public class DeltaServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println(this.getClass().getName());

        // resp.setStatus(302);
        // // resp.setHeader("Location","http://localhost:8080/echo");
        // resp.setHeader("Location","http://localhost:8080/WEB-INF/success.html");
        resp.sendRedirect("http://localhost:8080/echo");
    }
}
复制代码

Restart the application, redirection can still be achieved, the second method is recommended

Guess you like

Origin juejin.im/post/7078548826092470309