首页 > 技术文章 > 16、请求和响应

1989guojie 2016-12-05 17:27 原文

 
 

一、HttpServletResponse(服务器-->客户端)

响应行、响应头、响应体
里面有很多常量代表状态吗404等

1、响应行  

HTTP/1.1   200   OK
setStatus(int sc);   //设置响应状态码(200)
 

2、响应头

1 sendRedirect(String location)  // 请求重定向 (常用)
2 setHeader(String name, String value)   // 设置响应头信息
response.setHeader("content-type", "text/html;charset=UTF-8");  //告知浏览器使用什么码表
1 //告知客户端不缓存
2  response.setHeader("pragma", "no-cache");
3  response.setHeader("cache-control", "no-cache");
4  response.setDateHeader("expires", 0);
response.setIntHeader("refresh", 1);   //  刷新
response.setHeader("content-disposition", "attatchment;filename="+filename)  // 告诉浏览器下载文件
filename = URLEncoder.encode(filename, "UTF-8");  // 解决乱码,设置文件名的编码,将不安全的文件名改为UTF-8
1 // 虽然这两行代码在之前,但是只是告诉浏览器要重定向,再由浏览器重定向
2 response.setStatus(302);  // 告诉客户端重新定向新的资源
3 // 告诉浏览器要去访问那个URL
4 response.setHeader("location", "/httpServletResponce/demo8");  // 客户端执行,/如果是服务器直接解析就是代表当前应用;要是客户端解析是服务器的根目录就是8080下的/
1 // 重定向,告诉浏览器重定向和重定向到哪个URL
2 response.sendRedirect("/httpServletResponce/demo8");

 

3、响应正文(主体)

1 getWrite();   // 字符输出流
2 getOutputStream();   // 字节输出流
3 setCharacterEncoding(String charset);   // resuest.setCharacterEncoding,告知服务器要使用什么编码,浏览器使用的什么编码传过来的就是什么编码  客户端-->服务器
4 setContentType(String type);  // response.setContentType, 封装了setCharacterEncoding、setHeader,告知服务器使用了什么编码,客户端要使用什么编码,服务器传过来的是什么编码就是什么编码 (常用服务器-->客户端
 1 public void doGet(HttpServletRequest request, HttpServletResponse response)
 2         throws ServletException, IOException {
 3     // 服务器中默认编码为IOS8859-1,不支持中文,tomcat规定
 4     response.setCharacterEncoding("UTF-8");  // 告诉服务器用UTF-8解码
 5     response.setHeader("Content-type", "text/html;charset=UTF-8");  // 告诉客户端用什么编码
 6     // 告诉服务器使用的是UTF-8解析文本,告诉客户端使用什么编码
 7     response.setContentType("text/html;charset=UTF-8");
 8     
 9     PrintWriter writer = response.getWriter(); // 得到字符输出流
10     writer.write("你好");  // 向客户端响应文本内容,出现?
11 }
1 public void doGet(HttpServletRequest request, HttpServletResponse response)
2         throws ServletException, IOException {
3     
4     ServletOutputStream out = response.getOutputStream();
5     out.write("你好".getBytes());  // String的getBytes使用平台的字符集
6 }

 

4、常见应用:

(1)文件下载

(2)验证码

输出随机图片(CAPTCHA图像):Completely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的测试)
刷新网页不变是缓存的原因
(3)刷新和跳转页面
 
1 //告知各种客户端不缓存
2  response.setHeader("pragma", "no-cache");
3  response.setHeader("cache-control", "no-cache");
4  response.setDateHeader("expires", 0);  // 系统时间和设置时间差就是缓存时间

 

 1 // 文件下载
 2 public void doGet(HttpServletRequest request, HttpServletResponse response)
 3         throws ServletException, IOException {
 4     // 通过路径得到一个输入流
 5     String path = this.getServletContext().getRealPath("/WEB-INF/classes/美女.jpg");
 6     FileInputStream file = new FileInputStream(new File(path));
 7     // 创建字节输出流
 8     ServletOutputStream sos = response.getOutputStream();
 9     
10     // 得到要下载的文件名
11     String filename = path.substring(path.lastIndexOf("\\")+1);
12     // 设置文件名的编码,将不安全的文件名改为UTF-8
13     filename = URLEncoder.encode(filename, "UTF-8");
14     // 告知客户端要下载文件
15     response.setHeader("content-disposition", "attatchment;filename="+filename);
16     response.setHeader("content-type", "image/jpeg");  // jpeg简称jpg
17     // 执行输出操作
18     int length = 0;
19     byte[] buf = new byte[1024];
20     while((length=file.read(buf))!=-1) {
21         sos.write(buf, 0, length);
22     }
23     // 关闭资源
24     sos.close();
25     file.close();
26 }
 1 // 自定义验证码
 2 private void test1(HttpServletResponse response) throws IOException {
 3     int width = 110;
 4     int height = 25;
 5     // 在内存中创建图片对象
 6     BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
 7     
 8     // 创建一个画笔
 9     Graphics g = image.getGraphics();
10     
11     // 给图片添加背景色
12     g.setColor(Color.PINK);
13     g.fillRect(1, 1, width-2, height-2);  // 填充
14     
15     // 给边框一个颜色
16     g.setColor(Color.RED);
17     g.drawRect(0, 0, width-1, height-1);
18     
19     // 设置文本样式
20     g.setColor(Color.BLUE);
21     g.setFont(new Font("宋体", Font.BOLD|Font.ITALIC, 15));
22     
23     // 给图片添加文本
24     Random r = new Random();
25     int position = 20;
26     for(int i=0; i < 4; i++) {
27         g.drawString(r.nextInt(10)+"", position, 20);
28         position+=20;
29     }
30     
31     // 添加干扰线,确定左右两个点
32     for(int i=0; i<9; i++) {
33         g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
34     }
35     
36     // 将图片对象以流的形式输出到客户端
37     ImageIO.write(image, "jpg", response.getOutputStream());
38 }
// 利用ValidateCode封装好的验证码类实现验证码。网上有很多
private void test2(HttpServletResponse response) throws IOException {
    
    ValidateCode vc = new ValidateCode();
    vc.write(response.getOutputStream());
}
 1 <head>
 2 <script type="text/javascript">
 3     function changeCode(){
 4         // 得到图片元素
 5         var img = document.getElementsByTagName("img")[0];
 6         // img.setAttribute("src","/httpServletResponce/demo4");  // XML Dom语法
 7         img.src="/httpServletResponce/demo4?time="+new Date().getTime();  // 浏览器缓存会造成不会改变,两次时间改一下
 8     }
 9 </script>
10 </head>
11 <body>
12     <form action="#" method="post">
13         用户名:<input type="text" name="userName"/><br>
14         密码:<input type="password" name="pwd"/><br>
15         用户名:<input type="text" name="code"/>
16         <img src="/httpServletResponce/demo4" onclick="changeCode()"/><a href="javascript:changeCode()">看不清换一张</a><br>  <!-- src也会发送请求 -->
17         <input type="submit" value="提交"/><br>
18     </form>
19 
20 </body>

 

 

1 // 刷新
2 private void test3(HttpServletResponse response) throws IOException {
3     response.setIntHeader("refresh", 1);  // 1s钟刷新一次
4     
5     Random random = new Random();
6     response.getWriter().write(random.nextInt(100)+"");
7 }
1 // 跳转到主页
2 private void test4(HttpServletResponse response) throws IOException {
3     // 设置字符集避免乱码
4     response.setContentType("text/html;charset=UTF-8");
5     response.getWriter().write("注册成功,3s之后跳转到主页");
6     // 设置3s跳转到demo6
7     response.setHeader("refresh", "3;url=/httpServletResponce/demo6");
8 }

 

response注意:

(1)getOutputStream和getWriter方法分别用于得到输出二进制数据、输出文本数据的ServletOuputStream、Printwriter对象。
(2) getOutputStream和getWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法,会抛异常。
(3) Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端。
(4) Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象。

 

 二、HttpServletRequest(客户端-->服务器)

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息,查看request的API文档

域对象,维护了map,请求一次有效

1、请求行

1 Get http://localhost:8080/day09/servlet/req1 ?username=zs http/1.1
2 getMethod();    //获得请求方式
3 getRequestURL();  // 返回客户端发出请求时的完整URL。(常用
4 getRequestURI();  // 返回请求行中的资源名部分。(常用
5 getContextPath();  // 当前应用的虚拟目录 /day09_01_request (常用
6 getQueryString() ;  // 返回请求行中的参数部分。

 

2、请求消息头

1  String getHeader(String name)    // 根据头名称得到头信息值
2  Enumeration getHeaderNames()   // 得到所有头信息name
3  Enumeration getHeaders(String name)   // 根据头名称得到相同名称头信息值

 

 1 // 判断使用的是哪个浏览器
 2 public void doGet(HttpServletRequest request, HttpServletResponse response)
 3         throws ServletException, IOException {
 4     String header = request.getHeader("User-Agent");
 5     if(header.toLowerCase().contains("msie")) {
 6         System.out.println("你使用的是IE浏览器");
 7     } else if(header.toLowerCase().contains("firefox")) {
 8         System.out.println("你使用的是火狐浏览器");
 9     } else if(header.toLowerCase().contains("chrome")) {
10         System.out.println("你使用的是谷歌浏览器");
11     } else {
12         System.out.println("你使用的是其他浏览器");
13     }
14 }
 1 public void doGet(HttpServletRequest request, HttpServletResponse response)
 2         throws ServletException, IOException {
 3 /*  host:localhost:8080
 4     connection:keep-alive
 5     cache-control:max-age=0
 6     upgrade-insecure-requests:1
 7     user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.59 Safari/537.36
 8     accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*;q=0.8
 9     accept-encoding:gzip, deflate, sdch, br
10     accept-language:zh-CN,zh;q=0.8,en;q=0.6
11 */
12     // 获取所有消息头的name
13     Enumeration names = request.getHeaderNames();
14     while(names.hasMoreElements()) {
15         String e = (String) names.nextElement();
16         System.out.println(e+":"+request.getHeader(e));
17     }
18 }

 

3、请求正文(重要

(1)与获取表单数据相关的方法
1 <input type="text" name="username" />
2 getParameter(name)   //根据表单中name属性的名,获取value属性的值方法(常用)
3 getParameterValues(String name)  // 专业为复选框取取提供的方法(常用
4 getParameterNames()   // 得到表单提交的所有name的方法
5 getParameterMap   // 到表单提交的所有值的方法 //做框架用,非常实用(常用
6 getInputStream   // 以字节流的方式得到所有表单数据
 1 // 要提交的表单
 2 <body>
 3     <form action="/httpServletRequest/demo2" method="post">
 4         用户名:<input type="text" name="userName"/><br/>
 5         密码:<input type="password" name="pwd"/><br/>
 6         性别:<input type="radio" name="sex" value="男" checked="checked"/>
 7             <input type="radio" name="sex" value="女" /><br/>
 8         爱好:<input type="checkbox" name="hobby" value="篮球"/>篮球
 9             <input type="checkbox" name="hobby" value="羽毛球"/>羽毛球
10             <input type="checkbox" name="hobby" value="乒乓球"/>乒乓球<br/>
11         所在城市:
12         <select name="city">
13             <option>=====请选择======</option>
14             <option value="bj">北京</option>
15             <option value="sh">上海</option>
16             <option value="gz">广州</option>
17             <option value="sz">深圳</option>
18         </select>
19         <br/>
20         
21         <input type="submit" value="注册"/>
22     </form>
23 </body>
 1 // 以post方式提交表单
 2 public void doGet(HttpServletRequest request, HttpServletResponse response)
 3         throws ServletException, IOException {
 4     // 告诉服务器使用什么编码,浏览器使用的是什么编码传过来的就是什么编码
 5     request.setCharacterEncoding("UTF-8");  // 要是get方法会一直出现乱码,post则不会
 6     
 7     // 获取表单数据
 8     String userName = request.getParameter("userName");  // 根据表单中name属性的名,获取value属性的值方法
 9     String pwd = request.getParameter("pwd");
10     String sex = request.getParameter("sex");    
11     String[] hobbys = request.getParameterValues("hobby");
12     String city = request.getParameter("city");
13     
14     System.out.println(userName);
15     System.out.println(pwd);
16     System.out.println(sex);
17     
18     for (int i = 0; hobbys!=null && i < hobbys.length; i++) {
19         System.out.println(hobbys[i]+"\t");
20     }
21     
22     System.out.println(city);
23 }
 1 public void doGet(HttpServletRequest request, HttpServletResponse response)
 2         throws ServletException, IOException {
 3     // 告诉服务器使用什么编码,浏览器使用的是什么编码传过来的就是什么编码
 4     request.setCharacterEncoding("UTF-8");  // 要是get方法会一直出现乱码,post则不会
 5     
 6     Enumeration names = request.getParameterNames();  // 获取所有表单name的名字
 7     while(names.hasMoreElements()) {
 8         String name = (String) names.nextElement();  // 表单数据全是String,得到每一个name名
 9         String[] values = request.getParameterValues(name);  // 根据name名得到value值
10         for (int i = 0; i < values.length && values != null; i++) {
11             System.out.println(name+"\t"+values[i]);
12         }
13     }
14 }

 

 1 // 获取表单数据
 2 private void test1(HttpServletRequest request) {
 3     
 4     String userName = request.getParameter("userName");  // 根据表单中name属性的名,获取value属性的值方法
 5     String pwd = request.getParameter("pwd");
 6     String sex = request.getParameter("sex");    
 7     String[] hobbys = request.getParameterValues("hobby");
 8     String city = request.getParameter("city");
 9     
10     System.out.println(userName);
11     System.out.println(pwd);
12     System.out.println(sex);
13     
14     for (int i = 0; hobbys!=null && i < hobbys.length; i++) {
15         System.out.println(hobbys[i]+"\t");
16     }
17     
18     System.out.println(city);
19 }
 1 // 输出对应表单name对应的value
 2 private void test2(HttpServletRequest request) {
 3     Enumeration names = request.getParameterNames();  // 获取所有表单name的名字
 4     while(names.hasMoreElements()) {
 5         String name = (String) names.nextElement();  // 表单数据全是String,得到每一个name名
 6         String[] values = request.getParameterValues(name);  // 根据name名得到value值
 7         for (int i = 0; i < values.length && values != null; i++) {
 8             System.out.println(name+"\t"+values[i]);
 9         }
10     }
11 }
 1 // 封装表单数据,方式一,底层
 2 private void test3(HttpServletRequest request) {
 3     try {
 4         User user = new User();
 5         
 6         Map<String, String[]> map = request.getParameterMap();  // 获取表单数据,键-值
 7         
 8         for (Map.Entry<String, String[]> m : map.entrySet()) {
 9             String name = m.getKey();  // key
10             String[] value = m.getValue();
11             
12             // 创建一个属性描述器,反射内省
13             PropertyDescriptor pd = new PropertyDescriptor(name, User.class);  // 在实体类中字段要与表单中的name一致,约定优于编码,方便反射
14             // 得到setter属性,成员变量叫字段,setter等方法叫属性
15             Method setter = pd.getWriteMethod();
16             
17             if(value.length==1) {  // 值只有一项
18                 setter.invoke(user, value[0]);  // 给一个变量赋值
19             } else {  // 多项
20                 // jdk1.5之前value会被拆成多个对象,之后不会
21                 setter.invoke(user, (Object)value);  // 给复选框赋值
22             }
23         }
24         System.out.println(user);
25     } catch (Exception e) {
26         e.printStackTrace();
27     }
28 }
1 // 封装表单数据,方式二,用框架BeanUtils (好用)
2 private void test4(HttpServletRequest request) {
3     try {
4         User u = new User();
5         BeanUtils.populate(u, request.getParameterMap());
6     } catch (Exception e) {
7         e.printStackTrace();
8     }
9 }

entity 实体
domain 域
将表单数据封装成一个类传递给数据库插入
在实体类中字段要与表单中的name名一直,约定优于编码。反射中有使用
此后成员变量不叫属性,叫字段;getXxx方法才叫属性

 

(2)与操作非表单数据相关的方法(request也是一个域对象)
1 void setAttribute(String name, Object value); (常用2 Object getAttribute(String name); (常用3 Void removeAttribute(String name);
 
 
(3)与请求转发相关的方法
1 RequestDispatcher getRequestDispatcher(String path)  //得到请求转发或请求包含的协助对象
2 forward(ServletRequest request, ServletResponse response) //转发的方法 (常用
3 include(ServletRequest request, ServletResponse response) //请求包含

 转发(RequestDispatcher)和重定向(sendRedirect)

 

 

(4)与请求编码相关的方法:
1 //解决post方式编码
2 request.setCharacterEncoding("UTF-8"); //告诉服务器客户端要使用什么编码,只能处理post请求方式(常用3 //解决get方式编码,少,每个又要写一次
4 String name = new String(name.getBytes( “iso-8859-1 ” ),” UTF-8 ”);

 

 

 

 

 

推荐阅读