再写Request对象之前,先说一下HTTP协议中的请求消息,请求消息包括(请求行,请求头,请求空行,请求体)
请求行:格式-> 请求方式,请求url,请求协议,版本
举例:GET /login.html HTTP/1.1
请求方式常用的有get和post
请求头:客户端告诉服务端一些信息
格式->请求头名称:请求头值
常见的请求头:User-Agent浏览器的版本,可解决浏览器兼容问题
Referer 来源,可解决防盗和统计工作
请求空行:分割请求头和请求体
请求体:只有请求方式为post的时候才有请求体,里面放的时参数信息
客户端服务端原理:
当在浏览器中输入一个地址的时候并回车的时候
1.浏览器就会把请求消息发送给服务器,tomcat服务器会根据请求的url资源路径,创建相应的类对象,创建request和response对象,request中封装请求消息数据,
2.tomcat把request和response对象传递给service方法,调用service方法
3.程序员通过request和response对象可以获取请求消息数据并设置响应消息数据
4.服务器要给浏览器相应,首先要从response对象中拿到程序员设置的响应消息数据
5.通过相应消息数据response再响应消息
下面就说说request对象中的一些方法
request既然是获取请求消息数据,那么首先是获取请求头
1.获取请求行数据
写2个比较重要的,
一个是获取请求行中的虚拟目录 String getContextPath()
一个是获取请求行中的url:* String getRequestURI():
* StringBuffer getRequestURL() :
写了个示例:写一个html网页,里面有username和psw,然后输入提交,到demo1页面,提交后获取请求行的消息
@WebServlet("/demo1")
public class requestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();//获取请求方式 GET
String contextPath = req.getContextPath();//获取虚拟目录 /Servlet2_war_exploded
String servletPath = req.getServletPath();//获取servle目录 /demo1
String queryString = req.getQueryString();//获取get方式的请求参数 username=zhangsan&psw=123
String requestURI = req.getRequestURI();//获取uri /Servlet2_war_exploded/demo1
StringBuffer requestURL = req.getRequestURL();//获取url http://localhost:8080/Servlet2_war_exploded/demo1
String protocol = req.getProtocol();//获取版本 HTTP/1.1
String remoteAddr = req.getRemoteAddr();//获取客户机的ip地址 127.0.0.1
System.out.println(method);
System.out.println(contextPath);
System.out.println(servletPath);
System.out.println(queryString);
System.out.println(requestURI);
System.out.println(requestURL);
System.out.println(protocol);
System.out.println(remoteAddr);
}
}
获取请求头数据:
- String getHeader(String name):通过请求头的名称获取请求头的值
- Enumeration getHeaderNames():获取所有的请求头名称
一般getHeader用的比较多,下面通过获取常见的2个请求头
User-Agent来根据不同浏览器的版本,可解决不同的问题
Referer 可解决防盗和统计工作
先写一个html页面来方便演示Referer
我用火狐浏览器打开后输出了火狐的版本信息,以及火狐
然后输出了来源http://localhost:8080/Servlet2_war_exploded/demo2HTML.html
@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 {
//获取客户端的浏览器版本
String agent = request.getHeader("user-agent");
System.out.println(agent);
//Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0
if(agent.contains("chrome")){
System.out.println("谷歌");
}else if(agent.contains("Firefox")){
System.out.println("火狐");
}
//获取访问来源
String referer = request.getHeader("referer");
System.out.println(referer);
//http://localhost:8080/Servlet2_war_exploded/demo2HTML.html
//防盗链
if(referer.contains("/Servlet2_war_exploded")){
System.out.println("正常播放");
}else {
System.out.println("盗链!!");
}
}
}
获取请求体数据,只有请求方式为post时候才有请求体
步骤:
- 获取流对象
- BufferedReader getReader():获取字符输入流,只能操作字符数据
- ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
- 再从流对象中拿数据
还是写了一个页面,通过post方式提交数据
@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 {
this.doPost(request,response);
}
}
获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
- String getParameter(String name):根据参数名称获取参数值
- String[] getParameterValues(String name):根据参数名称获取参数值的数组
- Enumeration getParameterNames():获取所有请求的参数名称
- Map<String,String[]> getParameterMap():获取所有参数的map集合
- request.setCharacterEncoding(“utf-8”);解决post方式中文乱码问题
还是写一个页面,提交信息,我们添加了一个复选框hobby
@WebServlet("/requestDemo4")
public class requestDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决post请求中中文乱码问题
request.setCharacterEncoding("utf-8");
// 1. String getParameter(String name):根据参数名称获取参数值
String username = request.getParameter("username");
System.out.println(username);//zhangsan
//2. String[] getParameterValues(String name):根据参数名称获取参数值的数组
String[] hobbies = request.getParameterValues("hobby");
for (int i = 0; i <hobbies.length ; i++) {
System.out.println(hobbies[i]);
}//study game
//3. Enumeration<String> getParameterNames():获取所有请求的参数名称
Enumeration<String> names = request.getParameterNames();
while (names.hasMoreElements()){
System.out.println(names.nextElement());
}//username psw hobby
//4. Map<String,String[]> getParameterMap():获取所有参数的map集合
Map<String, String[]> pm = request.getParameterMap();
Set<String> set = pm.keySet();
for (String s1 : set ) {
System.out.println(s1);
String[] strings = pm.get(s1);
for (String value : strings ) {
System.out.println(value);
}
System.out.println("-----------");
}
}
}
请求转发功能
这种功能在我看来类似于超链接,浏览器的地址栏不发生变化,只是在服务器内部发生地址变化,转发是一次请求
具体步骤是:
- 通过request对象获取请求转发器对象:
RequestDispatcher getRequestDispatcher(String path) - 使用RequestDispatcher对象来进行转发:
forward(ServletRequest request, ServletResponse response)
共享数据
在多个转发中可以共享的数据,需要设置共享数据,然后接受共享数据
- 方法:
1. void setAttribute(String name,Object obj):存储数据
2. Object getAttribute(String name):通过键获取值
3. void removeAttribute(String name):通过键移除键值对
@WebServlet("/requestDemo5")
public class requestDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("555");
//存储共享数据
request.setAttribute("name","kavin");
//转发
request.getRequestDispatcher("/requestDemo6").forward(request,response);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
@WebServlet("/requestDemo6")
public class requestDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过键获取共享数据的值
Object name = request.getAttribute("name");
System.out.println(name);
System.out.println("6666");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
在输出中,不仅看到了555,还有kavin和666,说明当我们访问了第一个页面的时候,跳转到了第二个页面,这就是转发。