目录
1、Http请求协议概述
HTTP,Hyper Text Transfer Protocol,超文本传输协议,定义了客户端和服务器通信时,发送数据的格式。其特点是:
- 1)基于TCP/IP的高级协议;
- 2)默认端口是80;
- 3)基于请求、响应模型:一次请求对应一次响应;
- 4)无状态的:每次请求之间相对独立,不能交互数据;
【HTTP历史版本】:
- 1.0:每一次请求响应都会建立新的连接;
- 1.1:复用连接;
【请求消息数据格式】:
- 请求行:请求方式 请求url 请求协议/版本
请求方式,HTTP协议有7种请求方式,常见的有2种:
*GET:请求参数在请求行中,在url后;请求的url长度有限制;不太安全;
*POST:请求参数在请求体中,请求的url长度没有限制;相对安全; - 请求头:请求头名称:请求头值
常见的请求头:
*User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息,可以在服务器端获取该头信息,解决浏览器的兼容性问题;
*Referer:告诉服务器,当前请求从哪里来,作用是:可以防盗链、统计工作。 - 请求空行:空行,用于分割POST请求的请求头和请求体的
- 请求体(正文):封装POST请求消息的请求参数的
2、request和response对象的原理
request对象和response对象是由服务器创建的,我们来使用他们;request对象是来获取请求消息对象,response对象是来设置响应消息数据。
3、request对象
1)request对象的继承体系结构如下:
ServletRequset ——接口
| 继承
HttpServletRequest ——接口
| 实现
org.apache.catalina.connector.RequestFacade类(tomcat)
2)request对象的功能:
- 获取请求消息数据:
1、获取请求行数据(GET /4.servlet/demo4?name=zhangsan HTTP1.1)
获取请求方式-GET: String getMethod()
获取虚拟目录-/4.servlet: String getContextPath()
获取Servlet路径-/demo4: String getServletPath()
获取get请求方式参数-name=zhangsan: String getQueryString()
获取请求的URI- /4.servlet/demo4: String getRequestURI()
- http://localhost/4.servlet/demo4: String getRequestURL()
URL,统一资源定位符;URI,统一资源标识符
获取协议及版本-HTTP1.1: String getProtocol()
获取客户机的IP地址: String getRemoteAddr()@WebServlet("/requestDemo1") public class RequestDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String method = request.getMethod(); System.out.println(method); String contextPath = request.getContextPath(); System.out.println(contextPath); String servletPath = request.getServletPath(); System.out.println(servletPath); String queryString = request.getQueryString(); System.out.println(queryString); String requestURI = request.getRequestURI(); System.out.println(requestURI); StringBuffer requestURL = request.getRequestURL(); System.out.println(requestURL); String protocol = request.getProtocol(); System.out.println(protocol); String remoteAddr = request.getRemoteAddr(); System.out.println(remoteAddr); } }
2、获取请求头数据
通过请求头名称获取请求头的值:String getHeader(String name);
获取所有的请求头名称:Enumeration<String> getHeaderNames();@WebServlet("/requestDemo2") public class RequestDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()){ String s = headerNames.nextElement(); String value = request.getHeader(s); System.out.println(s+"---"+value); } //user-agent头 String agent = request.getHeader("user-agent"); if(agent.contains("Chrome")){ System.out.println("谷歌来了"); }else if(agent.contains("Firefox")){ System.out.println("火狐来了"); } //referer头 String referer = request.getHeader("referer"); System.out.println(referer); //防盗链 if(referer!=null){ if(referer.contains("/4.servlet")){ System.out.println("非盗链"); }else{ System.out.println("盗链"); } } } }
3、获取请求体数据
请求体:只有POST请求方式才有请求体,在请求体中封装了POST请求的请求参数;
获取步骤:1、获取流对象
--BufferedReader getReader():获取字符输入流,只能操作字符数据;
--ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据;
2、从流对象中拿数据@WebServlet("/requestDemo3") public class RequestDemo3 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { BufferedReader reader = request.getReader(); String line = null; while ((line=reader.readLine())!=null){ System.out.println(line); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
- 其他功能(重要):
1、获取请求参数通用方式:GET或POST方式均可
》String getParameter(String name):根据参数名称获取参数值; username=zhang&password=123
》String[] getParameterValues(String name):根据参数名称获取参数值的数组;hobby=1&hobby=2
》Enumeration<String> getParameterNames():获取所有请求的参数名称
》Map<String,String[]> getParameterMap():获取所有参数的map集合
@WebServlet("/requestDemo2")
public class RequestDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()){
String s = headerNames.nextElement();
String value = request.getHeader(s);
System.out.println(s+"---"+value);
}
//user-agent头
String agent = request.getHeader("user-agent");
if(agent.contains("Chrome")){
System.out.println("谷歌来了");
}else if(agent.contains("Firefox")){
System.out.println("火狐来了");
}
//referer头
String referer = request.getHeader("referer");
System.out.println(referer);
//防盗链
if(referer!=null){
if(referer.contains("/4.servlet")){
System.out.println("非盗链");
}else{
System.out.println("盗链");
}
}
}
}
【中文乱码问题】:get方式:tomcat8 已经将get乱码问题解决了;
post方式:在获取参数前设置request的编码 ,request.setCharacterEncoding("utf-8");
2、请求转发:一种在服务器内部的资源跳转方式,步骤:
》通过request对象和以前请求转发器对象:RequestDispatcher getRequestDispatcher(String path);
》使用该对象进行转发:forward(ServletRequest request, ServletResponse response);
@WebServlet("/requestDemo4")
public class RequestDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("requestDemo4被访问了");
//转发到demo5资源
request.getRequestDispatcher("/requestDemo5").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
请求转发的特点:
- 浏览器地址栏路径不发生变化;
- 只能转发到当前服务器内部内部资源中;
- 转发是一次请求;
3、共享数据:
域对象:一个有作用范围的对象,可以在范围内共享数据;
request域对象:代表一次请求的范围,一般用于请求转发的多个资源中共享数据,提供的方法:
》setAttribute(String name,Object obj):存储数据;
》Object getAttribute(String name):通过键获取值;
》void removeAttribute(String name):通过键移除键值对;
4、获取ServletContext:ServletContext getServletContext();
4、request登录案例
下面通过一个登录案例,对上述的request对象相关方法进行实战,需求如下:
- 编写login.xml登录页面(username&password 两个输入框);
- 使用Druid数据库连接池技术,操作mysql,day1数据库中的user表;
- 登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您;
- 登录失败跳转到FailServlet展示:登录失败,用户名或密码错误。
对于以上需求,分析如下:
开发步骤:
- 1)创建项目,导入login1.html页面,配置文件,jar包;
- 2)创建数据库环境;
- 3)创建一个包cn.test.domain,创建User类;
- 4)创建一个包cn.test.dao,创建类UserDao,操作user数据库表;
- 5)创建cn.test.servlet.LoginServlet类,完成登录的具体逻辑;
- 6)注意login.html的form表单中action路径写法:虚拟目录+Servlet的资源路径;
- 7)编写LoginServlet、FailServlet、SuccessServlet。
代码就不往上贴了,登录案例的实战代码传送门。
5、BeanUtils的使用
以上我们在LoginServlet中封装User对象时,是一个个获取再封装的,若参数较多时就比较麻烦了,有没有简单的封装方式?这里我们介绍下一个开源工具类,BeanUtils,加完jar包(commons-beanutils-1.8.0.jar)后使用步骤如下示例:
//2、获取所有请求参数
Map<String, String[]> parameterMap = request.getParameterMap();
//3、创建user对象
User loginUser = new User();
try {
BeanUtils.populate(loginUser,parameterMap);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
BeanUtils就是用来封装JavaBean的,JavaBean是标准的Java类,就是用来封装数据的,定义要求如下:
- 1)类必须被public修饰;
- 2)必须提供空参的构造类;
- 3)成员变量必须使用private修饰;
- 4)提供公共setter和getter方法。
BeanUtils的几个重要方法:
- 1)setProperty():设置属性值
- 2)getProperty():获取属性值
- 3)populate(Object obj,Map map):将Map集合的键值对信息封装都对应的JavaBean对象中。
作于202007032200,已归档
———————————————————————————————————
本文为博主原创文章,转载请注明出处!
若本文对您有帮助,轻抬您发财的小手,关注/评论/点赞/收藏,就是对我最大的支持!
祝君升职加薪,鹏程万里!