Response:代表响应的对象.从服务器向浏览器输出内容。
Response的常用API
响应行:设置状态码。
void setStatus(int sc)
Sets the status code for this response.
响应头:
* 针对一个key对应多个value的头信息
void addDateHeader(String name, long date)
Adds a response header with the given name and date-value.
void addHeader(String name, String value)
Adds a response header with the given name and value.
void addIntHeader(String name, int value)
Adds a response header with the given name and integer value.
boolean containsHeader(String name)
Returns a boolean indicating whether the named response header has already been set.
* 针对一个key对应一个value的头信息
void setDateHeader(String name, long date)
Sets a response header with the given name and date-value.
void setHeader(String name, String value)
Sets a response header with the given name and value.
void setIntHeader(String name, int value)
Sets a response header with the given name and integer value.
响应体:
ServletOutputStream getOutputStream()
Returns a ServletOutputStream suitable for writing binary data in the response.
PrintWriter getWriter()
Returns a PrintWriter object that can send character text to the client.
登录页面跳转
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class UserRefreshServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 解决向页面输出中文的乱码问题!!! response.setContentType("text/html;charset=UTF-8"); // 1.接收表单提交的参数. String username = request.getParameter("username"); String password = request.getParameter("password"); // 2.封装到实体对象中. User user = new User(); user.setUsername(username); user.setPassword(password); // 3.调用业务层处理数据. UserService userService = new UserService(); User existUser = userService.login(user); // 4.根据处理结果显示信息(页面跳转). if(existUser == null){ // 登录失败 response.getWriter().println("<h1>登录失败:用户名或密码错误!~</h1>"); }else{ // 登录成功 // response.getWriter().println("Login Success..."); response.getWriter().println("<h1>登录成功!您好:"+existUser.getNickname()+"</h1>"); response.getWriter().println("<h3>页面将在5秒后跳转!</h3>"); response.setHeader("Refresh", "5;url=/day09/demo5-refresh/index.html"); } } catch (Exception e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
更改上面的登录成功后的页面刷新为重定向: if(existUser == null){ // 登录失败 response.getWriter().println("<h1>登录失败:用户名或密码错误!~</h1>"); }else{ // 登录成功 // response.getWriter().println("Login Success..."); /*response.getWriter().println("<h1>登录成功!您好:"+existUser.getNickname()+"</h1>"); response.getWriter().println("<h3>页面将在5秒后跳转!</h3>"); response.setHeader("Refresh", "5;url=/day09/demo5-refresh/index.html");*/ response.setStatus(302); // 重定向到success.html response.setHeader("Location", "/day09/demo5-refresh/success.html"); } success.html页面 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="Refresh" content="5;url=/day09/demo5-refresh/index.html"/> <!-- 上面meta标签的http-equiv属性和content属性的组合就相当于响应头和值 --> <title>Insert title here</title> <script type="text/javascript"> var time = 5; window.onload = function(){ setInterval('changeTime()',1000); } function changeTime(){ time--; document.getElementById("s1").innerHTML = time; } </script> <!-- 数字的变化再用js来做修改 --> </head> <body> <h1>登录成功!</h1> <h3>页面将在<span id="s1">5</span>秒后跳转!</h3> </body> </html>
文件的下载
一种:超链接下载.直接将文件的路径写到超链接的href中.---前提:文件类型,浏览器不支持.
二种:手动编写代码的方式完成文件的下载.
* 设置两个头和一个流:
* Content-Type: 文件的MIME的类型.
* Content-Disposition: 以下载的形式打开文件.
* InputStream: 文件的输入流.
下载的实现代码:
public class DownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.接收参数 String filename = new String(request.getParameter("filename").getBytes("ISO-8859-1"),"UTF-8"); System.out.println(filename); // 2.完成文件下载: // 2.1设置Content-Type头 String type = this.getServletContext().getMimeType(filename); response.setHeader("Content-Type", type); // 2.3设置文件的InputStream. String realPath = this.getServletContext().getRealPath("/download/"+filename); // 根据浏览器的类型处理中文文件的乱码问题: // IE浏览器下载中文文件的时候采用的URL的编码. // Firefox浏览器下载中文文件的时候采用的是Base64的编码. String agent = request.getHeader("User-Agent"); System.out.println(agent); if(agent.contains("Firefox")){ filename = base64EncodeFileName(filename); }else{ filename = URLEncoder.encode(filename,"UTF-8"); } // 2.2设置Content-Disposition头 response.setHeader("Content-Disposition", "attachment;filename="+filename); InputStream is = new FileInputStream(realPath); // 获得response的输出流: OutputStream os = response.getOutputStream(); int len = 0; byte[] b = new byte[1024]; while((len = is.read(b))!= -1){ os.write(b, 0, len); } is.close(); } public static String base64EncodeFileName(String fileName) { BASE64Encoder base64Encoder = new BASE64Encoder(); try { return "=?UTF-8?B?" + new String(base64Encoder.encode(fileName .getBytes("UTF-8"))) + "?="; } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException(e); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
response输出中文乱码的处理
* 字节流:
* 设置浏览器默认打开的编码:
* resposne.setHeader(“Content-Type”,”text/html;charset=UTF-8”);
* 设置中文字节取出的时候编码.
* “中文”.getBytes(“UTF-8”);
* 字符流:
* 设置浏览器打开的时候的编码
* resposne.setHeader(“Content-Type”,”text/html;charset=UTF-8”);
* 设置response的缓冲区的编码,将字符以"UTF-8"编码输出到客户端浏览器
* response.setCharacterEncoding(“UTF-8”);
* 简化的写法:response.setContentType(“text/html;charset=UTF-8”);
request接收参数的中文乱码的处理
post请求
* 设置request的缓冲区的编码:
* request.setCharacterEncoding(“UTF-8”); --- 一定要在接收参数之前设置编码就OK.
get请求
* 1.修改 tomcat 的字符集编码(不推荐)。 confserver.xmlConnectorURIEncoding="utf-8"
* 2.使用URLEncoder和URLDecoder进行编码和解码的操作.
* 3.使用String的构造方法:
String name = request.getParameter("name");
name =new String(name.getBytes("ISO8859-1"), "UTF-8");
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
以post方式提交数据: 浏览器将数据(假设为“中国”)发送给服务器的时候,将数据变成0101的二进制数据(假设为98 99)时必然要查码表,浏览器以哪个码表打开网页,浏览器就以哪个码表提交数据。数据到达服务器后,数据(98 99)要封装到request中,在servlet中调用Request的getParameter方法返回的是字符串(“中国”),方法内部拿到数字后要转成字符,一定要查码表,由于request的设计者是外国人,所以默认查的是他们常用的ISO8859-1,这就是请求数据产生乱码的根源。 以get方式提交数据: get方式提交的数据依然是浏览器用什么码表打开就用什么码表发送。不同的是,以get方式提交数据时,request设置编码无效。即使设置了UTF-8还是会去查ISO8859-1。得到(? ?),要解决这个问题,需要拿着(??)反向查ISO8859-1,拿到(98 99)后,再去查正确码表。
重定向和转发区别
重定向: response.sendRedirect(request.getContextPath()+"/ListServlet?method=findAll"); //全路径
转发: request.getRequestDispatcher("/jsp/XXX.jsp").forward(request, response); //不含工程名的相对路径
1.重定向的地址栏会发生变化,转发的地址栏不变.
2.重定向两次请求两次响应,转发一次请求一次响应.
3.重定向路径需要加工程名,转发的路径不需要加工程名.
4.重定向可以跳转到任意网站,转发只能在服务器内部进行转发.
5.重定向的过程中,传输的信息会被丢失。转发不会。
转发过程:客户浏览器发送http请求——> web服务器接受此请求 ——>调用内部的一个方法在容器内部完成请求处理和转发动作 ——> 将目标资源发送给客户。在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。
重定向过程:客户浏览器发送http请求——> web服务器接受后发送302状态码响应及对应新的location给客户浏览器 ——> 客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址 ——> 服务器根据此请求寻找资源并发送给客户。在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。
addHeader与setHeader区别
1、同名Header可以有多个 ,Header[] getHeaders(String name)。
2、运行时使用的是第一个, Header getFirstHeader(String name)。
3、addHeader,如果同名header已存在,则追加至原同名header后面。
4、setHeader,如果同名header已存在,则覆盖一个同名header。
Request作为域对象存取数据
使用request对象存取数据:
* setAttribute(String name,String value);
* Object getAttribute(String name);
request的作用范围:
* 作用范围就是一次请求的范围。
* 创建和销毁:
* 创建:客户端向服务器发送了一次请求以后,服务器就会创建一个request的对象。
* 销毁:当服务器对这次请求作出了响应之后。