【小家Java】Servlet规范之---请求(request):Servlet中如何获取POST请求参数?(使用getParameter())

简介: 【小家Java】Servlet规范之---请求(request):Servlet中如何获取POST请求参数?(使用getParameter())

前言


request对象封装了来自客户端的所有请求信息。在HTTP协议中,客户端发给服务端的所有信息都是通过request对象的请求头和请求体来传送的。


Servlet请求参数


servlet的请求参数作为客户端请求的一部分都是以字符串形式传给servlet容器。


参数以键值对方式存储,而且一个参数名可以对应多个参数值。ServletRequest接口的以下4个方法用于访问这些参数信息:


  • getParameter:返回getParameterValues结果的第一个值
  • getParameterNames
  • getParameterValues:查询一个参数名对应的所有参数值,然后以String数组返回
  • getParameterMap:以Map方式返回所有的请求参数,当然,这个Map以参数名为key,参数值为对应的value


从query字串**和post提交的请求体(是有规范约束的,下面介绍)获得的所有请求数据都会包装进请求参数集合(这是个重要概念,可以理解成一个Map)**中。query字串的数据优先性要高于post提交的数据。


简答的说URL里能够get到就以它的为准,若没有再去看~


Servlet参数可用性(POST请求规范)


我们大多数情况下的一个通识:post方式请求,body体里的内容我们是无法使用getParameter等方式去获取参数的。


But可能你只知其一,不知其二。其实如果你的POST请求符合下面4个先决条件,也是能够使用getParameter()


  1. HTTP请求或者是HTTPS请求。
  2. HTTP的请求方法为POST方式。(不支持PUT)
  3. 内容类型是application/x-www-form-urlencoded。
  4. Servlet上可使用getParameter系列方法了


备注:Servlet规范只约束了POST请求,对于PUT、HEAD等请求方式,它是没有办法的处理的


Demo Show:

先写个Servlet:

@WebServlet(urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String hello = req.getParameter("hello");
        System.out.println(hello);
    }
}


GET请求:http://localhost:8080/demo_war_war/hello?hello=world。毫无疑问可以正常的获取到值world。


get请求可以通过request.getQueryString()获取url后面的字符串。


现在我们来一个POST请求,用POSTMAN模拟请求:

URL:http://localhost:8080/demo_war_war/hello

Headers:


image.png


这样我们虽然参数是写进body体,但是还是使用req.getParameter("hello")把world获取出来。


这就是Servlet规范,它只作于POST请求~

若POST请求不是application/x-www-form-urlencoded,怎么获取body体的内容呢?


下面以我们最常见的application/json为例。


image.png


若还是使用req.getParameter("hello"),拿得到的结果是null。那怎么破呢?


那就只能这样子了:getInputStream() 它的作用官方有说明:Retrieves the body of the request as binary data,因此我们只需要把这个流读出来成为字符串,就OK啦~~


IOUtils.toString(request.getInputStream())


/当然你在Spring环境,还可以使用StreamUtils、FileCopyUtils来代替对common-io包的依赖~


这样我们就能拿到请求的字符串,若是个Json格式的串,就可以转换为对象了。这也是Spring MVC中@RequestBody的基本原理


备注:请注意流都是只能读一次的,避免冲虚读取~~


PUT请求可以像POST这样使用规范吗?


显然Servlet默认是只支持POST请求参数的,若是PUT源生的它是不支持的。


如果你使用的是Spring MVC,并且版本号是5.1.x.RELAESE或以上版本,福利就有了。它给我们提供了一个FormContentFilter,它能帮我处理这种情况下的PUT请求(其实还有PATCH和DELETE请求),比如如下我使用PUT请求:


image.png


并且加上此过滤器(此处,因为我是注解驱动的Web应用,所以用编程的方式添加Filter):

servletContext.addFilter("formContentFilter", new FormContentFilter()).addMappingForUrlPatte


**完美。**我们依然可以使用req.getParameter("hello")拿到world这个值啦~~~ 这是强大的Spring MVC 5.1之后的版本赋予我们的能力~


Attribute属性


不同于请求你参数Parameter,它一般用于多个servlet之间相互沟通交流数据


  • getAttribute
  • getAttributeNames
  • setAttribute:设置属性值~


一个属性名只能对应一个属性值。


以“java.”和“javax.”开头的属性名已经预留给Servlet规范本身。同样的,“sun.”和“com.sun”也已经预留给Sun微系统公司。 命名方式可参考Spring的命名方式~~~


Servlet与请求路径相关的元素


请求路径由多段重要信息组合而成。以下元素有请求的URI获得并由request对象展示:


  • Context Path:**和ServletContext关联的路径前缀。**如果应用的上下文是Web服务URL命名空间的默认上下文,那么Context Path就是空的。否则,它就以斜杠“/”开始开始的。
  • Servlet Path:这段路径对应着处理请求的映射路径,它始于斜杠“/”。如果请求匹配于“/*”规则,那么这时的Servlet Path会是空字串。
  • PathInfo:这段既不是Context Path的一部分,也不是Servlet Path的一部分。它要么为空,要么就是以斜杠“/”作为前导字符的一段字符串


HttpServletRequest下述3个方法用于访问这些信息:


  1. getContextPath
  2. getServletPath
  3. getPathInfo


如上面例子结果为:


System.out.println(req.getContextPath()); //  /demo_war_war
System.out.println(req.getServletPath()); //  /hello
System.out.println(req.getPathInfo()); // null


requesetURI = contextPath + servletPath + pathInfo。 这是个恒等式(除非请求的URI和路径部分的编码不同)


其它相关规范


相对来说不是非常重要的了,提一句即可


  • 路径转换的方法:ServletContext.getRealPath:获取真实路径
  • Cookies:getCookies方法去获取请求对象的cookies数组
  • SSL属性: HTTPS等安全协议
  • 国际化:getLocale(返回客户端更喜欢使用的locale) getLocales
  • 请求数据的编码:当下很多浏览器都并不指定编码格式(默认都是ISO-8859-1),由服务程序自动决定读取请求数据时的编码方法。 getCharacterEncoding:用于获取客户端显示指定的编码,一般都是null
  • 请求对象的生命周期:每个request请求对象只在当前servlet的service方法域内可用,或者是在filter的doFilter方法域内可用。


还有个Servlet的规范,在这里也说了:


在servlet-2.3中,Filter会过滤一切请求,包括服务器内部使用forward转发请求和<%@ include file="/index.jsp"%>的情况

到了servlet-2.4中Filter默认下只拦截外部提交的请求,forward和include这些内部转发都不会被过滤(更别谈SpringMVC的拦截器了,更不会被拦截喽~)。当然你若想让你的Filter拦截到所有,你需要显示的做如下配置:


<filter>  
    <filter-name>myFilter</filtername>  
    <filter-class>xxx.MyFilter</filter-class>  
</filter>  
<filter-mapping>  
    <filter-name>myFilter</filtername>  
    <url-pattern>/*</url-pattern>  
  <!-- 拦截模式,不写默认只有REQUEST:只拦截外部的请求 -->
    <dispatcher>REQUEST</dispatcher>  
    <dispatcher>FORWARD</dispatcher>  
    <dispatcher>INCLUDE</dispatcher>  
    <dispatcher>EXCEPTION</dispatcher>  
</filter-mapping>  


总结


上面说的对POST请求的这个规范是Servlet 2.4就已经出来了,在微服务大行其道的今天,大都是前后端完全分离的架构设计。前后端通讯基本采用更加轻量级的JSON格式,所以他们的Config-type一般都是application/json方式,自然而然就不符合Servlet规范了~


另外其实我们也能感觉到,随着Spring5.0的发布,Servlet的地位已经被撼动了。相信在不久的将来,它将成为历史。但是技术都能触类旁通的,技多不压身~~

相关文章
|
1月前
|
缓存 算法 Java
【Java引用规范】强软引用
本文详细介绍了Java中引用的概念和作用,包括强引用、软引用、弱引用和虚引用,并探讨了不同引用类型在内存管理和垃圾回收中的特性与用途。强引用是最常见的引用类型,对象只要被引用就不会被垃圾回收;软引用适用于内存敏感的缓存场景,在内存不足时会被回收;弱引用在更早的垃圾回收阶段被清除;虚引用主要用于对象的finalize过程。文章通过示例代码和内存分析工具展示了软引用的具体应用和回收机制。
【Java引用规范】强软引用
|
22天前
|
JSON 前端开发 JavaScript
java中post请求调用下载文件接口浏览器未弹窗而是返回一堆json,为啥
客户端调接口需要返回另存为弹窗,下载文件,但是遇到的问题是接口调用成功且不报错,浏览器F12查看居然返回一堆json,而没有另存为弹窗; > 正确的效果应该是:接口调用成功且浏览器F12不返回任何json,而是弹窗另存为窗口,直接保存文件即可。
55 2
|
4天前
|
Java 编译器 Android开发
java作业的提交规范与要求
java作业的提交规范与要求
9 0
|
1月前
|
Java API 开发者
Java 注释规范
Java中的注释规范包括单行注释(`//`)、多行注释(`/* ... */`)和文档注释(`/** ... */`)。单行注释适用于简短说明,多行注释用于较长描述,文档注释则专为自动生成API文档设计。注释应清晰明了、及时更新,避免冗余,并详细说明参数和返回值。遵循这些规范有助于提高代码的可读性和可维护性。
|
2月前
|
Java
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
|
2月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
|
2月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决
|
2月前
|
Java 开发者
Java 编程风格与规范:跟上时代热点,打造高质量代码,为开发者梦想保驾护航
【8月更文挑战第30天】本文强调了Java编程中代码质量和可维护性的重要性,详细介绍了命名规范、代码格式和注释的最佳实践,如使用描述性的命名、适当的缩进及空行,以及关键代码部分的注释说明,同时还提供了避免魔法值和减少代码重复的建议与示例,帮助提升团队协作效率和项目长期发展。
43 2
|
2月前
|
Java
编写规范JAVA代码
本文档制定了Java编程规范,旨在确保系统源程序的可读性和可维护性,适用于所有Java开发、测试及维护过程。规范包括命名规则(如Package、Class及其成员等)与样式规定,强调统一风格以提高协作效率,并列举了具体示例与注意事项,如避免单字符变量名及使用有意义的反义词组命名等。
44 1
|
2月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决