1. Request概述
2. reuqest获取请求消息内容
请求行
请求头
请求参数(体)
3. request其他功能
请求转发
域对象
- 用户通过浏览器访问服务器时,Tomcat将HTTP请求中所有的信息都封装在Request对象中
- 作用:开发人员可以通过request对象方法,来获取浏览器发送的所有信息.
Web 服务器收到客户端的 http 请求,会针对每一次请求分别创建一个用于代表请求的 request 对象和代表响应的 response 对象。
Request的体系结构
上图为继承关系:HttpServletRequest 对象代表客户端的请求,当客户端通过 HTTP 协议访问服务器时, HTTP 请求中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。
在javaEE中我们是面向接口编程
通过以上分析:Request对象进行常用的操作为:
1) 获取请求数据2)作为域对象3)请求转发
Api介绍
String getMethod() 获取请求方式的类型 如:GET或POST
StringBuffer getRequestURL() 获取客户端发出请求完整URL
String getRequestURI() 获取请求行中的资源名部分
String getContextPath() 获取当前项目根路径
String getProtocol() 获取当前协议的名称和版本
String getRemoteAddr() 获取IP地址
int getLocalPort() 获取端口
注:uri: 统一资源标识符 , 用来标识一个资源 , 资源路径。 ( 相当于身份证 )url: 统一资源定位符 , 是一种具体的 URI, 可以用来标识一个资源 . 并且指明了如何定位一个资源(相当于身份证的地址)如:http://localhost:8080/wsl/demourl: http://localhost:8080/wsl/demouri: /wsl/demo
1。获取请求行信息
* 例如:
GET /wsl_request/requestDemo1 HTTP/1.1
* 相关API:
1. 获取请求方式 GET
String getMethod()
2. 获取项目虚拟路径(项目名)/wsl_request
String getContextPath()
3. 获取URI /wsl_request/requestDemo1
统一资源标识符(范围广) 共和国
String getRequestURI()
4. 获取URL http://localhost:8080/wsl_request/requestDemo1
统一资源定位符(确定某一个地址) 中华人民共和国
StringBuffer getRequestURL()
5. 获取协议和版本号 HTTP/1.1
String getProtocol()
6. 获取客户端ip
String getRemoteAddr()
@WebServlet("/requestDemo1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// System.out.println(req);
System.out.println("请求方式:" + req.getMethod());
System.out.println("虚拟路径:" + req.getContextPath());
System.out.println("URI:" + req.getRequestURI());
System.out.println("URL:" + req.getRequestURL());
System.out.println("协议和版本:" + req.getProtocol());
System.out.println("客户端ip:" + req.getRemoteAddr());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
2.获取请求头信息
* 例如:
Host: localhost:8080
* 相关API:
1. 获取知道请求头名称对应的值,注:名称不区分大小写
String getHeader(String name)
2. 获取所有请求头的名称
EnumerationgetHeaderNames()
注:是Iterator前身
@WebServlet("/requestDemo2")
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取所有的请求头名称
Enumeration enumeration = req.getHeaderNames();
// 遍历
while(enumeration.hasMoreElements()){
// 取出元素名(请求头名称)
String name = enumeration.nextElement();
// 根据名称获取值
String value = req.getHeader(name);
System.out.println(name +" : "+ value);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
3.demo
请求头中参数有一个referer:请求来源
/*
视频防盗链
*/
@WebServlet("/refererRequest")
public class RefererRequest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
// 1.获取请求来源(如果是浏览器地址直接访问的话,referer就是null)
String referer = req.getHeader("referer");
// 2.判断是不是自家网站发起的请求
if (referer != null && referer.startsWith("http://localhost:8080")) {
resp.getWriter().write("正常播放视频...");
}else{
resp.getWriter().write("想看吗?来优酷吧....");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
4.浏览器兼容性问题
user-agen:浏览器版本信息
/*
浏览器兼容性
*/
@WebServlet("/userAgentReqeust")
public class UserAgentReqeust extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
// 1.获取浏览器版本信息
String userAgent = req.getHeader("user-agent");
// 2.判断浏览器版本
if (userAgent.contains("Chrome")) {
resp.getWriter().write("浏览器:谷歌");
} else if (userAgent.contains("Firefox")) {
resp.getWriter().write("浏览器:火狐");
} else {
resp.getWriter().write("浏览器:其他");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
5.获取请求参数,请求体
不论get还是post请求方式,都可以使用下列方法来获取请求参数
在web阶段,get和post处理的业务逻辑都是一样的
* 参数
username=wsl&password=123456&hobby=eat&hobby=perm
* API
1. 获取指定参数名的值 username=wsl
String getParameter(String name)
2. 获取指定参数名的值数组 hobby=eat&hobby=perm
String[] getParameterValues(String name)
3. 获取所有参数名和对应值数组,参数名 name(key),值数组 value,封装map集合
Map getParameterMap()
* 中文乱码【重点】
get:在tomcat8及以上版本,内部URL编码(UTF-8)
post:编码解码不一致,造成乱码现象
客户端(浏览器)编码:UTF-8
服务器默认 解码:ISO-8859-1 拉丁文
指定解码:void setCharacterEncoding(String env)
注:必须在方法内,行首
form
get方式:
post方式:
@WebServlet("/requestDemo3")
public class RequestDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("手动获取---------");
String username = req.getParameter("username");
System.out.println("用户:" + username);
String password = req.getParameter("password");
System.out.println("密码:" + password);
String[] hobby = req.getParameterValues("hobby");
System.out.println("爱好:" + Arrays.toString(hobby));
System.out.println("自动获取---------");
Map parameterMap = req.getParameterMap();
parameterMap.forEach((k, v) -> { //此处用了lamda表达式
System.out.println(k + " = " + Arrays.toString(v));
});
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 指定post的解码方式....
req.setCharacterEncoding("UTF-8");
System.out.println("post提交方法,再去调用get....");
this.doGet(req, resp);
}
}
6.BeanUtils jar包
是apache组织,提供一套工具类,简化参数的封装.....
简单来说:将前端提交的数据,直接封装到你想要的JavaBean中
(1)向项目中导入jar包
(2)使用工具类封装数据
BeanUtils测试:
(3)数据封装:
@WebServlet("/requestDemo4")
public class RequestDemo4 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
// 使用BeanUtils快速封装数据到 User对象中
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");// 指定解码方式
// 1.获取所有参数的数据,map集合
Map parameterMap = request.getParameterMap();
// 2.创建user对象
User user = new User();
// 3.调用工具类,实现快速封装
try {
BeanUtils.populate(user, parameterMap);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(user);
}
}
考虑问题:
1.请求转发
一种在服务器内部的资源跳转方式
* API
1. 通过reqeust对象,获得转发器对象
RequestDispatcher getRequestDispatcher(String path)
2. 通过转发器对象,实现转发功能
void forward(ServletRequest request, ServletResponse response)
* 请求转发特点
浏览器:发了一次请求
地址栏:没有发生改变
只能转发到服务器内部资源....
* 链式编程
request.getRequestDispatcher("/bServlet").forward(reqeust,response)
2.域对象,(共享数据)
- 域对象:一个有作用范围的对象,可以在范围内共享数据
- request域:代表一次请求的范围,一般用于一次请求中转发的多个资源中共享数据
API
1. 设置数据
void setAttribute(String name, Object o)
2. 获取数据
Object getAttribute(String name)
3. 删除数据
void removeAttribute(String name)
生命周期
1. 何时创建
用户发送请求时,创建request
2. 何时销毁
服务器返回响应是,销毁request
3. 作用范围
一次请求,包含多次转发
coding:
@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("aServlet处理功能上....");
// 转发到BServlet
/* // 1.获得转发器对象 path = @WebServlet("/bServlet")
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/bServlet");
// 2.实现转发功能
requestDispatcher.forward(request, response);*/
// 存一个数据
request.setAttribute("hanbao", "鸡腿堡");
// 链式编程横
request.getRequestDispatcher("bServlet").forward(request, response);
}
}
@WebServlet("/bServlet")
public class BServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("bServlet处理功能下....");
// 获取数据
String hanbao = (String) request.getAttribute("hanbao");
System.out.println("hanbao:" + hanbao);
}
}
3.获取ServletContext对象
应用上下文对象,表示一个web项目
通过reuqest,可以获得ServletContext对象
public ServletContext getServletContext();
案例分析:
1.新建项目,并导入工具包,编写index.html
index
用户登录
2.User实体类
// 用户对象
public class User {
private String username;// 用户名
private String password;// 密码
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{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
3.LoginServlet类, SuccessServlet类,FailServlet类
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.设置request解码方式
request.setCharacterEncoding("UTF-8");
// 2.获取浏览器请求参数,map集合
Map parameterMap = request.getParameterMap();
// 3.使用BeanUtils工具类,封装user对象中
User user = new User();
try {
BeanUtils.populate(user, parameterMap);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
// 4.判断
if("wsl".equals(user.getUsername())&&"123".equals(user.getPassword())){
// 正确
request.setAttribute("user", user);
request.getRequestDispatcher("/successServlet").forward(request,response);
}else{
// 错误
request.getRequestDispatcher("/failServlet").forward(request,response);
}
}
}
@WebServlet("/successServlet")
public class SuccessServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.从request域获取user对象
User user = (User) request.getAttribute("user");
// 2.友情提示
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(user.getUsername() + ",登录成功");
}
}
@WebServlet("/failServlet")
public class FailServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.友情提示
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("用户名或密码错误..");
}
}
1.自定义Servlet模板
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
@javax.servlet.annotation.WebServlet("/${Class_Name}")
public class ${Class_Name} extends javax.servlet.http.HttpServlet {
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
this.doPost(request,response);
}
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
}
}
2.IDEA 代码抛异常快捷方式
快捷方式一:(光标移到该代码行,Alt+Enter),可以异常外抛出,也可以try-catch:
快捷方式二:(光标移到该代码行,或者选中该行代码,Ctrl+Alt+T):