关于Request与Response,你所必须掌握的,都在这儿了

关于Request与Response,你所必须掌握的,都在这儿了

本文承接自

Servlet概念-原理-操作[Java-web]

在学习Request和Response之前,你最好先学习Servlet

doGet与doPost

Request请求可以分为Get与Post(最常见)

可以把 get 和 post 当作两个不同的行为,两者并没有什么本质区别,底层都是 TCP 连接

get请求用来从服务器上获得资源,而post是用来向服务器提交数据

在前端html文件中,Form标签里的method的属性为get时调用doGet(),为post时调用doPost()

相对路径与绝对路径

相对路径访问servlet

这是配置文件中的servlet:

<servlet-mapping>
    <servlet-name>HelloWorld</servlet-name>
    <url-pattern>/HELLO</url-pattern>
</servlet-mapping>

在html文件中:以相对路径定义跳转路径

<a href="./HELLO">点击访问Servlet</a>
  • 超链接设置为 ./HELLO 代表上一级目录下的HELLO 同理,…/代表退两层

启动Tomcat,访问http://localhost:8081/can.html

点击访问该超链接,路径跳转成功

绝对路径访问Servlet

直接跟浏览器地址栏对应,没什么好说的

<a href="http://localhost:8081/HELLO">点击访问Servlet</a>

缺点:

ip与端口写死了,一旦ip与端口改动,超链接失效该方式不建议使用

Tomcat请求响应流程

Web服务器收到客户端的http请求,会针对每一次请求,分别**创建一个用于代表请求的request对象、和代表响应的response对象

我们要获取客户机提交过来的数据,只需要找request对象就行了。要向客户机输出数据,只需要找response对象就行了

HttpServletRequest基本功能

ttpServletRequest在JavaWeb中非常重要的一个。它是Servlet的service()方法的参数之一!所以你必须必须要掌握它!

request的功能可以分为以下几种:

  • 封装了请求头数据

  • 封装了请求正文数据,如果是GET请求,那么就没有正文

  • request是一个域对象,可以把它当成Map来添加获取数据

  • 做请求的转发

获取请求头数据:

String value = request.getHeader("请求头名称")

quest对象可以用来获取请求头数据,当然,这些请求数据都是Tomcat封装到request中去的。我们在service()方法中可以直接来获取相关的方法

其他:

request中还提供了与请求相关的其他方法,有些方法是为了我们更加便捷的方法请求头数据而设计,有些是与请求URL相关的方法

  • int getContentLength():获取请求正文的字节数,GET请求没有正文,没有正文返回-1

  • String getContentType():获取请求类型,如果请求是GET,那么这个方法返回null;如果是POST请求,那么默认为application/x-www-form-urlencoded(理解为字符串类型),其它类型以后再学;

  • String getMethod():返回请求方法,例如:GET

  • Locale getLocale():返回当前客户端浏览器支持的Locale。java.util.Locale表示国家和言语,这个东西在国际化中很有用

  • String getCharacterEncoding():获取请求编码,如果没有setCharacterEncoding(),那么返回null。表示使用ISO-8859-1编码

  • void setCharacterEncoding(String code):设置请求编码,只对正文有效!注意,对于GET而言,没有正文!!!所以此方法只能对POST请求中的参数有效

  • String getContextPath():返回项目路径,例如:/项目名称

  • String getQueryString():返回请求URL中的参数,例如:name=zhangSan

  • String getRequestURI():返回要请求URI路径,例如:/hello/oneServlet

  • String getServletPath():返回Servlet路径,例如:/oneServlet

  • String getSchema():返回请求协议,例如:http

  • String getServerName():返回主机名,例如:localhost

  • int getServerPort():返回服务器端口号,例如:80

  • int getRemotePort():返回客户端的端口号,每次请求都会变

对于一个url,我们可以获取它的全部信息

HttpServletRequest参数问题

获取参数

可以使用HttpServletRequest获取客户端的请求参数,相关方法如下:

String getParameter(String name):通过指定名称获取参数值

String[] getParameterValues(String name):通过指定名称获取参数值数组,有可能一个名字对应多个值,例如表单中的多个复选框使用相同的name时;

Enumeration getParameterNames():获取所有参数的名字,返回值是枚举类型;

Map getParameterMap():获取所有参数对应的Map,其中key为参数名,value为参数值。

传递参数

GET请求传参:

  • 地址栏中直接给出参数:http://localhost/param/ParamServlet?p1=v1&p2=v2;

  • 超链接中给出参数:<a href=” http://localhost/param/ParamServlet?p1=v1&p2=v2”>???</a>

  • 表单中给出参数:<form method="GET" action="ParamServlet">…</form>

Ajax传参待补充

POST:

表单中给出参数:<form method="POST" action="ParamServlet">…</form>

接收前端参数

单值参数接收:

单值参数包括单选,单值下拉框,文本,隐藏域

无论是GET还是POST,获取参数的方法是相同的

String s1 = request.getParameter(“p1”);//返回v1

前端html文件通过标签属性,指定参数的key,后端通过key获取参数的值

图示:

多值参数接收:

多值参数主要就是表单的多选checkbox

例如在注册表单中,如果让用户填写爱好,那么爱好可能就是多个,那么hobby参数就会对应多个值:

request.getParameterMap()方法返回Map类型,对应所有参数,其中Map的key对应参数的名字;Map的value对应参数的值

示例:

<form action="ParamServlet" method="post">
		姓名:<input type="text" name="name"/><br/>
		年龄:<input type="text" name="age"/><br/>
		性别:<input type="text" name="sex"/><br/>
    	<input type="submit" value="提交"/><br/>
    </form>
		Map<String,String[]> map = request.getParameterMap();
		Set<String> keys = map.keySet();//获得所有键
		for(String key : keys) {
			String[] value = map.get(key);//由键拿值
			System.out.println(key + " = " + value[0]);
		}
sex = male
name = zhangSan
age = 23

图解:

其实当参数的值是单个的时候,同样可以使用request.getParameterValues(String)方法来获取参数值,不过这个参数返回的值为String[],这时我们需要再去获取数组下标0的元素

String name = request.getParameterValues(“name”)[0];

补充:

request.getAttribute()和 request.getParameter()有何区别:
从获取方向来看:

  • getParameter()是获取 POST/GET 传递的参数值;
  • getAttribute()是获取对象容器中的数据值;

从用途来看:

  • getParameter()用于客户端重定向时,即点击了链接或提交按扭时传值用,即用于在用表单或url重定向传值时接收数据用。

关于重定向与转发的区别,在下面有说到

  • getAttribute() 用于服务器端重定向时,即在 sevlet 中使用了 forward 函数,或 struts 中使用了 mapping.findForward。 getAttribute 只能收到程序用 setAttribute 传过来的值。
  • 可以用 setAttribute(),getAttribute() 发送接收对象.而 getParameter() 显然只能传字符串

从内存角度来看:
setAttribute() 是应用服务器把这个对象放在该页面所对应的一块内存中去,当你的页面服务器重定向到另一个页面时,应用服务器会把这块内存拷贝另一个页面所对应的内存中。这样getAttribute()就能取得你所设下的值,当然这种方法可以传对象。session也一样,只是对象在内存中的生命周期不一样而已。getParameter()只是应用服务器在分析你送上来的 request页面的文本时,取得你设在表单或 url 重定向时的值

Request请求中文乱码问题[选读]

我们在做项目时会全站都采用统一的编码,最常用的就是UTF-8,也就是说request请求所带的参数是utf-8编码的

Post乱码问题

我们知道,请求信息中,只有POST存在正文,所谓POST参数编码就是就是请求正文的编码。

默认情况下,使用getParameter()获取POST请求参数时,使用的是ISO-8859-1编码,而我们请求是统一设置称UTF-8的,故在获取参数时已经被错误的编码了

解决办法一:

使用ISO-8859-1获取字节数组,然后再使用正确的UTF-8编码得到字符串,这样就没问题了

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getOutputStream().write(" doPost方法被调用".getBytes());
        String name = req.getParameter("name");
        name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
        System.out.println(name);
    }

但这种方式相当不优雅!

解决方法二:

对请求对象request转换编码

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getOutputStream().write(" doPost方法被调用".getBytes());
        req.setCharacterEncoding("UTF-8");
        String name = req.getParameter("name");

        System.out.println(name);
    }

比第一种好看多了

request的setCharacterEncodng()可以设置编码,当然这必须在调用所有的getParameter()方法之前调用request的setCharacterEncodng()方法来设置编码,这样,就不会使用ISO解读字节串了,而是使用你给定的编码来解读。

对于每个请求,只需要调用request的setCharacterEncodng()一次,然后所有getParameter()都会使用这个编码来解读参数。但要注意,只对请求正文有效,即POST参数。

Get乱码问题

第一种方式:

采用字符串转码的方式来处理

	String s = request.getParameter(“s”);

	s = new String(s.getBytes(“iso-8859-1), “utf-8);

第二种方式:

设置< Connector>元素的URIEncoding属性的值为UTF-8。即conf\server.xml中的< Connector>元素的URIEncoding属性

一旦设置了这个属性,那么对于GET参数就直接是UTF-8编码的了。但是,< Connector>元素来说,对整个Tomcat都是有效的

注意:GET参数不在请求正文中,而是在URL中。所以不能使用request的setCharacterEncodng()来设置GET参数的编码

第三种方式:

依赖于JS,对GET请求中的参数使用JavaScript做URL编码,URL编码后的内容就不再是中文了,这样也就不会丢失字节(乱码)了

由于全栈设置了编码,故encodeURI会把url设置称UTF-8

<a href="#" onclick="click1()">ff</a>
<script type="text/javascript">
function click1(){
	var path = encodeURI(encodeURI("/servlet?namea=悟空"));
	location.href = path;
}
</script>
String val = request.getParameter("namea");
		val = URLDecoder.decode(val, "UTF-8");
		System.out.println(val);

请求转发

在Servlet中请求转发是大量要使用的,因为当我们访问一个Servlet的时候通常会执行一些后台的业务逻辑,然后跳转到一个结果页面,那么跳转到结果页面的这个过程就是请求转发

举个例子:我们做登录的功能,我们填写用户名密码然后提交到一个负责登录的Servlet,Servlet为我们做用户名和密码的校验,如果我们都正确的话,我们就要跳转到登录的提示页面,如果错误就要跳转到登录失败的页面

Request的请求转发也可以叫做服务器端的跳转虽然有页面的跳转但是我们会发现地址栏是不会有变化的

代码:

request.getRequestDispatcher("/success.html").forward(request, response);

Request域的作用范围

回顾:ServletContext是一个域的对象,它的范围非常大,是指定项目所有Servlet的公共的对象,随着服务器的启动而产生,服务器的停止而销毁

request的也是域对象,它的作用范围小的多,它的范围只在一次请求响应范围之内,每一个线程的请求都会新产生一个HttpServletRequest和HttpServletResponse的对象

HttpServletResponse基本功能[选读]

response对象的功能分为以下四种:

  • 设置响应头信息;addHeader(“reFresh”, “5;URL=xxxx”);

  • 发送状态码;sendError(404);

  • 设置响应正文;getWriter().print(“aaa”);

  • 重定向:sendRedirect(“path”);

    重定向不同于上面说的请求转发,它的地址栏是会变的!

转发与重定向的异同

读到这,我们自然会想去了解转发与重定向有何区别
转发是服务器行为,重定向是客户端行为
这很好解释,转发是request对象的特性,重定向是response的特性,response传给客户端的对象,自然是客户端行为
再研究深一点:
重定向(Redirect) 是利用服务器返回的状态码来实现的。客户端浏览器请求服务器的时候,服务器会返回一个状态码。服务器通过 HttpServletResponse 的 setStatus(int status) 方法设置状态码。如果服务器返回301或者302,则浏览器会到新的网址重新请求该资源

请求与转发有以下具体区别:

  • forward:转发页面和转发到的页面可以共享request里面的数据. redirect:不能共享数据.
  • forward:一般用于用户登陆的时候,根据角色转发到相应的模块. redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
  • forward:效率高. redirect:效率低.
    其他方法:
  • response.setContentType("text/html;charset=utf-8"):设置响应类型为html,编码为utf-8,处理相应页面文本显示的乱码

  • response.setCharacterEncoding(“utf-8”):如果响应类型为文本,那么就需要设置文本的编码类型,然后浏览器使用这个编码来解读文本。注意,如果没有设置contentType,那么浏览器会认为contentType为text/html,如果没设置编码,那么默认为ISO-8859-1编码。所以以上两点在使用response返回结果之前必须设置

  • response.setHeader(“contentType”, “text/html;charset=utf-8”):setContentType()方法的功能相同。setContentType()方法属于便捷方法

  • response.setHeader("Refresh","5; URL=http://www.baidu.com"):5秒后自动跳转到百度主页

原创文章 197 获赞 142 访问量 6万+

猜你喜欢

转载自blog.csdn.net/JunSIrhl/article/details/105743900