文章目录
1. Request 对象和 Response 对象的原理
- Request 和 Response 对象是由服务器创建的,我们只是来使用它们
- Request 对象是来获取请求消息,Response 对象是来设置响应消息
2. Request 对象继承体系结构
ServletRequest -- 接口
| 继承
HttpServletRequest -- 接口
| 实现
org.apache.catalina.connector.RequestFacade -- 类(Tomcat 实现的)
3. Request 对象的功能
3.1 获取请求消息数据
3.1.1 获取请求行数据
-
请求行格式
请求方式 请求url 请求协议/版本
-
方法
- 获取请求方式
- String getMethod()
- 如:GET
- 获取虚拟目录
- String getContextPath()
- 如:/day14
- 获取 Servlet 路径
- String getServletPath()
- 如:/demo1
- 获取 GET 方式请求参数
- String getQueryString()
- 如:name=zhangsan
- 获取请求 URI(统一资源标识符)
- String getRequestURI()
- 如:/day14/demo1
- 获取请求 URL(统一资源定位符)
- StringBuffer getRequestURL()
- 如:http://localhost/day14/demo1
- 获取协议及版本
- String getProtocol()
- 如:HTTP/1.1
- 获取客户机的 IP 地址
- String getRemoteAddr()
- 获取请求方式
3.1.2 获取请求头数据
- 方法
- 通过请求头的名称获取请求头的值
- String getHeader(String name)
- 获取所有的请求头名称
- Enumeration getHeaderNames()
- 通过请求头的名称获取请求头的值
3.1.3 获取请求体数据
-
注意
只有 POST 请求方式,才有请求体,在请求体中封装了 POST 请求的请求参数
-
使用步骤
- 获取流对象
- 获取字符输入流,只能操作字符数据
- BufferedReader getReader()
- 获取字节输入流,可以操作所有类型数据
- ServletInputStream getInputStream()
- 获取字符输入流,只能操作字符数据
- 从流对象中获取数据
- 获取流对象
3.2 其他功能(重要)
3.2.1 获取请求参数通用方式
-
不论 GET 还是 POST 请求方式都可以使用下列方法来获取请求参数:
- 根据参数名称获取参数值
- String getParameter(String name)
- 根据参数名称获取参数值的数组
- String[] getParameterValues(String name)
- 获取所有请求的参数名称
- Enumeration getParameterNames()
- 获取所有参数的 Map 集合
- Map<String,String[]> getParameterMap()
- 根据参数名称获取参数值
-
中文乱码问题
-
问题:当以 POST 方式请求时,请求参数为中文,获取请求参数时会出现中文乱码
-
解决办法:在获取请求参数前,设置 Request 对象的编码
request.setCharacterEncoding("utf-8");
-
3.2.2 请求转发
-
请求转发的概念
一种在服务器内部的资源跳转方式
-
请求转发的使用
- 通过 Request 对象获取请求转发器对象
- RequestDispatcher getRequestDispatcher(String path)
- 使用 RequestDispatcher 对象来进行转发
- void forward(ServletRequest request, ServletResponse response)
- 通过 Request 对象获取请求转发器对象
-
请求转发的特点
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中。
- 转发是一次请求
-
请求转发的练习
由 RequestDemo5 转发到 RequestDemo6
@WebServlet("/RequestDemo5") public class RequestDemo5 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("RequestDemo5 被访问了"); // 转发到 RequestDemo6 request.getRequestDispatcher("/RequestDemo6").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
@WebServlet("/RequestDemo6") public class RequestDemo6 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("RequestDemo6 被访问了"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
运行结果:
RequestDemo5 被访问了 RequestDemo6 被访问了
3.2.3 共享数据
-
域对象
一个有作用范围的对象,可以在范围内共享数据
-
Request 域
代表一次请求的范围,一般用于请求转发的多个资源中共享数据
-
方法
- 存储数据
- void setAttribute(String name,Object obj)
- 通过键获取值
- Object getAttribute(String name)
- 通过键移除键值对
- void removeAttribute(String name)
- 存储数据
-
共享数据的练习
实现 RequestDemo7 和 RequestDemo8 共享数据
@WebServlet("/RequestDemo7") public class RequestDemo7 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("RequestDemo7 被访问了"); // 存储数据到 Request 域中 request.setAttribute("value1","hello"); // 转发到 RequestDemo8 request.getRequestDispatcher("/RequestDemo8").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
@WebServlet("/RequestDemo8") public class RequestDemo8 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("RequestDemo8 被访问了"); // 获取 Request 域中的数据 Object value1 = request.getAttribute("value1"); System.out.println(value1); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
运行结果:
RequestDemo7 被访问了 RequestDemo8 被访问了 hello
3.2.4 获取 ServletContext 对象
-
方法
- 获取 ServletContext 对象
- ServletContext getServletContext()
- 获取 ServletContext 对象
-
练习
@WebServlet("/RequestDemo9") public class RequestDemo9 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext servletContext = request.getServletContext(); System.out.println(servletContext); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
运行结果:
org.apache.catalina.core.ApplicationContextFacade@52df6894
4. 用户登录案例
-
需求分析
编写一个登陆页面,用户输入用户名和密码后,会显示登陆成功或失败的页面。
-
概要设计
-
编码实现
-
创建数据库 day14,并创建 USER 表,在 User 表中插入两条记录
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(32) NOT NULL, `password` varchar(32) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; INSERT INTO `user` VALUES ('1', '张三', '123'); INSERT INTO `user` VALUES ('2', '李四', '321');
-
创建一个 JavaEE 项目,在 web 包中创建 WEB-INF 包,在 WEB-INF 包中创建 lib 包,在 lib 包中导入驱动 jar 包
- commons-logging-1.2.jar
- druid-1.0.9.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
-
在 src 包下创建 Druid 配置文件 druid.properties
driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/day14 username=root password=123456 initialSize=5 maxActive=10 maxWait=3000
-
在 src 下创建 com.zt.util 包,在其中创建工具类 JDBCUtils
package com.zt.util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtils { // 1.定义静态变量 dataSource private static DataSource dataSource; static { try { // 2.加载配置文件 Properties properties = new Properties(); InputStream resourceAsStream = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"); properties.load(resourceAsStream); // 3.创建数据库连接池对象,并赋值给 dataSource dataSource = DruidDataSourceFactory.createDataSource(properties); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 获取连接池方法 */ public static DataSource getDataSource() { return dataSource; } /** * 通过数据库连接池获取连接对象 */ public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } /** * 释放资源 */ public static void close(ResultSet resultSet, Statement statement, Connection connection) { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Statement statement, Connection connection) { close(null, statement, connection); } }
-
在 src 下创建 com.zt.domain 包,在其中创建用户实体类 User
package com.zt.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 + '\'' + '}'; } }
-
在 src 下创建 com.zt.dao 包,在其中创建操作数据库的类 UserDao,提供 login 方法
package com.zt.dao; import com.zt.domain.User; import com.zt.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 jdbcTemplate = 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 = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), loginUser.getUsername(), loginUser.getPassword()); return user; } catch (DataAccessException e) { return null; } } }
-
在 src 下创建 com.zt.web.servlet 包,在其中创建 LoginServlet,FailServlet,SuccessServlet
LoginServlet:
package com.zt.web.servlet; import com.zt.dao.UserDao; import com.zt.domain.User; import javax.servlet.RequestDispatcher; 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 { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.设置编码 request.setCharacterEncoding("utf-8"); // 2.获取请求参数 String username = request.getParameter("username"); String password = request.getParameter("password"); // 3.封装 user 对象 User loginUser = new User(); loginUser.setUsername(username); loginUser.setPassword(password); // 4.调用 login 方法 UserDao userDao = new UserDao(); User login = userDao.login(loginUser); // 5.判断 user if(login == null){ // 登陆失败 request.getRequestDispatcher("/FailServlet").forward(request,response); }else { // 登陆成功 // 存储数据 request.setAttribute("user",login); request.getRequestDispatcher("/SuccessServlet").forward(request,response); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
FailServlet:
package com.zt.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 { this.doPost(request,response); } }
SuccessServlet
package com.zt.web.servlet; import com.zt.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 { // 设置编码 response.setContentType("text/html;charset=utf-8"); // 获取 request 域中的 user 对象 User user = (User) request.getAttribute("user"); // 输出 response.getWriter().write("登录成功!"+user.getUsername()+",欢迎您"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
-
在 web 包中创建 login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/LoginServlet" method="post"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> <input type="submit" value="登录"> </form> </body> </html>
-
-
效果展示
5. BeanUtils
-
JavaBean 的概念
JavaBean 是标准的 Java 类,用于创建实体类,有如下要求:
- 类必须被 public 修饰
- 必须提供空参的构造器
- 成员变量必须使用 private 修饰
- 提供公共 setter 和 getter 方法
两个概念:
- 成员变量,如:private String username;
- 属性:setter 和 getter 方法截取后的产物,如:getUsername() --> Username–> username
注意:成员变量和属性大多数时候是相同的,但也可以不同。
-
BeanUtils 的作用
用于封装 JavaBean,可以简化数据的封装。
-
BeanUtils 的方法
- 设置属性值
- setProperty(Object bean, String name, Object value)
- 获取属性值
- getProperty(Object bean, String name)
- 封装 JavaBean(将 Map 集合的键值对信息,封装到对应的 JavaBean 对象中)
- populate(Object obj , Map map)
- 设置属性值
-
BeanUtils 的使用
-
导入 BeanUtils 的 jar 包,右键 Add as Library
- commons-beanutils-1.8.0
-
使用 BeanUtils 简化数据的封装
/* // 2.获取请求参数 String username = request.getParameter("username"); String password = request.getParameter("password"); // 3.封装 user 对象 User loginUser = new User(); loginUser.setUsername(username); loginUser.setPassword(password); */ // 2.获取请求参数 Map<String, String[]> parameterMap = request.getParameterMap(); // 3.封装 user 对象 // 3.1 创建 user 对象 User loginUser = new User(); // 3.2 使用 BeanUtils 封装 try { BeanUtils.populate(loginUser,parameterMap); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }
-