05.Request

Request

注意

  1. tomcat服务器创建并封装的请求对象为org.apache.catalina.connector.RequestFacade
  2. tomcat服务器创建并封装的响应对象为org.apache.catalina.connector.ResponseFacade
  3. 使用的是他们各自的实现的接口HttpServletRequest-ServletRequest;HttpServletResponse-ServletResponse
  4. web项目导包:web/WEB-INF/lib
  5. Request与Response对象随着访问请求而创建,随着响应完毕而销毁

之前接触过线程池数据库连接池的概念,因为创建线程以及数据库连接是非常耗费资源耗费时间的一件事,而创建一个普通的对象比创建线程以及数据库连接对象的时空开销是非常微小的!

一、Request概念及体系

1.Request对象和Response对象的原理


Request对象和Response对象的原理.png
  1. request和Response对象是由服务器创建的。我们需要使用它们
  2. 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请求的请求参数

  1. 获取流对象request
    • BufferedReader getReader():获取字符输入流,只能操作字符数据。
    • ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
  2. 从流中拿数据

三、【其他功能】:很重要!

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.步骤

  1. RequestDispatcher getRequestDispatcher(String path):通过【request】对象获取请求转发器对象,path是访问虚拟路径
  2. forward(ServletRequest request, ServletResponse response):使用【RequestDispatcher】请求转发器对象进行转发

request.getRequestDispatcher("转发路径").forward(response,response);

2.特点

  1. 浏览器地址栏路径不发生跳转【因为是服务器内部处理逻辑】。
  2. 只能转发到当前服务器内部资源中【如果要访问外部服务器的,需要代理】。
  3. 转发是【浏览器与服务器的一次请求响应之内】【转发前后的请求对象和响应对象是同一个】。
  4. 路径的写法,不带虚拟路径的

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内部能够根据这些规范的特点再结合反射就容易进行封装和其他操作了!

使用步骤

  1. 导包:commons-beanutils-1.8.0.jar
  2. 获取请求参数封装对象
// 获取所有参数
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类,封装数据的规范
    • 特点:
      1. 类必须被public修饰
      2. 必须提供空参的构造器
      3. 成员变量必须使用private修饰
      4. 提供公共settergetter方法
    • 概念:
      1. 成员变量:
      2. 属性:setter与getter方法被截取后的产物
        • 比如getUsername() -> Username -> username, 这个就是属性值,与设置的成员变量名一样

BeanUtils的方法

  1. populate(Object javaBean, Map map):将map集合的键值对应的信息,封装到对应的JavaBean对象中。
  2. setProperty(); 【了解】设置属性,执行对应的set属性名(属性值)方法
    • BeanUtils.setProperty(JavaBean实例,属性名,属性值)
  3. 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的区别(面试点)
    1. get方式提交的数据显示在地址栏中,准确的说是在请求行中的请求路径后面,没有请求体,而post方式提交的数据不会显示在地址栏中,提交的数据在请求体中
    2. get方式url的长度有限制,而post没有限制
    3. 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)
  • 转发特点写法
    1. 浏览器地址栏不变
    2. 只能在当前项目内部跳转
    3. 转发是一次请求一次响应
    4. 转发的路径编写:不需要带虚拟路径
request.getRequestDispatcher("转发路径").forward(request,response);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容