HttpServletResponse和HttpServletRequest

1,294 阅读5分钟

HttpServletResponse

http响应由状态行,实体内容,消息头和一个空行组成,而HttpServletResponse对象封装了http响应信息,当我们想对页面做些什么时,则需要通过此对象。

getOutputStream()方法

该方法返回Servlet创建的字节输出流对象,通过该对象的print()方法和write()方法可以将内容写到页面中。

print()方法

print()方法可以将数字,true/false,字符和字符串写到页面中。

当print()方法接收的是一个字符串时,print()方法需要把它改成二进制数据,Tomcat默认使用IOS 8859-1编码对其进行转换,如果字符串中出现中文,由于中文不支持IOS 8859-1编码,因此会出现异常。

ServletOutputStream out = resp.getOutputStream();
out.print("中文");

write()方法

write()方法接收的参数如下所示。

不同于print()方法,write()方法能正常向页面输出中文,这是因为字符串转换为byte[]数组后,默认采用GB2312编码转化,而中文支持GB2312编码。

ServletOutputStream out = resp.getOutputStream();
out.write("Halo中午".getBytes());

为了编码的一致,一般采用UTF-8编码。不过这可能会导致乱码,这是因为浏览器默认采用GBK编码,而我们向服务器(Tomcat)输出的中文是UTF08编码。

ServletOutputStream out = resp.getOutputStream();
out.write("Halo中午".getBytes("UTF-8"));

因此我们需要在响应中告诉浏览器我们的信息是什么编码格式的,即在消息头中设置。

    resp.setHeader("Content-Type", "text/html;charset=UTF-8");
    ServletOutputStream out = resp.getOutputStream();
    out.write("Halo中午".getBytes("UTF-8"));

getWriter()方法

该方法返回字符输出流,它只能向页面输出字符数据,不能输出二进制数据。

    resp.setHeader("Content-Type", "text/html;charset=UTF-8");
    PrintWriter writer = resp.getWriter();
    writer.write("halo中午");

重定向

@WebServlet("/MServlet")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("MyPage/Test.jsp");
    }
}

这个过程出现了两个状态码:302表示临时重定向,当我们访问localhost:8080/MServlet时,MServlet告知浏览器它要的资源在index.jsp中,然后就会直接跳转到index.jsp页面,此时状态200表示成功。


HttpServletRequest

HttpServletRequest对象封装了客户端对服务器的请求信息。

防盗链

对于一些下载网站,通常会要求先在登陆页面登陆后,才能进入下载页面。如果直接复制下载页面地址来跳过登陆页面,则称为盗链。为了防止这种情况,就需要检查请求来源,比如只接收来自登陆页面的请求。

@WebServlet("/MServlet")
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String refer = req.getHeader("Referer");
        if(refer == null || !refer.contains("localhost:8080/index.jsp")) {
            resp.sendRedirect("index.jsp"); //跳转到index页面
            return;
        }
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().write("下载资源页面");
    }
}

index.jsp

html>
  <head>
    <title>登陆页面</title>
  </head>
  <body>
  <a href="MServlet">download</a>
  </body>
</html>

如果直接访问 localhost:8080/MServlet,是会直接跳转到index.jsp页面。只有在index.jsp页面中点击超链接,才能跳转到localhost:8080/MServlet页面

获取表单数据

<html>
  <head>
    <title>这里没东西</title>
  </head>
  <body>
    <form action="MServlet" method="post">
        <table>
            <tr>
                <td>用户名</td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td>密码</td>
                <td><input type="password" name="password"></td>
            </tr>

            <tr>
                <td>性别</td>
                <td>
                    <input type="radio" name="sex" value="男">男
                    <input type="radio" name="sex" value="女">女
                </td>
            </tr>

            <tr>
                <td>爱好</td>
                <td>
                    <input type="checkbox" name="hobbies" value="游泳">游泳
                    <input type="checkbox" name="hobbies" value="跑步">跑步
                    <input type="checkbox" name="hobbies" value="飞翔">飞翔
                </td>
            </tr>

            <tr>
                <td>你的家乡在哪里</td>
                <td>
                    <select name="address">
                        <option value="广州">广州</option>
                        <option value="深圳">深圳</option>
                        <option value="北京">北京</option>
                    </select>
                </td>
            </tr>

            <tr>
                <td><input type="submit" value="提交"></td>
            </tr>
        </table>

    </form>
  </body>
</html>
@WebServlet("/MServlet")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //服务器Tomcat默认采用ISO 8859-1编码来对中文编码,
    //而浏览器发送的中文是UTF-8编码
        req.setCharacterEncoding("UTF-8");

        System.out.println(req.getParameter("username"));
        System.out.println(req.getParameter("password"));
        System.out.println(req.getParameter("sex"));
        //数组存储选中的选项值
        String[] hobbies = req.getParameterValues("hobbies");
        String[] address = req.getParameterValues("address");

    }

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

本例采用的是POST来发送表单结果,各个结果会默认被封装到Form Data中

而如果采用get请求,则会将表单结果放在地址栏后面

转发

实现页面跳转有两种方式:前面介绍过的重定向

response.sendRedirect()

和转发

request.getRequestDispatcher.forward(request,response)。

在转发时可以通过req对象来传递数据,比如在两个Servlet中传递字符串:

@WebServlet("/MS")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("uName", "C2y");
        req.getRequestDispatcher("/AS").forward(req, resp);
    }
}
@WebServlet("/AS")
public class AnoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uName = (String)req.getAttribute("uName");
        resp.getWriter().write("the name is " + uName);
    }
}

此外实现Servlet通讯的方式还有以前提到的ServletContext, 一般情况下尽可能使用request对象,毕竟ServletContext代表整个web应用,这意味着会消耗大量资源,而request对象会随着请求的结束而结束。

转发和重定向的区别

(1)转发是由服务器进行跳转的, 转发过程中浏览器的地址栏是没有变化的,即浏览器不知道跳转的动作;而重定向是由浏览器进行跳转的,因此浏览器地址会变化。

(2)转发只是一次http请求,一次转发中的request和response对象都是同一个。因此request可以作为Servlet通讯的媒介;而重定向发出的是两个http请求,两次request对象是不同的。


参考资料

Servlet第三篇【request和response简介、response的常见应用】

Servlet第四篇【request对象常用方法、应用】