一、SpringMVC 使用 @PathVariable、@RequestParam、@RequestHeader、@CookieValue 等来解决参数获取问题。

1. @PathVariable:映射 URL 绑定的占位符,可以借助于传入到方法参数列表中的 @PathVariable 注解获取到 URL 映射中的参数值。如:

<a href="handler01/1">test pathvariable</a>
@RequestMapping("/handler01/{id}")
public String testPathVariable(@PathVariable("id") String id) {
  System.out.println("id:" + id);
  return "success";
}

说明:URL 绑定占位符使 SpringMVC 对 REST 提供了支持。对于具体的 SpringMVC 的 REST 风格的例子会在以后的文章里介绍。

2.@RequestParam 

官方文档是这样描述的:

* Annotation which indicates that a method parameter should be bound to a web
* request parameter. Supported for annotated handler methods in Servlet and
* Portlet environments.
*
* <p>If the method parameter type is {@link Map} and a request parameter name
* is specified, then the request parameter value is converted to a {@link Map}
* assuming an appropriate conversion strategy is available.
*
* <p>If the method parameter is {@link java.util.Map Map&lt;String, String&gt;} or
* {@link org.springframework.util.MultiValueMap MultiValueMap&lt;String, String&gt;}
* and a parameter name is not specified, then the map parameter is populated
* with all request parameter names and values.

说明一下:

(1)该注解表明 web 请求参数绑定到目标 handler 方法的入参。

(2)如果方法的入参类型是一个 Map,不包含泛型类型,并且请求参数名称是被指定的

(如:public String testRequestParam5(@RequestParam("userName") Map map)),请求参数会被转换为一个 Map,前提是存在转换策略。

这里所说的转换策略,通常是指 请求参数 到 Map 的类型转换,如请求参数为 userName=a|12,b|34 这样的数据,需要通过一个转换策略(类型转换器)

来完成 a|12,b|34 到 map 的转换。在我们一般开发的过程中,不包含这种情况。是一种扩展。关于类型转换会在后面的文章中介绍。

(3)如果方法的入参是一个 Map 且指定了泛型类型 Map<String,String> 或者是 org.springframework.util.MultiValueMap 类型的 MultiValueMap<String, String>

并且没有指定请求参数,那么这个 Map 类型的参数会将所有的请求参数名称和值填充(populate)到其中。

如:

请求:<a href="testRequestParam4?userName=jack&age=23">test request param4</a>

handler 方法:

@RequestMapping("/testRequestParam4")
public String testRequestParam4(@RequestParam Map<String, String> map) {
  System.out.println("map:" + map);
  return "success";
}

控制台输出:

map:{userName=jack, age=23}

上面整体介绍了 @RequestParam,下面详细看看它的API:

包含三个属性:

(1)value 属性,默认为 ""

官方文档说明:

The name of the request parameter to bind to.

解释的已经很明白了,不再赘述。

(2)required 属性,默认为 true

官方文档说明:Whether the parameter is required.

见名知意,该请求参数是否是必须的。为 true 的请求下,若请求参数中没有,则会抛出一个异常。为 false 的情况下,如果请求参数中没有,则方法入参对应值为 null。

另外,提供一个 defaultValue 属性,则会是此属性设置为 false。

(3)defaultValue 属性

当没有提供对应的请求参数,或者请求参数为空时,会使用此属性对应的值。当设置此属性的时候,会将 required 属性设置为 false。

下面提供几个常见请求情况的例子:

(1)请求为:<a href="testRequestParam?userName=abc">test request param</a>

handler 方法:

@RequestMapping("/testRequestParam")
public String testRequstParam01(@RequestParam("userName") String userName) {
  System.out.println("userName: " + userName);  return "success";
}

(2)请求为:<a href="testRequestParam2?userName=jack&userName=lucy">test request param2</a>

handler 方法:

@RequestMapping("/testRequestParam2")
public String testRequestParam02(@RequestParam("userName") List<String> userNames) {
  System.out.println("userNames:" + userNames);
  return "success";
}

控制台输出:

userNames:[jack, lucy]

(3)请求为:<a href="testRequestParam4?userName=jack&age=23">test request param4</a>

handler 方法:

@RequestMapping("/testRequestParam4")
public String testRequestParam4(@RequestParam Map<String, String> map) {
  System.out.println("map:" + map);
  return "success";
}

控制台输出:

map:{userName=jack, age=23}

主要就分为这三种情况,其中第一种最为常用,第二种和第三种很少能想到,若能想到的话,能为我们开发节省不少时间。

3.@RequestHeader

官方文档中是这样描述的:

Annotation which indicates that a method parameter should be bound to a web request header.
Supported for annotated handler methods in Servlet and Portlet environments.

和 @RequestParam 描述类似,只不过绑定的是 web 请求头信息到方法入参。

定义的三个属性和 @RequestParam 一样,默认值和使用的方法也一样。由于用的比较少,这里只做一个例子说明:

请求:<a href="testRequestHeader">test request header</a>

handler 方法:

@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept", required = false) String accept) {
  System.out.println("accept:" + accept);
  return "success";
}

控制台输出:

accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

4.@CookieValue

官方文档描述:

Annotation which indicates that a method parameter should be bound to an HTTP cookie.
Supported for annotated handler methods in Servlet and Portlet environments.

绑定一个 http cookie 到方法的入参,其中 value 属性表明要入参的 cookie 的 key。

默认值和使用方式和 @RequestParam 类似。

例子:

请求:<a href="testCookieValue">test cookie value</a>

handler 方法:

@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue(value = "JSESSIONID", required = false) String sessionId) {
  System.out.println("sessionId:"+sessionId);
  return "success";
}

控制台输出:

sessionId:9D16BDF7063E1BFD9A0C052F1B109A0D

5.绑定请求参数到方法入参处的 bean 对象。

先看两个例子:

(1)绑定请求参数到 bean

请求:包括 get 和 post 请求方式提交的情况。

<a href="testBean?personName=jack&age=23">test bean</a>
<form action="testBean" method="post">
  <label>
    personName:<input type="text" name="personName"/>
  </label>
  <label>
    age:<input type="text" name="age"/>
  </label>
  <input type="submit" value="submit"/>
</form>

handler 方法:

@RequestMapping("/testBean")
public String testBean(Person person) {
  System.out.println(person);//Person{personName='jack', age='23'}
  return "success";
}

发现不论是通过 get 方式,还是post 方式,都可以将对应的请求参数注入到对应的 bean 中。

(2)绑定请求参数到级联的 bean

bean 的结构:

/**
* @author solverpeng
* @create 2016-08-04-9:43
*/
public class Employee {
private String empName;
private Address address; public String getEmpName() {
return empName;
} public void setEmpName(String empName) {
this.empName = empName;
} public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
} @Override
public String toString() {
return "Employee{" +
"empName='" + empName + '\'' +
", address=" + address +
'}';
}
}

Employee

/**
* @author solverpeng
* @create 2016-08-04-9:43
*/
public class Address {
private String addressName; public String getAddressName() {
return addressName;
} public void setAddressName(String addressName) {
this.addressName = addressName;
} @Override
public String toString() {
return "Address{" +
"addressName='" + addressName + '\'' +
'}';
}
}

Address

请求:同样包含 get 请求 和 post 请求

<a href="testBeanCascade?empName=jack&address.addressName=beijing">test bean cascade</a>

<form action="testBeanCascade" method="post">
<label>
empName:<input type="text" name="empName"/>
</label>
<label>
Address:<input type="text" name="address.addressName"/>
</label>
<input type="submit" value="submit"/>
</form>

handler 方法:

@RequestMapping("/testBeanCascade")
public String testBeanCascade(Employee employee) {
  System.out.println(employee);//Employee{empName='jack', address=Address{addressName='beijing'}}
  return "success";
}

是如何绑定的呢?翻源码过程如下:

org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#invokeHandlerMethod

ExtendedModelMap implicitModel = new BindingAwareModelMap();
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);

第一步:发现在 result 中已经包含了注入的 bean。所以注入是在methodInvoker.invokeHandlerMethod() 方法中做的。

第二步:org.springframework.web.bind.annotation.support.HandlerMethodInvoker#invokeHandlerMethod
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);

第三步:org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolveHandlerArguments
doBind(binder, webRequest, validate, validationHints, !assignBindingResult);// 这里进行的绑定

第四步:org.springframework.web.bind.ServletRequestDataBinder#bind
doBind(mpvs);

第五步:org.springframework.validation.DataBinder#doBind
this.applyPropertyValues(mpvs);

最终发现,是在 DataBinder 这个类的 doBind() 方法中进行的绑定。在翻源码的过程中,发现 resolveHandlerArguments() 方法值得大家看一看,不论水平高低,

其实真正解决 SpringMVC 参数问题就是在这个方法中解决的。

总结一下:Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。

二、SpringMVC 解决 Servlet 资源获取问题

1. SpringMVC 使用 Servlet 资源作为方法的入参来解决 Servlet 资源获取问题。

2.可以作为入参的 Servlet 资源有:HttpServletRequest、HttpServletResponse、HttpSession、Locale、InputStream、OutputStream、Reader、Writer

3.例子:

使用 HttpServletRequest 作为入参

请求:<a href="testServletAPI">test servlet api</a>

handler 方法:

@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request) {
  String id = request.getSession().getId();
  System.out.println("sessionId:" + id);
  return "success";
}

控制台输出:

sessionId:E369037AF3DC276BA78539F0AF5C044B

其他的 Servlet 资源这里就不在赘述。

三、总结

SpringMVC 使用 @PathVariable 来获取 @RequestMapping 中占位符的值,为 REST 风格的程序的编写提供了支持。使用 @RequestParam 能接收绝大部分请求参数,同时提供了类型

转换这种扩展。使用 @RequestHeader 来映射请求头信息。使用 @CookieValue 来映射 http cookie 信息。同时还支持模型的注入。也可以获取到原生的 servlet 资源。即在目标的方法处,

我们可以获取到任何我们想要的资源,SpringMVC 对这个过程进行了简化,使开发更加便捷,灵活。

SpringMVC核心——参数获取与Servlet资源获取问题的更多相关文章

  1. 传值:web.xml传递参数 即在Servlet中获取web.xml里的值

    传值:web.xml传递参数 在web.xml中的Servlet里配置多个init-param <servlet> ... <init-param> <param-nam ...

  2. Javaweb学习笔记——(九)——————Servlet的进入,及ServletConfig、GenericServlet、HttpServlet、ServletContext、获取类路径资源

    Servlet1.什么是Servlet? *Servlet是Javaweb三大组件之一(Servlet,Filter,Listener) *Servlet是用来处理客户端请求的动态资源 *Servle ...

  3. springMVC(spring)+WebSocket案例(获取请求参数)

    开发环境(最低版本):spring 4.0+java7+tomcat7.0.47+sockjs 前端页面要引入: <script src="http://cdn.jsdelivr.ne ...

  4. servlet中获取配置文件中的参数.

    web.xml (添加init-param) <?xml version="1.0" encoding="UTF-8"?> <web-app ...

  5. SpringMVC请求参数的获取方式

    一.GET请求参数获取 1. 通过HttpServletRequest获取参数 2. 直接方法参数获取 3. RequestParam注解方式获取请求参数 4. Bean方式获取参数 5. Model ...

  6. springmvc请求参数获取的几种方法

    1.直接把表单的参数写在Controller相应的方法的形参中,适用于get方式提交,不适用于post方式提交. /** * 1.直接把表单的参数写在Controller相应的方法的形参中 * @pa ...

  7. springmvc请求参数获取(自动绑定)的几种方法

    1.直接把表单的参数写在Controller相应的方法的形参中,适用于get方式提交,不适用于post方式提交. /** * 1.直接把表单的参数写在Controller相应的方法的形参中 * @pa ...

  8. web.xml中在Servlet中获取context-param和init-param内的参数

    引自:http://blog.csdn.net/yakson/article/details/9203231 web.xml里面可以定义两种参数:1.application范围内的参数,存放在serv ...

  9. servlet自动获取前端页面提交数据

    servlet自动获取前端页面jsp提交数据 以下是本人在学习过程中,因前端页面提交参数过多,后台servlet封装实体类过于麻烦而写的一个工具类,应用于jsp/servlet数据提交后,基于MVC+ ...

随机推荐

  1. 完美解决 向UILable 文字最后插入N张图片,支持向限制行数的UILable 最后一行插入,多余文字显示...

    效果: ====直接上代码吧=== // // UILabel+StringFrame.h // QYER // // Created by qyer on 15/3/19. // Copyright ...

  2. 传统认知PK网络认知 刚子扯谈烤串认知

    文/刚子 2013.7.23 提到认知,有太多的介绍,我就不在秀理论文字了,那样等于自我抄袭式的传播给大家,对于大家也没意思,可以推荐大家到百度里面搜索下”认知结构”,介绍的比我详细.同行老陈说的! ...

  3. C++ 虚函数在基类与派生类对象间的表现及其分析

    近来看了侯捷的<深入浅出MFC>,读到C++重要性质中的虚函数与多态那部分内容时,顿时有了疑惑.因为书中说了这么一句:使用“基类之指针”指向“派生类之对象”,由该指针只能调用基类所定义的函 ...

  4. JAVA自动化测试数据设计

    数据管理是很重要的,数据管理与方法一样,依然是有层次的,我们在测试的过程中,可能会有多个环境,每个环境的URL啊,登录名啊,数据库连接地址啊等等不一样,我们可以把这些环境每个都配置一个数据文件,里面写 ...

  5. 【C++沉思录】代理类

    1.考虑下面的场景:设计一个容器,包含一组类型不同但相互关联的对象(比如:Animal,Dog,Cat),对象具备多态行为.2.容器一般只能包含一种类型的对象,使用vector<Animal&g ...

  6. goldengate一些参数整理

    转自:http://blog.csdn.net/lemontree1123/article/details/46603549 manager参数: AUTOSTART:指定在mgr启动时自动启动那些进 ...

  7. mahout分类学习和遇到的问题总结

    这段时间学习Mahout有喜有悲.在这里首先感谢樊哲老师的指导.以下列出关于这次Mahout分类的学习和遇到的问题,还请大家多多提出建议:(全部文件操作都使用是在hdfs上边进行的). (本人用的环境 ...

  8. LeetCode: Remove Nth Node From End of List 解题报告

    Remove Nth Node From End of List Total Accepted: 46720 Total Submissions: 168596My Submissions Quest ...

  9. Android 基于Message的进程间通信 Messenger完全解析

    一.概述 说到Android进程间通信,大家肯定能想到的是编写aidl文件,然后通过aapt生成的类方便的完成服务端,以及客户端代码的编写.如果你对这个过程不熟悉,可以查看Android aidl B ...

  10. 增加Xss过滤步骤

    1.往项目web.xml中增加以下的代码: <!-- xss param过滤开始 bgy 2014-12-25 --> <filter>  <filter-name> ...