requset请求处理与BeanUtils封装
HTTP:
- 概念:Hyper Text Transfer Protocol 超文本传输协议
- 传输协议:定义了,客户端和服务器端通信时,发送数据的格式
- 特点:
- 基于TCP/IP的高级协议
- 默认端口号:80
- 基于请求/响应模型的:一次请求对应一次响应
- 无状态的:每次请求之间相互独立,不能交互数据
- 历史版本:
- 1.0:每一次请求响应都会建立新的连接
- 1.1:复用连接
- 请求消息数据格式
-
请求行
请求方式 请求url 请求协议/版本
GET /login.html HTTP/1.1- 请求方式:
- HTTP协议有7中请求方式,常用的有2种
- GET:
- 请求参数在请求行中,在url后。
- 请求的url长度有限制的
- 不太安全
- POST:
- 请求参数在请求体中
- 请求的url长度没有限制的
- 相对安全
- GET:
- HTTP协议有7中请求方式,常用的有2种
- 请求方式:
-
请求头:客户端浏览器告诉服务器一些信息
请求头名称: 请求头值
* 常见的请求头:
1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
* 可以在服务器端获取该头的信息,解决浏览器的兼容性问题2. Referer:http://localhost/login.html * 告诉服务器,我(当前请求)从哪里来? * 作用: 1. 防盗链: 2. 统计工作:
-
请求空行
空行,就是用于分割POST请求的请求头,和请求体的。 -
请求体(正文):
- 封装POST请求消息的请求参数的
- 字符串格式:
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 username=zhangsan
-
Request:
-
request对象和response对象的原理
- request和response对象是由服务器创建的。我们来使用它们
- request对象是来获取请求消息,response对象是来设置响应消息
-
request对象继承体系结构:
ServletRequest -- 接口
| 继承
HttpServletRequest -- 接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat) -
request功能:
-
获取请求消息数据
-
获取请求行数据
- 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
- URL:统一资源定位符 : http://localhost/day14/demo1
- URI:统一资源标识符 : /day14/demo1
- 获取协议及版本:HTTP/1.1
- String getProtocol()
- 获取客户机的IP地址:
- String getRemoteAddr()
- 获取请求方式 :GET
-
获取请求头数据
- 方法:
- String getHeader(String name):通过请求头的名称获取请求头的值
- Enumeration尖括号String> getHeaderNames():获取所有的请求头名称
- 方法:
-
获取请求体数据:
- 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
- 步骤:
- 获取流对象
- BufferedReader getReader():获取字符输入流,只能操作字符数据
- ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
- 再从流对象中拿数据
- 获取流对象
- 代码示例
package cn.servletDemo.web.request; 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.BufferedReader; import java.io.IOException; import java.util.Enumeration; @WebServlet("/RequestDemo02") public class ServletRequest extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String methopd = req.getMethod(); String contextPath = req.getContextPath(); String servletPath = req.getServletPath(); String requestURI = req.getRequestURI(); StringBuffer RequsetURL = req.getRequestURL(); String requestProtocol = req.getProtocol(); String IP = req.getRemoteAddr(); Enumeration<String> headerNames = req.getHeaderNames(); System.out.printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n", methopd,contextPath,servletPath,requestURI, RequsetURL,requestProtocol,IP); while(headerNames.hasMoreElements()){ String name = headerNames.nextElement(); String value = req.getHeader(name); System.out.printf("%s\t:%s\n",name,value); } } /***结果 GET /req /RequestDemo02 /req/RequestDemo02 http://localhost:8080/req/RequestDemo02 HTTP/1.1 0:0:0:0:0:0:0:1 host :localhost:8080 connection :keep-alive upgrade-insecure-requests :1 user-agent :Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36 sec-fetch-user :?1 accept :text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,; q=0.8,application/signed-exchange;v=b3;q=0.9 sec-fetch-site :none sec-fetch-mode :navigate accept-encoding :gzip, deflate, br accept-language :zh-CN,zh;q=0.9 cookie :JSESSIONID=4973752F177A01DFD0BC110AB93AEA40; Idea-fe3516c6=e1f7407c-f751-4f0d-99cf-6bbfd9ff1826; goSessionid=wqXEMF4WFNSPwE3L9lcUSMXcLjCnLUgizfec2DipoDI%3D; SL_G_WPT_TO=zh-CN; SL_GWPT_Show_Hide_tmp=undefined; SL_wptGlobTipTmp=undefined; JSESSIONID=7DB8D0F83015408AC113950CB3E0A18B ***/ @Override protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException { //获取请求消息体 //获取字符流 BufferedReader br = req.getReader(); //读数据 String line = null; while((line = br.readLine()) != null){ System.out.println(line); } //结果username=315019748%40qq.com&password=%E9%98%BF%E6%96%AF%E8%BE%BE } }
- html代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>注册页面</title> </head> <body> <form action="/req/RequestDemo02" method="post"> <input type="text" placeholder="请输入用户名" name="username"><br> <input type="text" placeholder="请输入密码" name="password"><br> <input type="submit" value="注册"> </form> </body> </html>
- 结果
-
-
其他功能:
- 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
- String get(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 已经将get方式乱码问题解决了
- post方式:会乱码
- 解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");
- 代码示例
@WebServlet("/RequestDemo03") public class ServletRequest01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //get获取请求参数 //根据请求参数名称获取请求参数值 String username = req.getParameter("username"); System.out.println("get:"+username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //post请求参数 req.setCharacterEncoding("utf-8"); //根据请求参数名称获取请求参数值 String username = req.getParameter("username"); System.out.println("post:"+username); } }
-
请求转发:一种在服务器内部的资源跳转方式
- 步骤:
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
- 特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中,不能访问外部资源。
- 转发实质是同一次请求
- 步骤:
-
共享数据:
- 域对象:一个有作用范围的对象,可以在范围内共享数据
- request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
- 方法:
- void setAttribute(String name,Object obj):存储数据
- Object getAttitude(String name):通过键获取值
- void removeAttribute(String name):通过键移除键值对
-
获取ServletContext:
- ServletContext getServletContext()
- 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
-
案例:用户登录
-
用户登录案例需求:
1.编写login.html登录页面
username & password 两个输入框
2.使用Druid数据库连接池技术,操作mysql,day14数据库中user表
3.使用JdbcTemplate技术封装JDBC
4.登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您 -
开发步骤
- 创建项目,导入html页面,配置文件,jar包
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录</title> </head> <body> <form action="/test/LoginServlet" method="post"> 用户名:<input type="text" name="username"><br> 密码:<input type="text" name="password"><br> <input type="submit" value="登录"> </form> </body> </html>
- 创建数据库环境
CREATE DATABASE day14; USE day14; CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32) UNIQUE NOT NULL, PASSWORD VARCHAR(32) NOT NULL );
- 创建包package cn.test.domain;,创建类User
package cn.test.domain; /* 用户的实体类 */ public class User { private int id; private String username; private String password; 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; } }
- 创建包cn.test.util,编写工具类JDBCUtils,加载配置文件
package cn.test.util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; /* JDBC工具类,使用的是Druid连接池 */ public class JDBCUtils { private static DataSource dataSource; /* 静态代码块加载配置文件,初始化连接池 */ static { try { //1.加载配置文件 Properties pro = new Properties(); //使用ClassLoader加载配置文件,获取字节输入流 InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(inputStream); //2.初始化连接池对象 dataSource = DruidDataSourceFactory.createDataSource(pro); } catch (Exception e) { e.printStackTrace(); } } /* 获取连接池对象 */ public static DataSource getDataSource(){ return dataSource; } /* 获取Connection对象 */ public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }
- 创建包cn.test.dao,创建类UserDao,提供login方法
package cn.test.dao; import cn.testT.domain.User; import cn.testT.util.JDBCUtils; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; /* 操作数据库User表 */ public class UserDao { //声明JDBCTemplate对象,实现共用 private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource()); //登录逻辑的完成 public User login(User loginUser){ try { //1.编写sql String sql = "select * from user where username = ? and password = ?"; //2.调用querry方法 User user = template.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class), loginUser.getUsername(),loginUser.getPassword()); return user; } catch (DataAccessException e) { e.printStackTrace(); //一般在此处处理日志 return null; } } }
- 编写cn.test.web.servlet.LoginServlet类
package cn.testT.web.servlet; import cn.testT.dao.UserDao; import cn.testT.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; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //设置编码 req.setCharacterEncoding("utf-8"); //获取请求参数 String username = req.getParameter("username"); String password = req.getParameter("password"); //封装user对象 User loginUser = new User(); loginUser.setUsername(username); loginUser.setPassword(password); //调用UserDao的login方法 UserDao dao = new UserDao(); User user = dao.login(loginUser); //判断user if (user == null) { //登录失败,内部转发 req.getRequestDispatcher("/FailServlet").forward(req, resp); } else { //登录成功 //存储数据 req.setAttribute("user",user); //转发 req.getRequestDispatcher("/SuccessServlet").forward(req,resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
- 编写FailServlet和SuccessServlet类
package cn.testT.web.servlet; 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; @WebServlet("/FailServlet") public class FailServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //给页面写一句话 //设置页面的编码 response.setContentType("text/html;charset=utf-8"); //输出 response.getWriter().write("输入错误,登录失败"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } ------------------------------------------------------------------------------------------------------------------ package cn.testT.web.servlet; import cn.testT.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; @WebServlet("/SuccessServlet") public class SuccessServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取request域中共享的user对象 User user = (User) request.getAttribute("user"); //给页面写一句话 //设置页面的编码 response.setContentType("text/html;charset=utf-8"); //输出 response.getWriter().write("登录成功"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
-
login.html中form表单的action路径的写法
- 虚拟目录/Servlet的资源路径
-
BeanUtils工具类,简化数据封装
- 用于封装JavaBean的
package cn.testT.web.servlet; import cn.testT.dao.UserDao; import cn.testT.domain.User; import org.apache.commons.beanutils.BeanUtils; 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; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //设置编码 req.setCharacterEncoding("utf-8"); // //获取请求参数 // String username = req.getParameter("username"); // String password = req.getParameter("password"); // //封装user对象 // User loginUser = new User(); // loginUser.setUsername(username); // loginUser.setPassword(password); //获取所有请求参数 Map<String, String[]> parameterMap = req.getParameterMap(); //创建user对象 User loginUser = new User; //使用BeanUtils封装 try { BeanUtils.populate(loginUser,parameterMap); } 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) { //登录失败,内部转发 req.getRequestDispatcher("/FailServlet").forward(req, resp); } else { //登录成功 //存储数据 req.setAttribute("user",user); //转发 req.getRequestDispatcher("/SuccessServlet").forward(req,resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
- JavaBean:标准的Java类(上述User类,一般再domain目录下)
- 要求:
- 类必须被public修饰
- 必须提供空参的构造器
- 成员变量必须使用private修饰
- 提供公共setter和getter方法
- 功能:封装数据
- 要求:
- 方法:
- setProperty()与getProperty()
- populate(Object obj , Map map):将map集合的键值对信息,封装到对应的JavaBean对象中
- 注意:以上操作的是属性:setter和getter方法截取后的产物,例如:getUsername() --> Username--> username,不是JavaBean的成员变量
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步