在代码开发过程中,参数的定义非常重要,目前springmvc提供的较多的参数获取方式,譬如 @PathVariable 和 @RequestParam,
或者通过增加如下注解
<mvc:annotation-driven> </mvc:annotation-driven>
mvc:annotation-driven默认增加了MappingJackson2HttpMessageConverter,可以将传递进来的body体解析成对应的JAVA对象。
但是存入如下问题
1、@PathVariable 和 @RequestParam只能解析基础的Java格式,int string boolean等,
2、MappingJackson2HttpMessageConverter只能将对象转变为一个JAVA Bean,
如果我们有两个java bean 定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public
class
Student {
private
String name;
private
int
year;
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
int
getYear() {
return
year;
}
public
void
setYear(
int
year) {
this
.year = year;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
class
Info {
private
String city;
private
String address;
public
String getCity() {
return
city;
}
public
void
setCity(String city) {
this
.city = city;
}
public
String getAddress() {
return
address;
}
public
void
setAddress(String address) {
this
.address = address;
}
}
|
如果我们定义了一个接口,需要传递这两个对象信息,采用MappingJackson2HttpMessageConverter就会比较麻烦。
这里讲解一个如何实现同时传递多个对象的方法,我们最终定义的接口如下
public Student addstudentpost(@JsonObject Student student,@JsonObject Info info)
原理是实现我们自定义的HandlerMethodArgumentResolver,并且插入到springMvc的参数解析队列中。
1、首先定义一个注解类
1
2
3
4
5
|
@Target
(ElementType.PARAMETER)
@Retention
(RetentionPolicy.RUNTIME)
@Documented
public
@interface
JsonObject {
}
|
2、其次实现自定义的参数解析类JsonObjectArgResolverHandler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
public
class
JsonObjectArgResolverHandler
implements
HandlerMethodArgumentResolver {
@Override
public
boolean
supportsParameter(MethodParameter methodParameter) {
return
methodParameter.hasParameterAnnotation(JsonObject.
class
);
}
@Override
public
Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest,
WebDataBinderFactory webDataBinderFactory)
throws
Exception {
try
{
JSONObject para = getRequestInfo(nativeWebRequest);
Class<?> type = methodParameter.getParameterType();
String name = methodParameter.getParameterName();
if
(
null
!= para && para.containsKey(name)) {
return
JSON.parseObject(para.getString(name), type);
}
}
catch
(Exception e) {
}
return
null
;
}
private
JSONObject getRequestInfo(NativeWebRequest webRequest)
throws
IOException {
JSONObject para =
new
JSONObject();
HttpServletRequest httpServletRequest =
(HttpServletRequest) webRequest.getNativeRequest(HttpServletRequest.
class
);
String method = httpServletRequest.getMethod();
if
(!method.equals(
"GET"
) && !method.equals(
"DELETE"
)) {
if
(
null
!= httpServletRequest.getAttribute(
"para"
)) {
try
{
para = JSON.parseObject(httpServletRequest.getAttribute(
"para"
).toString());
}
catch
(Exception e) {
}
}
else
{
StringBuilder buffer =
new
StringBuilder();
BufferedReader reader = httpServletRequest.getReader();
String line;
while
((line = reader.readLine()) !=
null
) {
buffer.append(line);
}
httpServletRequest.setAttribute(
"para"
, buffer.toString());
try
{
para = JSON.parseObject(buffer.toString());
}
catch
(Exception e) {
}
}
}
else
{
Map<String, String[]> parameterMap = webRequest.getParameterMap();
for
(Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
String key = entry.getKey();
String values = StringUtils.join(entry.getValue());
para.put(key, values);
}
}
return
para;
}
}
|
注意:
a、supportsParameter表明我们的类只支持解析带有JsonObject的对象解析。
b、httpServletRequest的body体只能读取一次,再次读取后就返回空,因为带有JsonObject注解的对象都会执行一遍,在第一次获取后需要将body体保存下来,以便下次使用。所有有如下的代码
将body体保存
1
|
httpServletRequest.setAttribute(
"para"
, buffer.toString());
|
读取Attribute,没有则从body体读取。
1 if (null != httpServletRequest.getAttribute("para")) { 2 try { 3 para = JSON.parseObject(httpServletRequest.getAttribute("para").toString()); 4 } catch (Exception e) { 5 } 6 } else {
3、将 JsonObjectArgResolverHandler配置进xml文件中。
<mvc:annotation-driven> <mvc:argument-resolvers> <bean class="com.nuaa.handler.JsonObjectArgResolverHandler"></bean> </mvc:argument-resolvers> <mvc:return-value-handlers> <bean class="com.nuaa.handler.ReponseJsonBodyMethodReturnValueHandler"> <property name="messageConverters"> <list> <bean class="com.nuaa.handler.Base64JsonHttpMessageConverter"/> </list> </property> </bean> </mvc:return-value-handlers> </mvc:annotation-driven>
这个我们可以定义如下的接口,
@RequestMapping(value="/addstudentpost", method = RequestMethod.POST,produces="application/json")
@ResponseJsonBody
public Student addstudentpost(@JsonObject Student student,@JsonObject Info info){
student.setName(JSON.toJSONString(student)+JSON.toJSONString(info)+(new Date()));
return student;
}
整个函数的定义就比较明了和直观。
关于 ResponseJsonBody的注解,请查看http://www.cnblogs.com/wangjiuyong/articles/7162207.html
在readme中有测试方法:
http://localhost:8080/spring/controlhandler/addstudentget?student={"name":"zhang","year":100}&info={"address":"yuhuataiqu","city":"nanjing"} http://localhost:8080/spring/controlhandler/addstudentpost { "student": { "name": "wangjiuyong", "year": 2000 }, "info": { "address": "yuhuataiqu", "city": "nanjing" } }