《SpringMVC数据绑定入门》笔记

基本类型

最好使用封装类型

简单多数据&多层级对象

简单多数据

单个对象,直接使用属性名=值即可

多层级对象

属性.属性=值即可

同属性多对象

WebDataBinder只在当前类中生效,不是全局的

    //TODO http://localhost:8080/object.do?user.name=Tom&admin.name=Lucy&age=10
    @RequestMapping(value = "object.do")
    @ResponseBody
    public String object(User user,Admin admin){
        return user.toString()+" "+admin.toString();
    }

    @InitBinder("user")
    public void initUser(WebDataBinder binder){
        binder.setFieldDefaultPrefix("user.");
    }
    @InitBinder("admin")
    public void initAdmin(WebDataBinder binder){
        binder.setFieldDefaultPrefix("admin.");
    }

List、Set、Map类型的数据绑定

list

下标,最好是连续的,不然中间都是null

//TODO http://localhost:8080/list.do?users[0].name=Tom&users[1].name=Lucy&users[20].name=Jim
@RequestMapping(value = "list.do")
@ResponseBody
public String list(UserListForm userListForm){
    return "listSize:"+userListForm.getUsers().size() + "  " + userListForm.toString();
}

public class UserListForm {
    private List<User> users;

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    @Override
    public String toString() {
        return "UserListForm{" + "users=" + users + '}';
    }
}

Set

主要是用来去除重复,初始化时,需要设置大小。

//TODO http://localhost:8080/set.do?users[0].name=Tom&users[20].name=Lucy
@RequestMapping(value = "set.do")
@ResponseBody
public String set(UserSetForm userSetForm){
    return userSetForm.toString();
}

public class UserSetForm {
    private Set<User> users;

    private UserSetForm(){
        users = new LinkedHashSet<User>();
        users.add(new User());
        users.add(new User());
    }

    public Set<User> getUsers() {
        return users;
    }

    public void setUsers(Set<User> users) {
        this.users = users;
    }

    @Override
    public String toString() {
        return "UserSetForm{" + "users=" + users + '}';
    }
}

Map

//TODO http://localhost:8080/map.do?users['X'].name=Tom&users['X'].age=10&users['Y'].name=Lucy
@RequestMapping(value = "map.do")
@ResponseBody
public String map(UserMapForm userMapForm){
    return userMapForm.toString();
}

public class UserMapForm {
    private Map<String,User> users;

    @Override
    public String toString() {
        return "UserMapForm{" + "users=" + users + '}';
    }

    public Map<String, User> getUsers() {
        return users;
    }

    public void setUsers(Map<String, User> users) {
        this.users = users;
    }
}

Json、Xml数据类型的绑定

JSON

User类有name与age属性,并包含一个contactInfo

//    {
//            "name": "Jim",
//            "age": 16,
//            "contactInfo": {
//                "address": "beijing",
//                "phone": "10010"
//              }
//    }
    //content-Type:application/json
    @RequestMapping(value = "json.do")
    @ResponseBody
    public String json(@RequestBody User user){
        return user.toString();
    }

XML

//    <?xml version="1.0" encoding="UTF-8" ?>
//    <admin>
//      <name>Jim</name>
//      <age>16</age>
//    </admin>
    //content-Type:application/xml
    @RequestMapping(value = "xml.do")
    @ResponseBody
    public String xml(@RequestBody Admin admin){
        return admin.toString();
    }

@XmlRootElement(name="admin")
public class Admin {
    private String name;
    private Integer age;

    @XmlElement(name="name")
    public String getName() {
        return name;
    }

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

    @XmlElement(name="age")
    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Admin{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

格式化工具和类型转换器

应用:前台传入一字符串,后台接收一个java.util.Date类型

PropertyEditor的应用

内置的可扩展性;局部使用webdatabinder
binder.registerCustomEditor

    // http://localhost:8080/date1.do?date1=2016-07-18
    @RequestMapping(value = "date1.do")
    @ResponseBody
    public String date1(Date date1){
        return date1.toString();
    }

    @InitBinder("date1")
    public void initDate1(WebDataBinder binder){
        binder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
    }

PropertyEditorSupport有很多子类,可以根据使用场景来选择

Formatter的应用

内置的可扩展性;全局/局部;Source=String

  • 添加自定义的formatter
public class MyDateFormatter implements Formatter<Date> {

    public Date parse(String text, Locale locale) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.parse(text);
    }

    public String print(Date object, Locale locale) {
        return null;
    }
}
  • 配置,全局生效
<!-- 如果不加conversion-service是不会生效的 -->
<mvc:annotation-driven conversion-service="myDateFormatter"/>

<bean id ="myDateFormatter" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
	<property name="formatters">
		<set>
			<bean class="com.imooc.common.MyDateFormatter"></bean>
		</set>
	</property>
</bean>
  • 使用,由于当前MyDateFormatter是全局生效,所有直接使用Date即可,不需要WebDataBinder了
    @RequestMapping(value = "date2.do")
    @ResponseBody
     public String date2(Date date2){
        return date2.toString();
    }

Converter的应用

内置的不可扩展性;全局/局部;Source=自定义的
与Formatter类似,Converter高级一些,可设置Source

  • 实现converter
public class MyDateConverter implements Converter<String,Date> {
    public Date convert(String source) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return sdf.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}
  • 配置,全局生效
<!-- 如果不加conversion-service是不会生效的 -->
<mvc:annotation-driven conversion-service="myDateConverter"/>

<bean id ="myDateConverter" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
	<property name="converters">
		<set>
			<bean class="com.imooc.common.MyDateConverter"></bean>
		</set>
	</property>
</bean>
  • 使用,由于当前MyDateConverter是全局生效,所有直接使用Date即可,不需要WebDataBinder了
    @RequestMapping(value = "date2.do")
    @ResponseBody
     public String date2(Date date2){
        return date2.toString();
    }

RESTful

Resource Representational State Transfer
资源表现层状态转换
表现层:如果图片可以表现为jpg、png等
表现形式:content-Type

幂等性:每次HTTP请求相同的参数,相同的URI,产生的结果是相同的

@RequestMapping(value = "/book",method = RequestMethod.GET)
@ResponseBody
public String book(HttpServletRequest request){
    String contentType = request.getContentType();
    if(contentType == null){
        return "book.default";
    }else if(contentType.equals("txt")){
        return "book.txt";
    }else if(contentType.equals("html")){
        return "book.html";
    }
    return "book.default";
}

@RequestMapping(value = "/subject/{subjectId}",method = RequestMethod.GET)
@ResponseBody
public String subjectGet(@PathVariable("subjectId") String subjectId){
    return "this is a get method,subjectId:"+subjectId;
}

@RequestMapping(value = "/subject/{subjectId}",method = RequestMethod.POST)
@ResponseBody
public String subjectPost(@PathVariable("subjectId") String subjectId){
    return "this is a post method,subjectId:"+subjectId;
}

@RequestMapping(value = "/subject/{subjectId}",method = RequestMethod.DELETE)
@ResponseBody
public String subjectDelete(@PathVariable("subjectId") String subjectId){
    return "this is a delete method,subjectId:"+subjectId;
}

@RequestMapping(value = "/subject/{subjectId}",method = RequestMethod.PUT)
@ResponseBody
public String subjectPut(@PathVariable("subjectId") String subjectId){
    return "this is a put method,subjectId:"+subjectId;
}
  • RESTful设计
moive/douban.com/show/subject/11620560  # 不正确,不应有动词show
moive/douban.com/subject/11620560  # 正确

POST /accounts/1/transfer/500/to/2  # 不正确,不应有动词trfansfer
POST /transaction   # 正确
from=1&to=2&amount=500.00

www.example.com/app/1.0  # 不正确
www.example.com/app	# 正确
HEADER
version=1.0
posted @ 2016-07-19 20:45  chencye  阅读(736)  评论(0编辑  收藏  举报