Java——Spring MVC数据绑定
1.URL Mapping(URL映射)
URL Mapping指将URL与Controller方法绑定。
通过将URL与方法绑定,SpringMVC便可通过Tomcat对外暴露服务。
1)@GetMapping 绑定Get请求
@GetMapping("/g") @ResponseBody public String getMapping(){ return "This is get method"; }
2)@PostMapping 绑定Post请求
@PostMapping("/p") @ResponseBody public String postMapping(){ return "This is post mathod"; }
再访问Post请求的时候,我们可以使用form表单或者postman
form表单:
<div> <form action="/p" method="post"> <input type="submit" value="submit"> </form> </div>
postman:
3)@RequestMapping 通用绑定
(1)如果直接定义在类上,这是给类下面的所有逻辑处理增加URL前缀
@Controller
@RequestMapping("/test")
public class URLMappingController {
@GetMapping("/g")
@ResponseBody
public String getMapping(){
return "This is get method";
}
@PostMapping("/p")
@ResponseBody
public String postMapping(){
return "This is post mathod";
}
}
那么在访问路径下面都需要添加前缀:
(2)还可以直接定义在具体方法上面,功能与GetMapping与PostMapping一样
@Controller public class URLMappingController { // @GetMapping("/g") @RequestMapping("/g") @ResponseBody public String getMapping(){ return "This is get method"; } }
如果这样定义将不区分是post方法还是get方法:
也可以通过下面方式来指定具体请求方式:
public class URLMappingController { // @GetMapping("/g") @RequestMapping(value = "/g",method = RequestMethod.GET) @ResponseBody public String getMapping(){ return "This is get method"; } }
2.Controller方法参数接收
在spring中要接受请求参数有两种做法:
a.使用Controller方法参数接收
b.使用Java Bean接受数据
(1)Controller方法参数接受
@Controller public class URLMappingController { @PostMapping("/p") @ResponseBody public String postMapping(String name,String password){ return name + ":" + password; } }
访问:
需要注意的是:
public String postMapping(String name,String password)
我们这里输入的是数字,接收的是字符串,这是spring帮我们完成的强转。
但是强转可能出现问题。
get的参数传递是在url中拼接:
例如:localhost:8080/g?name=kebi&password=123456
@Controller public class URLMappingController { @GetMapping("/g") @ResponseBody public String getMapping(String name, String password){ return name + ":" + password; } }
如果我们在传参的时候:
localhost:8080/g?nameOld=kebi&password=123456
这样不符合URL的定义规则,虽然不会报错。
如果改成这样:
localhost:8080/g?nameo_ld=kebi&password=123456
java那边也会不符合命名规范:
public String getMapping(String name_old, String password)
所以可以使用注解映射:
public String getMapping(@RequestParam("name_old") String nameOld, String password)
(2)使用Java Bean来接受请求的参数
如果一个请求里面传入了100个参数,那么使用Controller就会现在繁琐,因此我们可以将所有参数封装到一个对象,
这样在对象管理上面会方便很多。
创建User实体类:
public class User { private String name; private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
然后就可以使用对象来接收参数:
@PostMapping("/p1") @ResponseBody public String postMapping1(User user){ return user.getName() + ": " + user.getPassword(); }
当我们在请求这个URL的时候,spring MVC会自动创建实体对象,并将参数填充到User对象同名的参数中。
public String postMapping1(User user,String name)
如果我们在实体类之外在定义一个相同的参数,那么SpringMVC在填充的时候
只要是URL中同名的参数都会进行赋值,不论是实体类中的参数还是自定义的参数。
3.接收复合表单数据
利用数组或者List接收请求中的复合数据
利用@RequestParam为参数设置默认值
使用Map对象接收请求参数及注意事项
绝对路径与相对路径吗:
一般在提交数据的时候,可能并不简单:
当有多个复选按钮的时候,可能会一次提交多个数据
<form action="./apply" method="post"> <h3>您的姓名</h3> <input name="name" class="text" style="width: 150px"> <h3>您正在学习的技术方向</h3> <select name="course" style="width: 150px"> <option value="java">Java</option> <option value="h5">HTML5</option> <option value="python">Python</option> <option value="php">PHP</option> </select> <div> <h3>您的学习目的:</h3> <input type="checkbox" name="purpose" value="1">就业找工作 <input type="checkbox" name="purpose" value="2">工作要求 <input type="checkbox" name="purpose" value="3">兴趣爱好 <input type="checkbox" name="purpose" value="4">其他 </div> <div style="text-align: center;padding-top:10px" > <input type="submit" value="提交" style="width:100px"> </div> </form>
(1)使用list接收
@PostMapping("/apply") @ResponseBody public String apply(String name,String course,Integer[] purpose){ System.out.println(name); System.out.println(course); for (Integer p: purpose){ System.out.println(p); } return "apply test"; }
我们还可以设置默认值:
public String apply(@RequestParam(defaultValue = "ANON") String name, String course, Integer[] purpose)
这样如果前端不传参数,那么将会使用ANON默认值。
(2)使用List集合接收
public String apply(String name, String course, @RequestParam List<Integer> purpose)
只需要增加@RequestParam注解,spring才知道需要使用List集合来进行存储。
其实也可以使用对象接收:
public class Form { private String name; private String course; private List<Integer> purpose; }
控制器书写方式与前面类似。
@PostMapping("/apply") @ResponseBody public String apply(Form form){ System.out.println(form.getName()); System.out.println(form.getCourse()); for (Integer p: form.getPurpose()){ System.out.println(p); } return "apply test"; }
(3)使用Map注意事项
在使用map接收数据时,Map会无法接收复合数据的。
4.关联对象赋值
将关联对象的对象名放在表单参数名的前面,就可以给关联对象赋值。
public class Form { private String name; private String course; private List<Integer> purpose; private UserInfo userInfo=new UserInfo(); } public class UserInfo { private String name; private String mobile; private String address; }
表单传参的时候需要注意:
<h3>收货人</h3> <input name="userInfo.name" class="text" style="width: 150px"> <h3>联系电话</h3> <input name="userInfo.mobile" class="text" style="width: 150px"> <h3>收货地址</h3> <input name="userInfo.address" class="text" style="width: 150px">
这样就可以取出数据。
5.日期类型数据转换
1)@DateTimeFormat注解
如果前面传一个时间参数:
<input type="text" name="date">
后台直接使用date对象进行接收,那样肯定会强转失败:
public String postMapping(String name, String password, Date date)
400错误一般是由于强转失败。
可以使用@DateTimeFormat这个注解,pattern表示接收格式:
public String postMapping(String name, String password, @DateTimeFormat(pattern = "yyyy-MM-dd") Date date)
将其封装成为对象也是可行的:
将其封装成为对象也是可行的: public class User { private String name; private String password; @DateTimeFormat(pattern = "yyyy-MM-dd") private Date date; }
只是也需要加上@DateTimeFormat这个注解。
@PostMapping("/p") @ResponseBody public String postMapping(User user){ System.out.println(user.getName()); System.out.println(user.getPassword()); System.out.println(DateFormat.getDateInstance().format(user.getDate())); return "date test"; }
2)Converter全局转换器
如果每一个时间我需要进行时间注解,那也太麻烦了。
因此我们可以设置一个全局默认的时间转换器。
(1)创建转换器
新建converter这个包,以及转换器类MyDateConverter:
/* * 实现日期转换器的要点有三个: * 1.实现Converter这个接口 * 2.Converter<String, Date>有两个范型 * 3.必须要实现convert这个接口 * */ public class MyDateConverter implements Converter<String, Date> { public Date convert(String s){ //s表示输入的字符串 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { Date d = sdf.parse(s); //格式转换 return d; } catch (ParseException e){ return null; //如果输入的字符串格式不对,直接返回null } } }
(2)注册使用
在applicationContext.xml中配置:
<!--FormattingConversionServiceFactoryBean通知MVC有哪些自定义的转换类--> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!--转化类定义--> <property name="converters"> <set> <bean class="com.ikidana.springmvc.converter.MyDateConverter"/> </set> </property> </bean> <mvc:annotation-driven conversion-service="conversionService"/>
spring mvc在遇到类型转换的时候,一旦遇到date类型,就会使用MyDateConverter这个类进行转换。
那么如果既使用了@DateTimeFormat这个注解,又使用了全局转换器,那么以谁为准了?
对于SpringMVC,一旦增加了对应了日期转换器,那么优先使用转换器类来处理,而直接忽略掉注解。