zoukankan      html  css  js  c++  java
  • http的request和response

    HTTP

    超文本传输协议:定义客户端和服务器之间传输数据的格式

    特点:

    • 基于TCP/IP的高级协议
    • 默认端口号:80
    • 基于请求/响应模型:一次请求对应一次响应
    • 无状态的:每次请求之间相互独立

    历史版本:

    • 1.0:每次请求响应都会建立新的连接(一个网页需要多个请求)
    • 1.1:复用连接

    传输过程:

    1. tomcat根据请求url中的资源路径,根据配置文件找到Servlet实现类,并创建对象;
    2. tomcat创建request和response对象,requeset对象中封装请求消息;
    3. tomcat调用service方法
    4. 程序员在service中,根据请求消息,设置相应数据
    5. tomcat将response返给浏览器

    Request

    请求消息数据格式:

    1. 请求行 请求方式 请求url 请求协议/版本

      如:GET /day04/demo1?name=zhangsan HTTP/1.1

    2. 请求头 请求头名称:请求头值 (多个请求头)

      • User-Agent:浏览器版本等信息
      • Referer:请求来自哪个网站
    3. 请求空行:就是一个空行

    4. 请求体

      • GET没有,POST有

    request类

    ServletRequest 接口

    HttpServletrequest 接口,继承上面的接口

    org.apache.catalina.connector.RequestFacade 类,由Tomcat实现,继承上面接口

    所以,Tomcat实现request类

    request对象

    常用方法

    1. 获取请求行数据(几个常用的)
      • 获取虚拟目录:String getContextPath()
      • 获取URI:String getRequestURI()/day04/demo
      • 获取URL:StringBuffer getRequestURL()http://localhost/day04/demo
    2. 获取请求头数据
      • String getHeader(String name) 根据请求头名称获得值
    3. 获取请求体数据 (POST请求方式)
      • 获取流对象:字符流 getReader() 字节流getInputStream()
      • 从流对象中拿数据

    其他方法

    • 获取请求参数通用方法 (GET和POST都可以)

      • String getParameter(String name) 更根据参数名称获取参数值
      • String[] getParameterValues(String name) 更根据参数名称获取参数组
      • getParameterNames() 获取所有请求的参数名称
      • Map<String String[]> getParameterNames() 获取所有请求的参数map集合
      • POST会遇到中文乱码,需要先设置req.setCharacterEncoding("utf-8")
    • 请求转发:服务器内部的资源跳转方式(如Demo1转到Demo2)req.getRequestDispatcher("/demo2").forward(req, resp);

      特点:浏览器地址栏没有发生变化;只能转发到当前服务器内部资源。

    • 共享数据

      • 域对象:一个有作用范围的对象,可以在范围内共享数据
      • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
        1. setAttribute(String name, Object obj) 存储数据
        2. Object getAttrbute(String name) 通过键获取值
        3. removeAttribute(String name) 通过键移除键值对
    • 获取ServletContext

      • ServletContext getServletContext() 后面再讲

    案例

    用户登录的业务逻辑:

    1. 创建项目,导入login.html
    2. 创建数据库中的user表
    3. 创建User类
    4. 创建JDBCUtils工具类(获取连接池,获取链接对象)
    5. 创建UserDao类,实现login方法(使用JDBCTemplate执行sql查询)
    6. 创建loginServlet类:
      • 获取请求参数 (username, password)
      • 封装成User对象
      • 调用UserDao的login方法 (传入User对象,执行sql语句,判断)
      • 判断是否登录成功

    BeanUtils工具类:简化 请求参数 的封装

    1. 导入jar包commons-beanutils-1.8.0.jar
    2. User类必须符合JavaBean标准(JavaBean是定义一个Java类的标准的要求,可百度搜索)

    BeanUtils代码:(Servlet中)

    // 设置请求数据编码
    req.setCharacterEncoding("UTF-8");
    // 获取提交数据
    Map<String, String[]> map = req.getParameterMap();
    // 创建对象
    User loginUser = new User();
    // 封装对象
    BeanUtils.populate(loginUser, map);  // try-catch捕获
    // 登录判断
    UserDao dao = new UserDao();
    User user = dao.login(loginUser);
    if (user == null) {
    	System.out.println("登录失败");
    } else {
    	System.out.println("登录成功");
    }
    

    案例代码

    文件目录结构:

    --项目/模块
    	--src/包
    		druid-properties // 连接池配置文件
    		domain/User
    		dao/UserDao
    		util/JDBCUtils
    		servlet/ServletDemo
    	--web
    		--WEB-INF
    			lib // jar包,需要右键add as libaray
    		xxx.html
    		xx.jsp
    

    login.html

    <form action="./demo" method="post">
        username: <input type="text" name="username"> <br>
        password: <input type="password" name="password"> <br>
        <input type="submit" value="submit">
    </form>
    

    User略 (JavaBean标准类)

    JDBCUtils略 (参考JDBC中的Druid连接池,一模一样)

    UserDao类:

    public class UserDao {
        // 声明JDBCTemplate对象共用
        private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    
        public User login(User loginUser) {
            try {
                String sql = "select * from user where username=? and password=?";
                User user = template.queryForObject(sql,
                        new BeanPropertyRowMapper<User>(User.class),
                        loginUser.getUsername(), loginUser.getPassword());
                return user;
            } catch (DataAccessException e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    

    Servlet类,参考上面BeanUtils

    Response

    响应消息格式:

    1. 响应行:协议/版本 响应状态码 状态码描述HTTP/1.1 200 OK
      • 响应状态码:都是3位数,分为5类
        • 1xx 服务器收到消息,但没有接受完成
        • 2xx 成功200
        • 3xx 重定向 (302重定向 304访问缓存)
        • 4xx 客户端错误 (404请求路径错误 405请求方法没有对应的doXx方法)
        • 5xx 服务器错误 (500服务内异常)
    2. 响应头 头名称:值
      • Content-type:响应数据格式(html),以及编码格式
      • Content-disposition:以什么格式打开响应数据(当前页面内打开、附件下载等)
    3. 响应空行:空行
    4. 响应体:HTML代码/图片的编码

    response对象

    常用方法

    1. 设置响应行:setStatus(int sc)
    2. 设置响应头:setHeader(String name, String value)
    3. 设置响应体:
      • 获取输出流:字符输出流getWriter()、字节输出流getOutputStream()
      • 使用输出流,将数据输出到客户端

    其他方法

    1. 重定向:resp.sendRedirect("/day04/ServletDemo2")

      • 重定向特点:地址栏发生变化,属于两次请求,可以访问其他站点资源,不能共享数据
      • 转发特点:地址栏不变,是一次请求,只能访问当前站点资源,能共享数据
      • 可以获取虚拟目录:String req.getContextPath()
    2. 告诉浏览器编码方式 resp.setContentType("text/html;charset=utf-8");

    3. 字符流

      resp.setContentType("text/html;charset=utf-8");
      PrintWriter pw = resp.getWriter();
      pw.write("你好 hello");
      
    4. 字节流

      resp.setContentType("text/html;charset=utf-8");
      ServletOutputStream os = resp.getOutputStream();
      os.write("你好".getBytes("utf-8"));
      

    ServletContext

    概念:代表整个web应用,可以和程序的服务器交互

    获取ServletContext对象:

    1. req.getServletContext();
    2. this.getServletContext(); (建议使用)

    功能:

    1. 获取MIME类型

      • MIME类型:互联网通信定义的一种文件数据类型

      • MIME格式:大类型/小类型, 如 text/html

      •   ServletContext context1 = req.getServletContext();
          String filename = "a.jpg";
          System.out.println(context1.getMimeType(filename)); // 输出image/jpeg
        
    2. 域对象:共享数据:所有用户,所有数据

      • setAttribute(String, Object);
      • getAttribute(String);
      • removeAttribute(String)
    3. 获取文件在服务器中的路径

      ServletContext c = this.getServletContext();
      String path = c.getRealPath("/b.txt");  // web目录下的资源路径
      String path2 = c.getContextPath("/WEB-INF/classes/a.txt"); // src目录下的资源路径
      

    下载功能

    现在浏览器比较高级,一些文件可以自动转到下载功能。

    对于任何文件,如何实现下载功能(让浏览器下载):

    • 使用响应头设置资源的打开方式:content-disposition:attachment;filename=xxx(以附件形式打开)

    实现:

    1. 超链接指向servlet (传递文件名);
    2. servlet获取文件名;加载文件进内存;指定response响应头;将文件写到response输出流中。

    代码:

    1. html页面:

      • 图片放在web/img/687.png,必须有img文件夹
      • servlet是虚拟目录,demo是servlet资源路径
       <a href="/servlet/demo?filename=1.png">图片下载</a>
      
    2. servlet编程:

      // 获取参数
      String filename = req.getParameter("filename");
      // 找到资源路径
      ServletContext c = this.getServletContext();
      String realPath = c.getRealPath("/img/" + filename);
      // 设置响应头(文件类型)
      String mimeType = c.getMimeType(filename);
      resp.setHeader("content-type", mimeType);
      // 设置响应头(浏览器打开方式)
      resp.setHeader("content-disposition", "attachment;filename="+filename);
      // 字节流加载
      FileInputStream is = new FileInputStream(realPath);
      // 数据输出
      ServletOutputStream os = resp.getOutputStream();
      byte[] buff = new byte[2014 * 8];
      int len = 0;
      while ((len = is.read(buff)) != -1) {
          os.write(buff, 0, len);
      }
      is.close();
      

    中文乱码

    刚才下载的文件,如果是中文,不同浏览器显示不一样的编码。

    解决思路:

    1. 获取客户端使用的浏览器版本信息
    2. 根据不同的版本,设置不同的编码方式

    代码:

    1. 将DownLoadUtils.java文件(工具类)放在utils工具包
    2. servlet中编码
      String agent = req.getHeader("user-agent");
      filename = DownLoadUtils.getFileName(agent, filename);
  • 相关阅读:
    Abp 领域事件简单实践 <一>
    Abp session和Cookie
    Abp 聚合测试
    反向代理
    Angular 变更检测
    VS 之github
    Docker 启动SQLServer
    查出第二大的数是多少
    DDD 理解
    ActionBar的简单应用
  • 原文地址:https://www.cnblogs.com/mingriyingying/p/13477284.html
Copyright © 2011-2022 走看看