- 一、处理器方法参数的处理
- 1、Servlet API 参数
- 2、简单类型参数
- 3、POST请求时中文乱码问题
- 4、RESTful风格传参
- 5、数组和List类型的参数(一个参数多个值的情况)
- 6、JavaBean类型的参数
- 7、ModelAttribute注解
- 8、请求头信息、Coolie等
- 9、数据绑定流程
- 10、多对象封装传递参数
- 11、JSON数据处理
- 12、日期类型处理
跳转到目录 如何在Controller中获取(前端传过来的数据)请求中的信息呢?
1、Servlet API 参数跳转到目录
@Controller
@RequestMapping("/request")
public class HandleRequestController {
// 也可以通过DI注入的方式,因为Controller是单例的,多线程不安全(不建议使用)
@Autowired
private ServletContext servletContext;
// 可以通过参数来操作Servlet的api
@RequestMapping("/test1")
public void test1(HttpServletRequest request, HttpServletResponse responser, HttpSession session) {
System.out.println(request.getParameter("username"));
System.out.println(request);
System.out.println(responser);
System.out.println(session);
System.out.println(this.servletContext);
}
}
2、简单类型参数
跳转到目录
@RequestParam注解
@Controller
@RequestMapping("/request")
public class HandleRequestController {
// 获取请求参数,保证请求参数名称和Controller方法的形参(入参)同名;
// 这样就可以获得请求的参数内容; 名字不同,得不到
@RequestMapping("/test2")
public void test2(String username, int age) {
System.out.println("username:" + username);
System.out.println("age:" + age);
}
// 如果请求参数名称和形参名称不同 ==> 使用RequestParam注解
// 使用@RequestMapping注解后,名字不同,也可以获取,请求参数的内容
@RequestMapping("/test3")
public void test3(@RequestParam("name") String username, @RequestParam(value = "age") Integer age) {
System.out.println("username:" + username);
System.out.println("age:" + age);
}
}
测试如下: 同名:
不同名:
跳转到目录 在web.xml中配置
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
forceRequestEncoding
true
forceResponseEncoding
true
CharacterEncodingFilter
/*
跳转到目录
@PathVariable注解
/delete?id=11 以前的方式
/delete/11 RESTfull方式
@PathVariable: 可以将URL中占位符绑定到方法的形参中
// 请求地址为 http://localhost:8080/request/delete/3
@RequestMapping("delete/{id}")
public void test4(@PathVariable("id") Long id){
System.out.println(id);
}
测试如下:
跳转到目录
// 接受一个参数有多个值的情况
// 批量删除; /batchDelete?ids=10&ids=20&ids=30
// 使用数组: 可以直接接收传递的多个参数
@RequestMapping("/batchDelete")
public void batchDelete(Long[] ids){
System.out.println(Arrays.asList(ids));
}
// 使用集合List: 不能直接接受,可以在对象中存在一个集合
@RequestMapping("/batchDelete2")
public void batchDelete2(FormBean fb){
System.out.println(fb.getIds());
}
//操作一个参数有多个值的情况,一般直接使用数组接受就可以了,或者使用JavaBean对象来封装数据.
跳转到目录
//把数据直接封装到JavaBean对象
@RequestMapping("/test4")
public void test4(User u) {
System.out.println(u);
}
测试如下:
默认会把符合类型参数共享到视图中,共享的key名为参数类型首字母小写; 如果要修改共享数据的key名; 使用
ModelAttribute
注解
跳转到目录 ModelAttribute注解
- 给共享的Model数据设置key名,贴在形参上,也可以贴在方法上针对复合类型(非简单类型)参数,缺省情况下就会放到model中(共享),缺省的key就是类型首字母小写
- 我们也可以在参数上贴
@ModelAttribute
,设置一个model的key名;
@RequestMapping("/zy1")
public String test1(User u){
System.out.println(u);
return "welcome";
}
@RequestMapping("/zy2")
public String test2(@ModelAttribute("zyuser") User u){
System.out.println(u);
return "welcome";
}
welcome.jsp
welcome
retult:
${user}
${zyuser}
测试如下:
跳转到目录
// 操作其他的请求信息
@Controller
@RequestMapping("/other")
@SessionAttributes("errorMsg")
public class OtherController {
// 获取请求头中的User-Agent和Cookie信息
// 以前的方式
@RequestMapping("zy1")
public void test0(HttpServletRequest request){
String header = request.getHeader("User-Agent");
String jsessionid = request.getHeader("Cookie");
System.out.println(header);
System.out.println(jsessionid);
}
// 现在的方式
@RequestMapping("zy2")
public void test1(@RequestHeader("User-Agent") String userAgent, @CookieValue("JSESSIONID") String cookieName){
System.out.println("User-Agent:" + userAgent);
System.out.println("cookieName" + cookieName);
}
// 操作HttpSession;
// 默认情况下Model数据是放到request中共享的,如果我想在session共享---->SessionAttributes注解
@RequestMapping("/zy3")
public String test2(Model model){
model.addAttribute("errorMsg", "错误信息!");
//默认肯定不能共享数据的,因为是重定向;之前讲过的那个Flash共享也仅仅只是在Controller之间共享
return "redirect:/abc.jsp";
}
}
abc.jsp
Title
result:
${requestScope.errorMsg}
${sessionScope.errorMsg}
${errorMsg}
测试如下:
跳转到目录 SpringMVC通过反射机制对目标处理方法的签名进行分析,将请求信息绑定到处理方法的形参中,数据绑定的核心组件是DataBinder类。
数据绑定流程:
1、框架把ServletRequest对象和请求参数传递给DataBinder
;
2、DataBinder 首先调用Spring Web环境中的ConversionService
组件,进行数据类型转换
和格式化
等操作,将ServletRequest中的信息填充到形参对象中;
3、DataBinder 然后调用Validator
组件对已经绑定了请求消息数据的形参对象进行数据合法性校验
;
4、DataBinder 最后输出数据绑定结果对象BindingResult.
BindingResult包含了已完成数据绑定的形参对象和校验错误信息对象。
5、最终SpringMVC框架会把BindingResult中的数据,分别赋给相应的处理方法。
10、多对象封装传递参数 (了解)跳转到目录
- 当需要把
表单数据封装到多个不同对象
中去的时候,如果各个对象中都有相同的属性如name
,此时请求参数name就不清楚到底该把值封装到哪一个对象中去。 更何况缺省情况下SpringMVC也不支持Struts2中类似于对象名.属性名
传参方式。
此时需要我们来对象数据设置绑定规则
。
@InitBinder注解:
自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;
由@InitBinder注解标注的方法,可以对WebDataBinder对象进行初始化。而WebDataBinder是DataBinder的子类,用于完成由请求参数到JavaBean的属性绑定。
注意点:
@InitBinder标注的方法不能有返回值,它必须声明为void。 @InitBinder标注的方法的参数通常是WebDataBinder.
input.html
DOCTYPE html>
Insert title here
狗狗姓名:
狗狗年龄:
猫猫姓名:
猫猫年龄:
Java代码
// 处理多个对象的封装
@Controller
public class MultiObjectParamController {
/*
需要把表单数据封装到多个对象中去,如果各个对象都有相同的属性,此时要出问题.
不知道该把哪一个参数封装到哪一个对象中去.
*/
// 参数-->对象,封装规则需要我们来设置
// 把以dog.开头的参数封装到dog对象中
@InitBinder("dog") // 自定义数据绑定注册,用于将请求参数转换到对应的对象的属性中去
public void initBinderDogyType(WebDataBinder binder){
binder.setFieldDefaultPrefix("dog.");
}
@InitBinder("cat")
public void initBinderCatType(WebDataBinder binder){
binder.setFieldDefaultPrefix("cat.");
}
@RequestMapping("/save")
public ModelAndView save(Cat cat, Dog dog){
System.out.println(cat);
System.out.println(dog);
return null;
}
}
测试如下:
跳转到目录
JacksonJackson 是一个Java开源的JSON工具库,性能很高,可以轻松将Java对象转换成Json对象xml文档,同样也可以将json、xml转换成Java对象
首先导入Jackson的Maven依赖
com.fasterxml.jackson.core
jackson-databind
2.9.10
com.fasterxml.jackson.core
jackson-core
2.9.10
com.fasterxml.jackson.core
jackson-annotations
2.9.10
Java代码测试
// 处理JSON
@Controller
@RequestMapping("/json")
public class HandleJsonController {
/*
处理JSON的注解:
ResponseBody: 处理响应,把对象转换为JSON字符串.
贴到方法上:只针对当前方法做JSON处理.
贴到类上 : 会对当前类中所有的方法做JSON处理.
RestController = Controller + ResponseBody
RequestBody: 处理请求,用于读取HTTP请求的内容,把JSON格式的请求数据封装成对象.
一般的请求的数据格式:
application/x-www-form-urlencoded: 传统的key-value格式,处理起来非常方便. 不需要RequestBody都可以,贴上也可以.
application/multipart:文件上传的请求,SpringMVC装设设计模式,.既能处理文件上传,也能处理普通表单数据.
application/json: 参数是JSON格式的,此时必须使用RequestBody.
*/
// 把单个对象/Map转换为JSON格式
@RequestMapping("/test1")
@ResponseBody
public User test1() {
User u = new User();
u.setUsername("桂朝阳");
u.setAge(22);
return u;
}
// 把集合转为JSON格式
@RequestMapping("/test2")
@ResponseBody
public List test2() {
User u = new User();
u.setUsername("桂阳");
u.setAge(22);
return Arrays.asList(u, u, u);
}
注意 : Jackson包导入后可能没有加载上,后台会报500错误; 注意看这个地方是否有jar包
跳转到目录 方式一
@Controller
@RequestMapping("/date")
public class HandleDateController {
// 从前台--->后台传递参数: String ---> java.util.Date // http://localhost:8080/date/test1?d=2010-11-1
@RequestMapping("/test1")
public ModelAndView test1(@DateTimeFormat(pattern = "yyyy-MM-dd") Date d){
System.out.println(d);
return null;
}
}
方式二
@Data
public class User {
private Long id;
private String username;
private Integer age;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date hiredate;
}
@Controller
@RequestMapping("/date")
public class HandleDateController {
// http://localhost:8080/date/test1?id=2&username=zy&age=23&hiredate=2020-2-1
@RequestMapping("/test2")
public ModelAndView test2(User user){
System.out.println(user);
return null;
}
}
方式三 @ControllerAdvice注解
@Data
public class User {
private Long id;
private String username;
private Integer age;
private Date hiredate;
}
@ControllerAdvice
public class DateFormatAdvice {
//如果不想每次都在Date类型上@DateTimeFormat
@InitBinder
public void initBinderDateType(WebDataBinder binder) {
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern("yyyy-MM-dd");
binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(sdf, true));
}
}
测试如下:
// 处理JSON
@Controller
@RequestMapping("/json")
public class HandleJsonController {
@RequestMapping("/test3")
@ResponseBody
public User test3(){
User user = new User();
user.setUsername("will");
user.setAge(82);
user.setHiredate(new Date());
return user;
}
}
测试如下: