Request
注意
- tomcat服务器创建并封装的请求对象为
org.apache.catalina.connector.RequestFacade
- tomcat服务器创建并封装的响应对象为
org.apache.catalina.connector.ResponseFacade
- 使用的是他们各自的实现的接口
HttpServletRequest
-ServletRequest
;HttpServletResponse
-ServletResponse
- web项目导包:
web/WEB-INF/lib
- Request与Response对象随着访问请求而创建,随着响应完毕而销毁
之前接触过线程池和数据库连接池的概念,因为创建线程以及数据库连接是非常耗费资源耗费时间的一件事,而创建一个普通的对象比创建线程以及数据库连接对象的时空开销是非常微小的!
一、Request概念及体系
1.Request对象和Response对象的原理
Request对象和Response对象的原理.png
- request和Response对象是由服务器创建的。我们需要使用它们
- request对象是获取请求消息;response对象是来设置响应消息
2.Request对象继承体系结构
-
ServletRequest
-- 父接口-
HttpServletRequest
-- 子接口【使用的接口】-
org.apache.catalina.connector.RequestFacade
-- 孙实现类,(tomcat服务器实现的)
-
-
二.获取请求消息数据【HttpServletRequest接口】
1.获取请求行数据,例如GET /r/demo2?name=xiaoming&age=22 HTTP/1.1
- 【!】
String getMethod()
:获取请求方式GET
- 【!】
String getContextPath()
:获取虚拟路径/r
-
String getServletPath()
:获取Servlet路径/demo2
-
String getQueryString()
:获取get方式请求参数【序列化后的字符串】name=xiaoming&age=22
-
String getRequestURI()
:获取请求URI【统一资源标识符,范围大】/r/demo2
-
StringBuffer getRequestURL()
: 获取完整URL【统一资源定位符,范围小】http://localhost/r/demo2
-
String getProtocol()
: 获取协议及版本HTTP/1.1
- 【!】
String getRemoteAddr()
: 获取客户机的ip(这里是ipv6)地址0:0:0:0:0:0:0:1
-
String getRemotePort()
: 获取客户端的端口
2.获取请求头数据
-
Enumeration<String> getHeaderNames()
:获取所有请求头名称 -
String getHeader(String name)
: 通过请求头的名称获取请求头的值
// public class HttpServletLearn extends HttpServlet
...
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Enumeration<String> enu = req.getHeaderNames();
while (enu.hasMoreElements()){
String headName = enu.nextElement();
String headValue = req.getHeader(headName);
System.out.println(headName + ": " + headValue);
}
}
...
3.获取请求体数据的步骤
只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
- 获取流对象request
-
BufferedReader getReader()
:获取字符输入流,只能操作字符数据。 -
ServletInputStream getInputStream()
:获取字节输入流,可以操作所有类型数据
-
- 从流中拿数据
三、【其他功能】:很重要!
1.获取请求参数通用方式:不论是【get】还是【post】请求方式都可以使用以下方法来获取请求参数
String getParameter(String name)
:根据参数名称获取参数值u=z&p=1
String[] getParameterValues(String name)
:根据参数名称获取参数值的数组u=1&u=2
Enumeration<String> getParameterNames()
:获取请求的所有的参数名称Map<String, String[]> getParameterMap()
:获取所有参数的map集合。-
中文乱码问题
- get方式:tomcat8已经将get方式的乱码解决了
- post方式:会乱码,在获取参数之前,设置request的编码
-
request.setCharacterEncoding("utf-8)
;
-
response的设置:
resp.setContentType("text/html;charset=utf-8");
2.请求转发:一种在【服务器内部】的资源跳转方式
1.步骤
-
RequestDispatcher getRequestDispatcher(String path)
:通过【request】对象获取请求转发器对象,path是访问虚拟路径 -
forward(ServletRequest request, ServletResponse response)
:使用【RequestDispatcher】请求转发器对象进行转发
request.getRequestDispatcher("转发路径").forward(response,response);
2.特点
- 浏览器地址栏路径不发生跳转【因为是服务器内部处理逻辑】。
- 只能转发到当前服务器内部资源中【如果要访问外部服务器的,需要代理】。
- 转发是【浏览器与服务器的一次请求响应之内】【转发前后的请求对象和响应对象是同一个】。
- 路径的写法,不带虚拟路径的
3.共享数据【一次请求,需要经过不同的虚拟路径,需要共享数据】
注意:共享数据域【并不是】请求体或者请求头的参数,不能搞混淆了
- 域对象:一个有作用范围的对象,可以在范围内共享数据
- request域:代表【一次请求】的范围;一般用于请求转发的多个资源中共享数据
估计response也可以这样干,以后再说
-
方法:【request】
-
void setAttribute(String name, Object obj)
:存取数据 -
Object getAttitude(String name)
:通过键获取值 -
void removeAttribute(String name)
:通过键移除键值对
-
4.获取ServletContext:【request】
RequestDispatcher的作用域只能在一次请求响应之间,而ServletContext的作用域是当前整个web服务项目,而且是【单例模式】
ServletContext getServletContext()
四、综合案例:用户登录注册
代码部分详见:【i_loginVerify项目,后期补上代码】
1.BeanUtils工具类的基本使用
BeanUtils用于简化数据的封装,内部使用静态方法,需要传入一个JavaBean,由于JavaBean的成员变量和属性的严格规范,所以BeanUtils内部能够根据这些规范的特点再结合反射就容易进行封装和其他操作了!
使用步骤
- 导包:
commons-beanutils-1.8.0.jar
- 获取请求参数封装对象
// 获取所有参数
Map<String, String[]> map = request.getParameterMap();
// 创建user对象
User loginUser = new User();
// 使用org.apache.commons.beanutils下的BeanUtils封装
try {
BeanUtils.populate(loginUser, map);
} catch (IllegalAccessException e) {e.printStackTrace();
} catch (InvocationTargetException e) {e.printStackTrace();}
2.BeanUtils的介绍
用于分装javaBean【放在项目建立domain包下】
- JavaBean:标准的Java类,封装数据的规范
- 特点:
- 类必须被public修饰
- 必须提供空参的构造器
- 成员变量必须使用private修饰
- 提供公共setter和getter方法
- 概念:
- 成员变量:
- 属性:setter与getter方法被截取后的产物:
- 比如
getUsername() -> Username -> username
, 这个就是属性值,与设置的成员变量名一样
- 比如
- 特点:
BeanUtils的方法
-
populate(Object javaBean, Map map)
:将map集合的键值对应的信息,封装到对应的JavaBean对象中。 -
setProperty()
; 【了解】设置属性,执行对应的set属性名(属性值)
方法- BeanUtils.setProperty(JavaBean实例,属性名,属性值)
-
getProperty()
; 【了解】获得属性,指定对应的get属性名()
方法- BeanUtils.getProperty(JavaBean实例,属性名)
五、总结
- 生命周期:默认第一次访问的时候创建Servlet对象,执行init方法,每次请求过来之后执行Service方法,在service方法内部根据请求方式的不同调用不同的doXXX方法,Get请求调用doGet方法,Post请求调用doPost方法,当服务器关闭或者项目被移除了就销毁Servlet对象,执行destroy方法,初始化和销毁方法都只执行一次;Servet是单例,也就是说在Servlet整个生命周期中,Servet对象有且仅有一个
- http协议默认端口:80;超文本传输协议,基于请求和响应模型,请求先有,后有响应,一次请求只会有一次响应
- 程序优化思想:在HttpServlet实现子类的注解上添加loadOnStartup=1;将初始化操作放在服务器启动的时候操作【spring框架的配置文件就是这样干的】
- 项目的虚拟路径最好和项目名相同或者不写
- get请求的请求参数在请求行的请求路径后面;get请求方式没有请求体
- 请求头:
- key:value结构的,一般一个key对应一个value,也有一个key对应多个value的情况
- user-agent:浏览器的版本信息
- referer:当前这次请求从哪里发过来------防止盗取链接,做统计工作
- GET和POST的区别(面试点)
- get方式提交的数据显示在地址栏中,准确的说是在请求行中的请求路径后面,没有请求体,而post方式提交的数据不会显示在地址栏中,提交的数据在请求体中
- get方式url的长度有限制,而post没有限制
- post方式提交数据相对安全
- 获得请求方式:
String method = request.getMethod()
获取虚拟路径(项目名):
String contextPath = request.getContextPath();
获得URI/URL:
String uri = request.getRequestURI();
StringBuffer sb = request.getRequestURL();
获得远程ip地址:
String ip = reqeust.gerRemoteAddr();
- 获取请求提交的参数
获得单个值:
String value = reqeust.getParameter(String name);
获得一组值(复选框):
String[] values = request.getParameterValues(String name);
获得所有的值封装到map集合中:
Map<String,String[]> map = request.getParameterMap();
- 提交参数乱码问题的解决
get:tomcat8及以上已自主解决
post:
request.setCharacterEncoding("UTF-8"):
注意:这句话一定要写在获取参数之前
- 作为域对象存取数据
作用的范围: 一次请求响应的范围
什么时候创建:服务器收到客户端请求时创建request对象
什么时候销毁:服务器对当前这次请求做出响应后销毁
request.setAttribute(String key,Object value);
Object value = request.getAttribute(String key);
request.removeAttribute(String key)
- 转发特点写法
- 浏览器地址栏不变
- 只能在当前项目内部跳转
- 转发是一次请求一次响应
- 转发的路径编写:不需要带虚拟路径
request.getRequestDispatcher("转发路径").forward(request,response);