WEB核心之Request

HttpServletRequest

1 Request概述

​ ​ 我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。
​ ​ service方法中的request的类型是ServletRequest,而doGet/doPost方法的request的类型是HttpServletRequest,HttpServletRequest是ServletRequest的子接口,功能和方法更加强大。由于HTTP请求消息分为请求行,请求头和请求体三部分。因此,在HttpServletRequest接口中定义了获取请求行,请求头和请求体的相关方法。

2 Requset常用API

2.1 获取请求行信息的相关方法

​​ ​ 当访问Servlet时,会在请求消息的请求行中,包含了请求方式,请求资源名,请求路径,HTTP协议信息等信息。

方法声明功能描述
String getMethod()  该方法用于获取HTTP请求消息中的请求方式。
String getRequestURI()  该方法用于获取请求行中资源名称部分,即位于URL的主机和端口之后,参数之前的部分。
String getQueryString()  该方法用于获取请求行中的参数部分,也就是资源路径后面问号以后的所有内容。
String getContextPath()  该方法用于获取WEB工程的名字。
String getServletPath()  该方法用于获取Servlet的名称或Servlet所映射的路径。
String getRemoteAddr()  该方法用于获取请求客户端的IP地址。
StringBuffer getRequestURL()  该方法获取客户端发出请求时的完整URL,包括协议、服务器名、端口号、资源路径等信息,但不包括后面的查询参数部分。
演示代码:
@WebServlet(urlPatterns="/get", name="GetRequestServlet")
public class GetRequestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        String method = request.getMethod();
        System.out.println("method:"+method);

        String requestURI = request.getRequestURI();
        System.out.println("requestURI:"+requestURI);

        StringBuffer requestURL = request.getRequestURL();
        System.out.println("requestURL:"+requestURL);

        String contextPath = request.getContextPath();
        System.out.println("contextPath:"+contextPath);

        String remoteAddr = request.getRemoteAddr();
        System.out.println("remoteAddr:"+remoteAddr);

        String servletPath = request.getServletPath();
        System.out.println("servletPath:"+servletPath);

        String queryString = request.getQueryString();
        System.out.println("queryString:"+queryString);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        this.doPost(request, response);
    }
}

控制台:
    method:GET
    requestURI:/demo/get
    requestURL:http://localhost:8080/demo/get
    contextPath:/demo
    remoteAddr:0:0:0:0:0:0:0:1
    servletPath:/get
    queryString:username=kunkun&username=CTRL

注意:假如是POST提交方式的话,getQueryString的返回值是null

2.2 获取请求头信息的相关方法

方法声明功能描述
String getHeader(String name)获取一个指定头字段的值
long getDateHeader(String name)获取一个指定头字段的值,并将其值转为int类型
int getIntHeader(String name)获取一个指定头字段的值,并将其值转为毫秒值
Enumeration getHeaderNames()获取所有的头字段的名字
Enumeration getHeaders(String name)获取指定头字段的值(一个头字段可能有多个)

演示代码:

public class HeaderServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) 
	throws ServletException, IOException {
		String agent = request.getHeader("User-Agent");
		System.out.println("User-Agent头字段的信息:"+agent);
        
		Enumeration<String> headerNames = request.getHeaderNames();
		Iterator<String> it = headerNames.asIterator();
		while(it.hasNext()) {
			System.out.println("头名称:"+it.next());
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) 
	throws ServletException, IOException {
		doGet(request, response);
	}
}

控制台:
    User-Agent头字段的信息:
    Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:46.0) Gecko/20100101 Firefox/46.0
    
    头名称:host
    头名称:user-agent
    头名称:accept
    头名称:accept-language
    头名称:accept-encoding
    头名称:referer
    头名称:connection

注意:referer头字段:浏览器通知服务器,当前请求来自何处。如果是直接访问,则不会有这个头。常用于:防盗链

2.3 获取请求体参数的相关方法

方法声明功能描述
String getParameter(String name)  获取指定名称的参数值。
  若没有指定名称的参数,返回null。
  若包含指定名称参数,但无值,返回空串。
  若包含多个指定名称的参数,返回第一个参数值。
String[] getParameterValues(String name)  获取同一个参数名的所有值(如复选框checkbox)
Map<String,String[]> getParameterMap()  将请求消息中的所有参数的名称和值装进一个Map对象中返回
Enumeration getParameternames()  返回一个包含请求消息中所有参数名的Enumeration对象

演示代码:

public class BodyServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
        //解决输出中文乱码
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		//单个获得用户名,密码和爱好
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String hobby = request.getParameter("hobby");
		out.println("用户名:"+username+",密码:"+password+",爱好:"+hobby+"<br/>");
		
		//获得爱好的所有值
		String[] hobbys = request.getParameterValues("hobby");
		out.print("爱好:");
		for(String hobbyOne : hobbys) {
			out.print(hobbyOne+" ");
		}
		out.println("<br/>");
		
		//获得所有的参数名字
		Enumeration<String> parameterNames = request.getParameterNames();
		out.print("所有参数名:");
		while(parameterNames.hasMoreElements()) {
			out.print(parameterNames.nextElement()+" ");
		}
		out.println("<br/>");
		
		//获得参数键值对的Map集合
		out.print("所有参数Map集合键值对:"+"<br/>");
		Map<String, String[]> map = request.getParameterMap();
		for(String key : map.keySet()) {
			for(String value : map.get(key)) {
				out.println(key+"="+value+"<br/>");
			}
		}
	}
    
	public void doPost(HttpServletRequest request, HttpServletResponse response) 
	throws ServletException, IOException {
		doGet(request, response);
	}
}

浏览器打印内容:
    用户名:wangba,密码:666,爱好:tennis
    爱好:tennis Pingpong
    所有参数名:username password hobby
    所有参数Map集合键值对:
    username=wangba
    password=666
    hobby=tennis
    hobby=Pingpong

在这里插入图片描述

注意:无论是get提交还是post提交上述方法都可以获取到参数名和对应的值。

2.4 获取中文参数乱码问题

​ 用户在页面输入的数据总会有中文,这些中文数据传递到服务端的时候,如果不做处理会出中文乱码的问题。一切出现乱码的问题都是因为字符集不一致引起的,用户在HTML页面输入的中文是由HTML设置的UTF-8码表编码的,而request对象使用的ISO-8859-1编码解码,所以会出现乱码现象。下面分两种情况解决中文乱码问题。

  • post提交方式的解决方法:

    • request.setcharacterEncoding(“UTF-8”),设置request对象的解码方式。
    • 注意:一定要放在第一次接收参数之前先设置解码的字符集,否则还是会乱码。
  • get提交方式的解决方法:

    • tomcat7及以前:username = new String(username.getBytes("ISO-8859-1"),"UTF-8");
    • tomcat8不用处理,因为tomcat8的request缓冲区的默认解码方式就是UTF-8。

3 Request的其他功能

3.1 Request是一个域对象

​ ​ 生命周期:

  • 创建:在一次请求开始。
  • 销毁:一次请求结束。
  • 作用范围:一次请求中。
方法声明功能描述
void setAttribute(String name,Object value)  将一个键值对存储到ServletRequest对象中
Object getAttribute(String name)  从ServletRequest对象中返回指定名称的属性
removeAttribute(String name)   从ServletRequest对象中删除指定名称的属性

注意:关于setAttribute(String name,Object value)方法

  • 如果ServletRequest对象中已经存在指定名称的属性,该方法会覆盖原来的属性值。
  • 如果传递给该方法的属性值对象为null,则删除指定名称的属性,此时效果等同于removeAttribute方法。

3.2 请求转发

​ ​ 当一个WEB资源收到客户端的请求后,如果希望服务器通知另外一个资源去处理请求,这时除了使用sendRedirect()方法实现请求重定向外,还可以通过RequestDispatcher接口的实例对象来实现。在ServletRequest接口中定义了一个获取RequestDispatcher对象的方法。
​ ​ ①getRequestDispatcher(String path):返回封装了某个路径所制定资源的RequestDispatcher对象。需要注意的是,WEB-INF目录中的内容对RequestDispatcher对象也是可见的,因此传递给该方法的资源也可以是WEB-INF目录中的文件。
​ ​ 获得RequestDispatcher对象后,最重要的工作就是通知其他WEB资源处理当前的Servlet请求。
​ ​ ②forward(ServletRequest request,ServletResponse response):用于将请求从一个Servlet传递给另外一个WEB资源。


请求转发流程示意图

代码演示:

/*
 *	请求转发的Servlet
 */
public class DispacherServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) 
	throws ServletException, IOException {
		
		request.setAttribute("school", "CTGU");
		request.getRequestDispatcher("/result").forward(request, response);	
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) 
	throws ServletException, IOException {
		doGet(request, response);
	}
}

package com.itheima.Dispatcher;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ResultServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) 
	throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");	
		String shoolName = (String)request.getAttribute("school");
		response.getWriter().print("这是请求转发的结果: "+shoolName);
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) 
	throws ServletException, IOException {
		doGet(request, response);
	}
}

注意:

​ 1、在目标资源中调用forward方法时,必须保证此响应没有提交。也就是不要使用 ServletResponse 对象的输出流对象,**因为即便你写入了数据到响应缓冲区,最后也会被清空,**如果缓冲区数据被刷新提交(out.flush),还会抛出IllegalStateException异常。

​ 2、对于forward方法传递的request对象:虽然我们从调用上看,好像是将request对象传递给转动的资源上去了,但是我发现目标资源使用的request对象和转发的资源使用的request对象不是同一个request对象,因为分别从这2个request中获取RequestURL,发现是不一样的。但是在目标资源request提取的Paramter和 Attribute,在转发后的资源的request对象中,依然都可以提取到,且是相同的。所以,二者只是在请求路径相关的属性上不同,其它API调用返回的都是一样的。

​ 3、在forward语句的前后,都不应该有响应输出的语句,应该会被忽略。

​ 4、同时使用请求转发和重定向会报错,Cannot call sendRedirect() after the response has been committed或Cannot forward after response has been committed。

3.3 请求转发和重定向的区别

转发是服务器行为,重定向是客户端行为;

  • 重定向的地址栏会发生变化,而转发的地址栏不会发生变化。
  • 重定向至少两次请求两次响应,请求转发一次请求一次响应。
  • 重定向的路径需要加工程的名字,而请求转发的路径不需要加工程名,但是必须以“/”开头。
  • 重定向可以跳转到任意网站,而转发只能在服务器内部进行转发。
  • 转发2次跳转之间传输的信息不会丢失,重定向2次跳转之间传输的信息会丢失(request域范围)。
  • 转发的性能优于重定向,因为转发是服务器内部行为。
  • 请求转发可以转发到普通的HTML、WEB-INF下面的资源、其他Servlet资源,而重定向不能重定向到WEB-INF下的资源,其他两个可以。

注意:请求转发是唯一可以访问WEB-INF的资源的方式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值