Servlet 之 Requests

1. HTTP 协议

  • 概念:Hyper Text Transfer Protocol 超文本传输协议,定义了,客户端和服务器端通信时,发送数据的格式

  • 特点:

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

    • 1.0 :每次请求响应都会重新建立连接(比较消耗资源)
    • 1.1:复用连接

1.1 请求

HTTP 请求消息数据格式分为:

  • 请求行
    • 格式:请求方式 请求 url 请求协议/版本,如:GET /login.html HTTP/1.1
    • 请求方式:GET、POST、PUT、DELETE、PATCH、HEAD ,常用的:GET/POST
      • GET:请求参数在 URL 后,长度有限制,不太安全
      • POST:请求参数在请求体中,长度无限制,相对安全
  • 请求头:可以标识浏览器一些信息给服务器,格式:请求头名称: 请求头值,常见请求头
    • User-Agent:告诉服务器浏览器的版本信息,可以在服务端获取,用于解决浏览器兼容性问题
    • Referer:标识请求从哪里来,主要用于 反盗链、统计请求来源
  • 请求空行:用于分隔请求体和请求头
  • 请求体(正文):封装 POST 请求消息的请求参数的,GET 请求没有请求体

请求消息数据格式:

// 字符串格式
POST /login.html	HTTP/1.1	// 请求行
// 请求头
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
    
// 请求体(post 请求有,get 无)
username=zhangsan	

2. Request

request对象和response对象的原理

  • requestresponse 对象是由服务器创建的,可以直接使用

  • request 对象是来获取请求消息,response对象是来设置响应消息

  • request 对象继承体系:ServletRequest --- HttpServletRequest --- org.apache.catalina.connector.RequestFacade 类(tomcat)

request 的功能:

  • 获取请求消息数据
  • 获取请求头数据
  • 获取请求体数据
  • 请求转发及数据共享等

2.1 获取请求消息数据

获取请求行数据:

GET /day14/demo1?name=zhangsan HTTP/1.1

  • 获取请求方式(GET):String getMethod()

  • 获取虚拟目录(/day14):String getContextPath()

  • 获取 Servlet 路径(/demo1):String getServletPath()

  • 获取 get 方式请求参数 (name=zhangsan):String getQueryString()

  • 获取请求 URI/day14/demo1):

    • 获取路径 String getRequestURI()/day14/demo1
    • 获取完整路径 StringBuffer getRequestURL()http://localhost/day14/demo1
  • 获取协议及版本(HTTP/1.1):String getProtocol()

  • 获取客户机的 IP 地址:String getRemoteAddr()


URL 和 URI 的区别

  • URL:统一资源定位符 : http://localhost/day14/demo1 相当于中华人民共和国
  • URI:统一资源标识符 : /day14/demo1,相当于共和国,比 URL 范围要广

2.2 获取请求头数据

请求头数据键值对形式的,通过以下方式可以获取:

  • 通过请求头的名称获取请求头的值:String getHeader(String name)
  • 取所有的请求头名称:Enumeration<String> getHeaderNames()

2.3 获取请求体数据

只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数

1、获取流对象

  • BufferedReader getReader():获取字符输入流,只能操作字符数据
  • ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据,可以处理图片、视频等

2、从流对象中获取具体数据

2.4 请求转发及数据共享

2.4.1 通用请求参数获取

不论是 get 还是 post 请求,都可以通过下列方法获取请求参数

  • String getParameter(String name):根据参数名称获取参数值,如:username=zs&password=123
  • String[] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=game
  • Enumeration<String> getParameterNames():获取所有请求的参数名称
  • Map<String,String[]> getParameterMap():获取所有参数的 map 集合

中文乱码问题

  • get 方式:tomcat 8已解决

  • post 方法:在获取参数前,设置 request 的编码 request.setCharacterEncoding("utf-8");

2.4.2 请求转发

请求转发是一种在服务器内部的资源跳转方式,其特点是:

  • 浏览器地址不会发生改变
  • 只能转发到当前服务器内部资源
  • 转发是一次请求
// 1. 通过request对象获取请求转发器对象
RequestDispatcher getRequestDispatcher(String path)
    
// 2. 使用RequestDispatcher对象来进行转发
forward(ServletRequest request, ServletResponse response) 

2.4.3 共享数据

域对象是一个有作用范围的对象,在其范围内可以共享数据,request 域代表一次请求的范围,一般用于请求转发的多个资源中共享数据;比如用户请求 /xxx/A,服务器内部将请求转发到 /xxx/B,那么可以在转发之前封装数据,然后在转发之后获取:

// 存储数据
void setAttribute(String name,Object obj)

// 通过键获取值
Object getAttitude(String name)

// 通过键移除键值对
void removeAttribute(String name)

3. 登录示例

3.1 项目结构

项目目录:

- LoginWeb
    - src
    	- com.jun
    		- dao
    			- UserDao.java	// 操作数据库中 User 表的类
    		- domain
    			- User.java		// 数据库实体类
    		- util
    			- JDBCUtils.java	// JDBC 工具类 使用 Druid 连接池
    		- web.servlet
    			- loginServlet.java
    			- SuccessServlet.java
    			- FailServel.java
    	- druid.properties	// 数据库连接配置
    - web
    	- WEB_INF
    		- lib   // 第三方包
    	- login.html

1、loginServlet.java

import com.jun.dao.UserDao;
import com.jun.domain.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("开始登录!");

        // 获取请求参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println(username);
        System.out.println(password);

        // 获取所有请求参数
        Map<String, String[]> map = req.getParameterMap();
        System.out.println(map);

        // 创建 User 对象
        User loginUser = new User();

       loginUser.setUsername(username);
       loginUser.setPassword(password);

        // 使用 BeanUtils 封装
        try {
            BeanUtils.populate(loginUser, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

//        调用 UserDao 的 login 方法
        UserDao dao = new UserDao();
        User user = dao.login(loginUser);

        // 判断 user
        if (user == null) {
            System.out.println("登录失败!");
        } else {
            System.out.println("登录成功!");
        }
    }

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

2、SuccessServlet.java

package com.jun.web.servlet;

import com.jun.dao.UserDao;
import com.jun.domain.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@WebServlet("/successServlet")
public class SuccessServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码
        resp.setContentType("text/html;charset=utf-8");

        //输出
        String username = (String) req.getAttribute("username");
        resp.getWriter().write("登录成功!欢迎回来:" + username);

    }

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

3、FailServlet.java

import com.jun.dao.UserDao;
import com.jun.domain.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@WebServlet("/failServlet")
public class FailServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码
        resp.setContentType("text/html;charset=utf-8");

        //输出
        resp.getWriter().write("登录失败,用户名或密码错误");
    }

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

3.2 用户类

用户实体类 domain/User.java

package com.jun.domain;

/**
 * 用户实体类
 */
public class User {
    private int id;
    private String username;
    private String password;
    private String gender;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }


    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username=" + username + '\'' +
                ", password=" + password +'\'' +
                ", gender=" + password +'\'' +
                '}';

    }
}

3.3 操作用户

dao/UserDao.java

package com.jun.dao;

import com.jun.domain.User;
import com.jun.util.JDBCUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.dao.DataAccessException;

/**
 * 操作数据库中 User 表的类
 */
public class UserDao {
    // 声明 JDBCTemplate 对象共用
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    /**
     * 登录方法
     * @param loginUser 只有用户名和密码
     * @return user:包含用户全部数据,没有查询到,返回 null
     */
    public User login(User loginUser) {
        try {
            // 查询 sql
            String sql = "select * from user where username = ? and password = ?";
            System.out.println("UserDao: " + loginUser.getUsername() + " password: " + loginUser.getPassword());

            // query 查询
            User user = template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class),
                    loginUser.getUsername(), loginUser.getPassword()
                    );
            return user;

        } catch (DataAccessException e) {
            e.printStackTrace();
            return null;
        }
    }
}

3.4 JDBC 数据连接

这里采用 JDBC 工具类 + Druid 连接池来连接 MySQL 数据库:

package com.jun.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import java.io.InputStream;

/**
 * JDBC 工具类 使用 Druid 连接池
 */
public class JDBCUtils {
    private static DataSource ds;

    static {
        try {
            // 1. 加载配置文件
            Properties properties = new Properties();

            // 使用 ClassLoader 加载配置文件,获取字节输入流
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            properties.load(is);

            // 2. 初始化连接池对象
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接池对象
     */
    public static DataSource getDataSource() {
        return ds;
    }

    /**
     * 获取连接 Connection 对象
     */

    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
}

3.5 druid 数据库配置

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///java_test    // java_test 为数据库名称
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000

第三方 jar 包:

  • commons-beanutils-1.8.0.jar
  • commons-logging-1.2.jar
  • druid-1.0.9.jar
  • mchange-commons-java-0.2.12.jar
  • mysql-connector-java-5.1.37-bin.jar
  • spring-beans-5.0.0.RELEASE.jar
  • spring-core-5.0.0.RELEASE.jar
  • spring-jdbc-5.0.0.RELEASE.jar
  • spring-tx-5.0.0.RELEASE.jar

3.6 BeanUtils 工具类

BeanUtils 工具类用于简化 JavaBean 的封装,也就是简化数据的封装

JavaBean 其实就是一个标准的 java 类,功能就是封装数据(在这里就是 User 类),但是必须满足如下条件:

  • 类必须被 public 修饰
  • 必须提供空参的构造器
  • 成员变量必须使用 private 修饰
  • 提供公共 settergetter 方法

BeanUtils 常用方法:

  • setProperty()
  • getProperty()
  • populate(Object obj, Map map):将 map 集合的键值对信息封装到对应的 JavaBean 对象中

示例:

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("开始登录!");

        // 获取所有请求参数  map 形式
        Map<String, String[]> map = req.getParameterMap();
        System.out.println(map);

        // 创建 User 对象
        User loginUser = new User();

       loginUser.setUsername(username);
       loginUser.setPassword(password);

        // 使用 BeanUtils 将获取到的所以参数封装到 JavaBean 中
        try {
            BeanUtils.populate(loginUser, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

//        调用 UserDao 的 login 方法
        UserDao dao = new UserDao();
        User user = dao.login(loginUser);

        // 判断 user
        if (user == null) {
            System.out.println("登录失败!");
        } else {
            System.out.println("登录成功!");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风老魔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值