日期:2014-05-16  浏览次数:20470 次

自定义Spring MVC3的参数映射和返回值映射 + fastjson
自定义Spring MVC3的参数映射和返回值映射 + fastjson

首先说一下场景:在一些富客户端Web应用程序中我们会有比较多的Ajax调用,并且希望与服务器交互的数据需要是复杂的JSON对象。 fastjon是一个非常高效的JSON序列化和反序列化库,我希望我们输入的JSON串能通过fastjson直接反序列化为一个复杂的JavaBean对象,同时我的返回值能够能通过fastjson序列化为JSON串。

所谓复杂的JavaBean就是,不仅仅只有一层属性,而是属性也是JavaBean的情况, 例如:

public class FooBean {
    private String name;

    private Long id;

    private Date birthday;

    private List<Address> addresses;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public List<Address> getAddresses() {
        return addresses;
    }

    public void setAddresses(List<Address> addresses) {
        this.addresses = addresses;
    }

    @Override
    public String toString() {
        return "FooBean{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", birthday=" + birthday +
                ", addresses=" + addresses +
                '}';
    }
}


public class Address {
    private String street;
    private int number;

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return "Address{" +
                "street='" + street + '\'' +
                ", number=" + number +
                '}';
    }
}



当然,结构还可以再复杂,Adress对象里还可以又复杂JavaBean的属性。

在SpringMVC3中我们可以把输入简单的映射为某个Action方法的参数, 例如:

@RequestMapping(value="/someAction", method=RequestMethod.POST)
public String processSubmit(FooBean fooBean, Model model) {
// 利用fooBean
    return “views/some_page”;
}


用Spring MVC3, 我们可以把Form里的字段轻松的映射到JavaBean的属性。 Spring MVC3 提供了丰富的参数映射机制, 详细信息可以参见这里

同时对于Spring MVC3默认的提供的映射机制不能涵盖的对象,我们可以通过扩展HandlerMethodArgumentResolver和HttpMessageConverter的机制来实现。
HandlerMethodArgumentResolver对应输入, HttpMessageConverter对应输出

假设对于上面的FooBean, 我们有这样一个JSON对象和它对应:

var data = {
    name : "matianyi",
    id : 12345,
    birthday : "1983-07-01 01:12:12",
    addresses : [
        {
            street : "street1",
            number : 1
        },
        {
            street : "street2",
            number : 2
        }
    ]
};


Spring MVC3 本身也提供直接把JSON对象映射到JavaBean的功能,例如MappingJackson2HttpMessageConverter和MappingJackson2JsonView。
在这里我们希望通过fastjson来实现序列化和反序列化。所以我们要自定义一个HandlerMethodArgumentResolver用来指定HttpServletRequest的Body映射到一个JavaBean。并且返回的JavaBean通过fastjson序列化。

方法的定义是这样的:

@RequestMapping(value = "/fastjson", method = RequestMethod.POST)
public @ResponseBody FooBean fastjson2(@FastJson FooBean foo) {
    System.out.println(foo);
    return foo;
}


首先这里有个@FastJson的标注,这是我们为了让自己的HandlerMethodArgumentResolver能够识别这个参数是需要自己来处理而定义的一个Annotation

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FastJson {
}


然后就是定义一个FastJsonArgumentResolver,来对HttpServletRequest的body进行解析:

public class FastJsonArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        ret