第一章 HTTP
1.1 概述
HTTP(Hyper Text Transfer Protocol): 超文本传输协议
-
传输协议 : 定义了客户端和服务器通信时,发送数据的格式
-
特点:
- 基于 TCP/IP 的高级协议
- 默认端口号: 80
- 基于请求/响应模型的(一次请求,对应一次响应)
- 无状态的协议: 每次请求之间相互独立
-
历史版本
- 1.0: 每一次请求都会建立一个新的连接
- 1.1: 会复用前面的连接
1.2 HTTP请求消息数据格式
- **请求行 **: 说明请求的参数,请求的url,请求的协议
- 格式:
请求方式 请求url 请求版本/协议
- 例子
GET /JavaWeb_war_exploded/hello-servlet HTTP/1.1
- 请求方式不同, 参数的位置也会不同
GET
方式: 请求参数在请求行中, 在url之后 (可能会不安全,因为参数暴露在url后面) ,例如:localhost:8080/JavaWeb_war_exploded/haha?username = xxx
POST
方式, 请求的参数在方法体中- GET请求的url长度有限制 ,POST没有限制
- 格式:
- 请求头 : 请求行下面紧接着就是请求头,客户端的服务器告诉服务器的一些信息
- 格式:
请求头名称: 请求头值
有多个 - 代码有很多,下面有例子
- 常见的请求头里面的参数
User-Agent
: 浏览器告诉服务器我的浏览器及其版本信息,解决兼容性问题,同时也可以用来进行爬虫的伪装Accept
: 告诉服务器我可以响应和解析什么样的数据格式 (我是浏览器)Accept-Language
: 我这个浏览器支持什么语言Accept-Encoding
: 浏览器可以接受的压缩格式Referer
:告诉服务器 , 我(当前请求)从哪里来- 作用
- 防盗链: 判断referer是不是来自我想要他来自的网页
- 统计工作: 统计不同referer出现的次数
- 作用
Connection
: 连接是否可以被复用 ,现在一般都是Keep-alive
- 格式:
- 请求空行 : 就是一个空行,作用是 分割请求头和请求体
- 请求体: 封装POST请求消息的请求参数的
- get方式没有请求体,POST有
- 格式 :
上传的数据的名字 = xxx
- 例子:
username=213214
(我是通过表单提交,跳转到这个页面之后才有的这个数据)
HTML代码
<form action="/JavaWeb_war_exploded/haha" method="post">
<input type="text" name="username">
<input type="submit" value="提交">
</form>
跳转到页面之后我输入了213214然后提交 ,跳转页面之后,页面的请求消息的数据格式如下
POST /JavaWeb_war_exploded/haha HTTP/1.1 //1 这个是请求行
Host: localhost:8080 //2 下面都是请求头
Connection: keep-alive
Content-Length: 15
Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Microsoft Edge";v="90"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.56
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/JavaWeb_war_exploded/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh-TW;q=0.9,zh;q=0.8,en;q=0.7,en-GB;q=0.6,en-US;q=0.5
Cookie: JSESSIONID=1A4D131E4EDDA8E07B9B8561358319BF; Idea-874da8ff=e5d280ff-d15e-4ffc-9d9a-7deff96ccca0; Idea-874dacbf=2a6e965e-f65a-49e9-8b63-726ad404dc88
//3 这一行是请求空行
username=213214 //4 这个就是请求体
第二章 Request
2.1 Request和Response的原理
resquest对象和response对象的原理
- 这两个对象都是由服务器创建的,我们来使用它
- request对象就是用来获取请求消息,response用来设置响应消息
Tomcat对请求的处理原理
- tomcat服务器会根据请求url中的资源路径,创建对应的Servlet实现类的对象。
- tomcat服务器,会创建resquest和response对象,resquest中封装了请求消息数据
- tomcat将这两个对象传进service方法中,并调用service方法(关键步骤),里面怎么处理,响应什么,由我们程序员决定(定义service方法中的具体实现)
- 服务器在给浏览器做响应之前,会从response对象中拿到程序员设置的响应消息数据。
下面给出图解
2.2 Request对象继承体系结构
- ServletRequest 接口
- HttpServletRequest 接口
- Tomcat的实现类:
org.apache.catalina.connector.RequestFacade
- Tomcat的实现类:
- HttpServletRequest 接口
2.3 Request获取请求行数据
请求行数据的格式示例
POST /JavaWeb_war_exploded/haha HTTP/1.1
下面的方法都是基于接口HttpServletRequest
方法介绍
-
获取请求方式
-
String getMethod() Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT.
-
-
(*) 获取虚拟目录
-
String getContextPath() Returns the portion of the request URI that indicates the context of the request.
-
对于上面那个例子,返回的就是
/JavaWeb_war_exploded
-
-
获取Servlet实现类的urlpattern路径
-
String getServletPath() Returns the part of this request's URL that calls the servlet.
-
对于上面的例子,返回的就是
/haha
-
-
获取GET方式的请求参数
-
String getQueryString() Returns the query string that is contained in the request URL after the path.
-
对于上面的例子,返回的就是
null
-
-
(*) 获取请求的URI(统一资源标识符)
-
String getRequestURI() Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request.
-
对于上面的例子,返回的就是
/JavaWeb_war_exploded/haha
-
-
获取请求的URL(统一资源定位符)
-
StringBuffer getRequestURL() Reconstructs the URL the client used to make the request.
-
上面的例子,返回的就是
http://localhost/JavaWeb_war_exploded/haha
-
注意: 它返回的是StringBuffer类
-
-
获取浏览器的协议以及版本: (这个方法在
ServletRequest
接口里面)-
String getProtocol() Returns the name and version of the protocol the request uses in the form protocol/majorVersion.minorVersion, for example, HTTP/1.1.
-
对于上面的例子,返回的就是
HTTP/1.1
-
-
获取客户机的IP地址
-
String getRemoteAddr() Returns the Internet Protocol (IP) address of the client or last proxy that sent the request.
-
对于上面的例子,返回的就是
0:0:0:0:0:0:0:1
-
代码实现
@WebServlet("/haha")
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(req.getMethod());
System.out.println(req.getContextPath());
System.out.println(req.getServletPath());
System.out.println(req.getQueryString());
System.out.println(req.getRequestURL());
System.out.println(req.getRequestURI());
System.out.println(req.getProtocol());
System.out.println(req.getRemoteAddr());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
//输出结果
//GET
///JavaWeb_war_exploded
///haha
//null
//http://localhost/JavaWeb_war_exploded/haha
///JavaWeb_war_exploded/haha
//HTTP/1.1
//0:0:0:0:0:0:0:1
2.4 Request获取请求头数据
方法介绍
- 通过参数的名称获取对应的请求头的参数的值 (常用)
-
String getHeader(String name) Returns the value of the specified request header as a String. Enumeration<String> getHeaders(String name) Returns all the values of the specified request header as an Enumeration of String objects.
注意: 这里的name参数是不区分大小写的
-
获取请求头中所有的参数的名字
-
Enumeration<String> getHeaderNames() Returns an enumeration of all the header names this request contains.
-
枚举的用法和Iterator十分像,稍微介绍一下
boolean hasMoreElements()
Tests if this enumeration contains more elements.
E nextElement()
Returns the next element of this enumeration if this enumeration object has at least one more element to provide.
代码实现
@WebServlet("/haha")
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Enumeration<String> request = req.getHeaderNames();
while(request.hasMoreElements()){
String s = request.nextElement();
System.out.println(s + " : " + req.getHeader(s));
}
}=
}
//运行结果
//host : localhost
//connection : keep-alive
//cache-control : max-age=0
//sec-ch-ua : " Not A;Brand";v="99", "Chromium";v="90", "Microsoft Edge";v="90"
//sec-ch-ua-mobile : ?0
//upgrade-insecure-requests : 1
//user-agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.56
//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
//sec-fetch-user : ?1
//sec-fetch-dest : document
//accept-encoding : gzip, deflate, br
//accept-language : zh-CN,zh-TW;q=0.9,zh;q=0.8,en;q=0.7,en-GB;q=0.6,en-US;q=0.5
//cookie : JSESSIONID=548F53F7E4C684314F1315B2348D4A27; Idea-874da8ff=e5d280ff-d15e-4ffc-9d9a-7deff96ccca0; Idea-874dacbf=2a6e965e-f65a-49e9-8b63-726ad404dc88
//注意,这里无关的一些代码我都删掉了
注意: 如果我是直接通过浏览器输入地址进去的网站,那么 referer就是null
2.5 Request获取请求体数据
注意: 要想有请求体,那么请求方式必须是POST
步骤:
-
获取流对象 ( 若用户输入的账号密码等,那么就使用字符流 ) (若用户是上传图片等,那么我们就使用字节流 )
-
获取字符输入流,只能操作字符数据(但是它方便)
-
BufferedReader getReader() Retrieves(检索) the body of the request as character data using a BufferedReader.
-
-
获取字节输入流,可以操作所有类型的数据
-
ServletInputStream getInputStream() Retrieves the body of the request as binary data using a ServletInputStream.
-
-
-
再从流对象中拿取数据 (以前的知识,懂得都懂)
代码实现
这里实现一个字符流的
@WebServlet("/haha")
public class ServletDemo3 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//将请求参数的字符流放入br里面
BufferedReader br = req.getReader();
//读取数据
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}
}
2.6 其他功能
下面的方法都很常用
2.6.1 获取请求参数通用方式(Get和Post的请求方式参数都能获取)
String getParameter(String name)
: 根据参数名称获取参数值,不存在就返回nullString[] getParameterValues(String name)
: 根据参数名称获取参数值的数组 (多用于复选框)Enumeration getParameterNames()
: 获取所有请求的参数名称Map<String, String[]> getParameterMap()
: 获取所有参数的键值对的集合
方法演示
@WebServlet("/haha")
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求参数
//方法1
System.out.println(req.getParameter("username"));
//方法2
System.out.println(Arrays.toString(req.getParameterValues("hobby")));
//方法3
Map<String, String[]> parameterMap = req.getParameterMap();
Set<String> strings = parameterMap.keySet();
for (String name : strings) {
System.out.print(name + ":");
//根据name来获取值
String[] values = parameterMap.get(name);
System.out.println(Arrays.toString(values));
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
//我们会发现无论是post还是get都是会返回我们想要的请求参数的值
中文乱码问题
tomcat8以下会出现这个乱码问题(无论是get还是post都会)
解决方法: 在获取参数前,设置编码(设置的编码和网页的编码保持一致,一般是utf-8)
void setCharacterEncoding(String env)
Overrides the name of the character encoding used in the body of this request.
例如: setCharacterEncoding("utf-8")
2.6.2 请求转发
请求转发: 一种在服务器内部资源跳转的方式
实现步骤
-
通过
request
对象获取请求转发器对象:-
RequestDispatcher getRequestDispatcher(String path) Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path.
-
-
使用
RequestDispatcher
进行转发(下面这个方法就是属于RequestDispatcher接口的)-
void forward(ServletRequest request, ServletResponse response) Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server.
-
特点
- 浏览器的地址栏没有发生变化
- 资源只能转发到内部服务器里的其他servlet
- 通过抓包,我们知道: 转发是一次请求,即我们访问原来的网页之后就没有其他任何请求了
代码实现
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo5被访问了");
//我现在要转发资源
req.getRequestDispatcher("/demo6").forward(req,resp);
}
2.6.3 共享数据(域对象)
域对象: 一个有作用范围的对象,可以在范围之内共享数据
request域: 代表一次请求的范围 , 一般用于请求转发的多个资源中共享数据
相关方法
来自ServletRequest
接口
-
在这次请求中存储数据
-
void setAttribute(String name, Object o) Stores an attribute in this request.
-
-
得到数据,没有返回null
-
Object getAttribute(String name) Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
-
-
删除request域中的数据(通过键来删除)
-
void removeAttribute(String name) Removes an attribute from this request.
-
代码实现
//这是demo5
@WebServlet("/demo5")
public class ServletDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo5被访问了");
//存储资源
req.setAttribute("name","YourFather");
//我现在要转发资源
req.getRequestDispatcher("/demo6").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
//这是demo6
@WebServlet("/demo6")
public class ServletDemo6 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo6被访问了");
System.out.println(req.getAttribute("name"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
//我们只访问了http://localhost/JavaWeb_war_exploded/demo5
//打印台输出
//demo5被访问了
//demo6被访问了
//YourFather
2.6.4 获取ServletContext(这里了解即可,后面会详细讲)
相关方法
ServletContext getServletContext()
Gets the servlet context to which this ServletRequest was last dispatched.
第三章 Request 综合案例
3.1 需求介绍
- 编写login.html登录页面 (username和password)
- 使用Druid数据库连接池技术, 操作mysql中我们创建的user表
- 使用jdbcTemplate技术封装JDBC
- 登陆成功跳转到
SuccessServlet
展示: 登陆成功! [用户名],欢迎您~ - 登录失败跳转到
FailServlet
展示: 登陆失败,用户名或者密码有错误
3.2 需求分析
3.3 代码实现
-
首先创建一个mavenweb项目
-
然后我们要实现准备好
一个登录的html
,druid的配置文件(放在/main和/test的resources文件夹里面)
,JDBCUtils
,还有你的面对bug的斗志
-
看看我们的工具类长什么样子吧
package com.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; /* * 连接池工具类 * */ public class JDBCUtils { private static DataSource ds; //我们这里来初始化连接池 static { try { Properties pro = new Properties(); InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); ds = DruidDataSourceFactory.createDataSource(pro); } catch (Exception e) { e.printStackTrace(); } } //获取连接池对象 public static DataSource getDatasource() { return ds; } //获取Connection对象 public static Connection getConnection() throws SQLException { return ds.getConnection(); } }
-
再来看看我们的
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>example</groupId> <artifactId>Login</artifactId> <version>1.0-SNAPSHOT</version> <name>Login</name> <packaging>war</packaging> <properties> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> <junit.version>5.7.1</junit.version> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>compile</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.1</version> </plugin> </plugins> </build> </project>
-
我们再看看html文件
<form action="/Login_war_exploded/loginServlet" method="post"> <h2>邮箱账号登录</h2> <input type="text" placeholder="请输入邮箱账号" autocomplete="off" name="username"> <input type="password" placeholder="请输入密码" name="password"> <div class="third"><input type="checkbox">十天内免登录<span><a href="#">忘记密码?</a></span></div> <input type="submit" value="登 录"> </form>
-
-
封装一个数据库登录表的实体类,代码如下
-
package com.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; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
-
-
写一个登录方法的实现类
-
package com.dao; import com.domain.User; import com.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()); /** * 登录方法 * * @param loginUser 只有用户名和密码 * @return 包含用户的全部数据,没有就返回null */ public User login(User loginUser) { try { // 1 编写sql String sql = "select * from user where username = ? AND password = ?"; // 2 调用query方法 User user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), loginUser.getUsername(), loginUser.getPassword()); return user; } catch (DataAccessException e) { e.printStackTrace(); return null; } } }
-
-
写一个测试类(注意运行这里的时候,我们的source是在src/test/resources文件夹下的)
-
package com.test; import com.dao.UserDao; import com.domain.User; import org.junit.Test; public class UserDaoTest { @Test public void testLogin() { User user = new User(); user.setUsername("admin"); user.setPassword("123456"); UserDao dao = new UserDao(); User login = dao.login(user); System.out.println(login); } }
-
-
测试成功之后,我们就可以开始搞Servlet类了,先来搞一个登录之后参数首先传到的一个的Servlet类
-
package com.servlet; import com.dao.UserDao; import com.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 { // 2 获取请求参数 String username = req.getParameter("username"); String password = req.getParameter("password"); // 3 封装user对象 User user = new User(); user.setUsername(username); user.setPassword(password); // 4 调用UserDao的login方法 UserDao dao = new UserDao(); User login = dao.login(user); System.out.println(login); // 5 判断login是否是空 if (login == 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 { // super.doPost(req, resp); // 1 设置编码 req.setCharacterEncoding("utf-8"); // 2 获取请求参数 String username = req.getParameter("username"); String password = req.getParameter("password"); // 3 封装user对象 User user = new User(); user.setUsername(username); user.setPassword(password); // 4 调用UserDao的login方法 UserDao dao = new UserDao(); User login = dao.login(user); System.out.println(login); // 5 判断login是否是空 if (login == null) { //登录失败 req.getRequestDispatcher("/failServlet").forward(req, resp); } else { //登录成功 //存储数据 req.setAttribute("user", user); //转发 req.getRequestDispatcher("/successServlet").forward(req, resp); } } }
-
-
写一个登录成功的Servlet类
-
package com.servlet; import com.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 { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // super.doGet(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html;charset=utf-8"); //获取用户名 User user = (User) request.getAttribute("user"); if (user != null) { response.getWriter().write("<h1>登录成功," + user.getUsername() + ",你真是个小机灵鬼!</h1>"); } } }
-
-
最后再写一个登录失败的Sevlet类
-
package com.servlet; import com.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 { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // super.doGet(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html;charset=utf-8"); //获取用户名 User user = (User) request.getAttribute("user"); if (user != null) { response.getWriter().write("<h1>登录成功," + user.getUsername() + ",你真是个小机灵鬼!</h1>"); } } }
-
3.4 效果展示
登录页面
如果登录成功
登录失败
第四章 BeanUtils的基本使用
4.1 基本使用
上面的LoginServlet类中,我们发现有一段代码很麻烦,如下
// 2 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// 3 封装user对象
User user = new User();
user.setUsername(username);
user.setPassword(password);
我们可以试想一下,如果表单提交的数据能有十几个,难道我们要调用十几次
req.getParameter()
和十几次setUsername()
? 不可能,所以我们要寻找更好的办法
因此,org.apache.commons.beanutils.BeanUtils
这个包就排上用场了
我们直接看看怎么用
Map<String, String[]> parameterMap = req.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user,parameterMap);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
你没看错,就这三句话,懂得都懂
4.2 BeanUtils介绍
BeanUtils作用: 用于封装JavaBean的
首先,我们需要了解: 什么是JavaBean?
JavaBean: 标准的Java类 ,满足下列要求
- 类必须被public修饰
- 必须提供空参的构造方法
- 成员变量必须使用pricate修饰
- 提供公共setter和getter方法
JavaBean功能: 封装数据
BeanUtils的概念
BeanUtils操作的是类的属性
- 类的成员变量: 就是private修饰的那些沙雕东西
- 属性: setter和getter方法截取之后的产物
- 例如:
getUsername()--> Username --> username
- 例如:
也就是说,一般情况下,属性和成员变量是一样的,除非你的getter和setter方法你少写了或者多写了一些很奇怪的东西
BeanUtils的方法
-
setProperties(Obj obj,String name, String value)
:给Javabean实例对象设置属性-
@Test public void test(){ User user = new User(); try { BeanUtils.setProperty(user,"username","你爹"); BeanUtils.setProperty(user,"username","尼玛"); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } System.out.println(user);//User{id=0, username='尼玛', password='null'} }
-
-
getProperties(Object obj,String name, String value)
:获取属性-
@Test public void test(){ User user = new User(); try { BeanUtils.setProperty(user,"username","你爹"); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } try { System.out.println(BeanUtils.getProperty(user, "username"));//你爹 } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { e.printStackTrace(); } }
-
-
populate(Object obj ,Map map)
: 将map集合中的键值对信息,封装到对应的JavaBean对象中(重点掌握)BeanUtils.setProperty(user,"username","你爹"); BeanUtils.setProperty(user,"username","尼玛"); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } System.out.println(user);//User{id=0, username='尼玛', password='null'} }
-
getProperties(Object obj,String name, String value)
:获取属性-
@Test public void test(){ User user = new User(); try { BeanUtils.setProperty(user,"username","你爹"); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } try { System.out.println(BeanUtils.getProperty(user, "username"));//你爹 } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { e.printStackTrace(); } }
-
-
populate(Object obj ,Map map)
: 将map集合中的键值对信息,封装到对应的JavaBean对象中(重点掌握)