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对象是不同的。