12.ServletRequest
12.1.request对象和response对象的原理
- request和response对象是由服务器创建的。我们来使用它们
- request对象是来获取请求消息,response对象是来设置响应消息
12.2.request对象继承体系结构
ServletRequest接口
| 继承
HttpServletRequest接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat)
12.3.HttpServletRequest类的API
12.3.1.获取请求消息数据
- 获取请求行数据
- GET http//:localhost/app/temp?name=zhangsan&age=18 HTTP/1.1
- public String getMethod() : 获取请求方法,返回发出此请求的HTTP方法的名称,例如GET、POST或PUT。
- public String getContextPath() : 返回指示请求上下文的请求URI部分。/app
- public String getServletPath() : 返回此请求的URL中调用servlet的部分。/temp
- public String getQueryString() : 返回包含在路径后面的请求URL中的查询字符串。name=zhangsan&age=18
- public String getRequestURI() : 返回此请求的URL的一部分,从协议名到HTTP请求第一行中的查询字符串。/app/temp
- public StringBuffer getRequestURL() : 获取请求资源,重建客户端用于发出请求的URL。
http://localhost/app/temp
- URL: 统一资源定位符 :
http://localhost/app/temp
(范围较小) - URI:统一资源标识符 : /app/temp(范围较大)
- URL: 统一资源定位符 :
- public String getProtocol() : 获取版本协议,以protocol的形式返回请求使用的协议的名称和版本,继承于ServletRequest。HTTP/1.1
- GET http//:localhost/app/temp?name=zhangsan&age=18 HTTP/1.1
- 获取请求头数据
- public String getHeader(String name) : 以字符串形式返回指定请求头的值。
- public Enumeration getHeaderNames() : 返回此请求包含的所有头名称的枚举。
- public Enumeration getHeaders(String name) : 返回指定请求头的所有值,作为字符串对象的枚举。
- 获取请求体数据:
- 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
- 步骤:
- 获取流对象
- public BufferedReader getReader() : 使用BufferedReader将请求主体作为字符数据。继承于ServletRequest。
- public ServletInputStream getInputStream() : 使用ServletInputStream作为二进制数据的请求主体。继承于ServletRequest。
- 从流对象中拿数据
- 获取流对象
- 获取客户机信息
- public String getRemoteAddr() : 返回发送请求的客户端或最后一个代理的Internet协议(IP)地址。继承于ServletRequest
- public String getRemoteHost() : 返回发送请求的客户端或最后一个代理的完全限定名。如果引擎无法或选择不解析主机名(以提高性能)。继承于ServletRequest。
- public int getRemotePort() : 返回发送请求的客户端或最后一个代理的Internet协议(IP)源端口。继承于ServletRequest。
- 获取本机信息
- public String getLocalAddr() : 返回接收请求的接口的Internet协议(IP)地址。继承于ServletRequest。
- public int getLocalPort() : 返回接收请求的接口的Internet协议(IP)端口号。继承于ServletRequest。
12.3.2.获取请求参数数据
- 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
- public String getParameter(String name) : 以字符串形式返回请求参数的值,如果参数不存在,则返回null。继承于ServletRequest。
- public String[] getParameterValues(String name) :返回包含给定请求参数所具有的所有值的字符串对象数组,如果参数不存在,则返回null。继承于ServletRequest。
- public Enumeration getParameterNames() : 返回字符串对象的枚举,其中包含此请求中包含的参数的名称。如果请求没有参数,则方法返回空枚举。
- public Map<String,String[]> getParameterMap() : 返回java.util.Map文件此请求的参数。请求参数是随请求发送的额外信息。对于httpservlet,参数包含在查询字符串或发布的表单数据中。
中文乱码问题:
- get方式:tomcat 8 已经将get方式乱码问题解决了
- post方式:会乱码
- 在获取参数前,设置request的编码request.setCharacterEncoding(“utf-8”);
- public void setCharacterEncoding(String env):重写此请求正文中使用的字符编码的名称。必须在读取请求参数或使用getReader()读取输入之前调用此方法。否则,就没有效果。
12.3.3.获取form表单的提交数据
- 对于获取数据,form表单必须要有name属性,提交上的值才能是key-value形式,这样才能被成功获取到
public class User {
private String username;
private String password;
private String gender;
private String[] hobby;
private String province;
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;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String[] getHobby() {
return hobby;
}
public void setHobby(String[] hobby) {
this.hobby = hobby;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public User(String username, String password, String gender, String[] hobby, String province) {
this.username = username;
this.password = password;
this.gender = gender;
this.hobby = hobby;
this.province = province;
}
public User() {
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", gender='" + gender + '\'' +
", hobby=" + Arrays.toString(hobby) +
", province='" + province + '\'' +
'}';
}
}
@WebServlet("/submit")
public class SubmitServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//如何获取form表单提交的各种类型的请求参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String gender = request.getParameter("gender");
//如果提交的参数是checkbox,使用该方法可能获取的结果不全
//String hobby = request.getParameter("hobby");
String province = request.getParameter("province");
String[] hobbies = request.getParameterValues("hobby");
System.out.println(username);
System.out.println(password);
System.out.println(gender);
//System.out.println(hobby);
System.out.println(province);
System.out.println(Arrays.toString(hobbies));
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
- 在web目录下创建一个form.html文件,浏览器输入localhost/app/form.html,就可以提交到上面的Servlet中去
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
usename=xxx&password=xxx&gender=xxx&....
<!-- 路径一定要写对,和Servlet相对应 -->
<!-- 全路径写法:<form action="http://localhost:80/app/submit" method="get">
<!-- 相对路径写法:<form action="submit" method="get">
<!-- 相对应用路径写法,/应用名/资源名,把全路径中访问协议、主机、端口号部分给去掉,提交的路径始终不需要发生变更。推荐 -->
<form action="/app/submit" method="get">
<input type="text" name="username"><br>
<input type="password" name="password"><br>
<input type="radio" name="gender" value="male">男
<input type="radio" name="gender" value="female">女<br>
<input type="checkbox" name="hobby" value="java">java
<input type="checkbox" name="hobby" value="python">python
<input type="checkbox" name="hobby" value="c++">c++<br>
<select name="province">
<option value="wuhan">武汉</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
</select>
<input type="submit">
</form>
</body>
</html>
12.3.4.BeanUtils
- 介绍
- 用于封装JavaBean的工具类
- 要求:
- 类必须被public修饰
- 必须提供空参的构造器
- 成员变量必须使用private修饰
- 提供公共setter和getter方法
- 功能:封装数据
- 下载配置方式
https://mvnrepository.com/
进去验证以后搜索beanutils,找到对应版本,下载jar包的同时,下载下方Compile Dependencies的两个依赖环境,共三个- 在module根目录下创建一个lib文件夹,将三个包复制进去,同时,在上面右键,选择Add as Library,相当于在IDEA中注册该资源
- tomcat提供的类加载器加载应用下面的class以及jar包的时候,只会到WEB-INF/classes以及WEB-INF/lib目录下加载其他地方不会去加载
- 方式一:将这三个包放在WEB-INF目录下
- 方式二:打开Project Structure设置,找到Artifacts设置选项,点击Output Layout选项卡,会看到报错信息,缺失了beanutils资源包,在WEB-INF目录处右键,选择Create Directory,新建一个lib目录,在lib目录上右键,选择Add Copy of,点击Library Files,在新窗口选择beanutils,确定即可。
- 封装原理:BeanUtils.poulate(Object, parameterMap)方法,会获取到parameterMap中的键值对,parameterMap中存储的是form表单提交上来的参数,对于map中的每个key值,会去Object中寻找setXxx方法,对其设置为对应的value值。
- 同样对于上面例子的User和form表单,编写以下测试类
@WebServlet("/beanutils") public class BeanUtilsTest extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { User user = new User(); request.setCharacterEncoding("utf-8"); Map<String, String[]> parameterMap = request.getParameterMap(); try { BeanUtils.populate(user, parameterMap); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println(user); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //doPost(request, response); String username = request.getParameter("username"); System.out.println(username); } }
12.4.请求转发
- 特点:
- 一种在服务器内部的资源跳转方式
- 一个请求到来之后,交给一个servlet来处理,servlet处理完毕之后,需要将请求交给另外一个servlet,或者将请求交给另外一个页面来最后做出响应,那么这个时候就可以使用转发。在真实应用中很少用到,页面跳转一般由前端负责
- 一个组件(源组件)执行完毕之后,它将响应的主动权交给另外一个组件(目标组件),后续响应主要由另外一个组件(目标组件)来负责。这里面涉及到了一个主动权变更的过程。
- 针对源组件来说,转发前后,源组件可以再最终的响应报文中留下响应头,但是无法留下响应体。
- 包含主要用在页面包含另外一个页面中,最大的特征,主动权还在自己手中,源组件包含过后仍然可以设置响应体
- 转发前后请求方法不变,而refresh、重定向,浏览器默认使用get方式
- 原理:
- 转发:servlet————–> html(响应体由该组件来提供)
- 包含:html (响应体由该组件来提供)<—————— html
- 步骤:
- 通过request对象获取请求转发器对象:
public RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发:
public void forward(ServletRequest request,ServletResponse response)
:将来自servlet的请求转发到服务器上的另一个资源(servlet、JSP文件或HTML文件)。此方法允许一个servlet对请求进行初步处理,并允许另一个资源生成响应
- 或者,使用RequestDispatcher对象来进行包含:
public void include(ServletRequest request,ServletResponse response)
:响应中资源的内容(servlet、JSP页、HTML文件)。本质上,此方法支持编程的服务器端包含。
- 通过request对象获取请求转发器对象:
- 特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中。
- 转发是一次请求
- 共享数据:
- 域对象:一个有作用范围的对象,可以在范围内共享数据
- request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
- 方法:
public void setAttribute(String name,Object obj)
:存储数据public Object getAttitude(String name)
:通过键获取值public void removeAttribute(String name)
:通过键移除键值对
- 获取
ServletContext
:public ServletContext getServletContext()
- Example:
- 登录案例:登录成功跳转到成功的页面,失败后跳转到失败的页面
@WebServlet("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //登录需要做什么事情? String username = request.getParameter("username"); String password = request.getParameter("password"); //直接固定 if("admin".equals(username) && "admin".equals(password)){ //表示登录成功 //转发里面/开头的路径必须要求把应用名给去掉才可以正常访问。因为Tomcat配置了应用名,但是服务器不知道应用名 request.getRequestDispatcher("/success.html").forward(request,response); }else { request.getRequestDispatcher("/fail.html").forward(request, response); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
- 如果该路径的执行解析主体是服务器,那么就不需要加应用,直接/资源路径即可,如:转发
- 如果该路径的执行解析主体是浏览器,那么就需要加应用名,/应用名/资源路径,如:form action img src a href
- 下面是登陆成功的页面和失败的页面,均将其放置在web文件夹下面
<!-- 登录页面 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/app/login" method="post"> <input type="text" name="username"><br> <input type="password" name="password"><br> <input type="submit"> </form> </body> </html> <!-- 登录成功页面 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> login fail </body> </html> <!-- 登录失败页面 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> login success </body> </html>
12.5.Request域
- request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据,每个请求都会生成一个request域
- Request对象中也有一个map,只要两个Servlet能够拿到同一个Request对象,那么他们就可以共享该对象里面的map
- 只有转发或包含的两个组件之间可以共享Request域,其他的都不能共享
- 生命周期:
- 创建:访问时创建
- 销毁:响应结束request销毁
- 作用域:一次请求中
- API
- public void setAttribute(String name,Object obj):存储数据
- public Object getAttitude(String name):通过键获取值
- public void removeAttribute(String name):通过键移除键值对
@WebServlet("/domain1") public class DomainServlet1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttitude("username","request"); request.getRequestDispatcher("/domain2").forward(request,response); } } @WebServlet("/domain2") public class DomainServlet2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = (String) request.getAttitude("username"); System.out.println(username); } } //直接访问domain1,domain1会将其发送给domain2,可以看到控制台中输出了request
12.6.完整的登录案例
- 用户登录案例需求:
- 编写login.html登录页面,username & password 两个输入框
- 使用Druid数据库连接池技术,操作mysql,day14数据库中user表
- 使用JdbcTemplate技术封装JDBC
- 登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您
- 登录失败跳转到FailServlet展示:登录失败,用户名或密码错误
* 开发步骤
1. 创建项目,导入html页面,配置文件,jar包
2. 创建数据库环境
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
);
3. 创建包cn.itcast.domain,创建类User
package cn.itcast.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 + '\'' +
'}';
}
}
4. 创建包cn.itcast.util,编写工具类JDBCUtils
package cn.itcast.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import javax.xml.crypto.Data;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* JDBC工具类 使用Durid连接池
*/
public class JDBCUtils {
private static DataSource ds ;
static {
try {
//1.加载配置文件
Properties pro = new Properties();
//使用ClassLoader加载配置文件,获取字节输入流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//2.初始化连接池对象
ds = DruidDataSourceFactory.createDataSource(pro);
} 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();
}
}
5. 创建包cn.itcast.dao,创建类UserDao,提供login方法
package cn.itcast.dao;
import cn.itcast.domain.User;
import cn.itcast.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 user包含用户全部数据,没有查询到,返回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;
}
}
}
6. 编写cn.itcast.web.servlet.LoginServlet类
package cn.itcast.web.servlet;
import cn.itcast.dao.UserDao;
import cn.itcast.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 {
//1.设置编码
req.setCharacterEncoding("utf-8");
//2.获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//3.封装user对象
User loginUser = new User();
loginUser.setUsername(username);
loginUser.setPassword(password);
//4.调用UserDao的login方法
UserDao dao = new UserDao();
User user = dao.login(loginUser);
//5.判断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);
}
}
7. 编写FailServlet和SuccessServlet类
@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");
if(user != null){
//给页面写一句话
//设置编码
response.setContentType("text/html;charset=utf-8");
//输出
response.getWriter().write("登录成功!"+user.getUsername()+",欢迎您");
}
}
@WebServlet("/failServlet")
public class FailServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//给页面写一句话
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/181055.html