• 拙见--springMVC的controller接受的请求参数


     

     1-这种是最常用的表单参数提交,ContentType指定为application/x-www-form-urlencoded,也就是会进行URL编码。

    1.1-对象类型实体Bean接收请求参数(表单实体也可以用@ModelAttribute("UserForm")
    复制代码
    @Controller
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("/login")
        public String login(UserForm userForm, HttpSession session, Model model){
            if("wangguodong".equals(userForm.getUname()) && "123".equals(userForm.getUpass())){ //用户名和密码都相等
                session.setAttribute("u", userForm);
                return "main" ; //登录成功,跳到主页面
            }else{
                model.addAttribute("messageError", "用户名或密码错误") ;
                return "login" ;
            }
        }
    复制代码
    拓展底层:1>因为没有使用注解,最终的参数处理器为ServletModelAttributeMethodProcessor,主要是把HttpServletRequest中的表单参数封装到MutablePropertyValues实例中,
    再通过参数类型实例化(通过构造反射创建UserForm实例),反射匹配属性进行值的填充
    2>实际上RequestParamMethodArgumentResolver依赖WebConversionService中Converter列表进行参数转换:因为没有UserForm到String的转换器,添加一个
    org.springframework.core.convert.converter.Converter实现即可   

      1.2-非对象类型单个参数接收:通过处理方法的形参接收请求参数(就是直接把表单参数写在控制类相应方法的形参中,形参名称与请求参数名称可以不一致时用@RequestParam(name = "name"))
    复制代码
    @PostMapping(value = "/post")

    public String post(@RequestParam(name = "name") String name, @RequestParam(name = "age") Integer age) { String content = String.format("name = %s,age = %d", name, age); log.info(content); return content; }
    复制代码
    拓展底层:1>这种情况下,用到的参数处理器是RequestParamMapMethodArgumentResolver。

    2-其他参数主要包括请求头、Cookie、Model、Map等相关参数,还有一些并不是很常用或者一些相对原生的属性值获取;例如HttpServletRequest、HttpServletResponse等)

      2.1HttpServletRequest
    复制代码
    @Controller
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("/login")
        public String login(HttpServletRequest request, Model model){
            String uname = request.getParameter("uname") ;
            String upass = request.getParameter("upass") ;
            if("wangguodong".equals(uname) && "123".equals(upass)){ //用户名和密码都相等
                return "main" ; //登录成功,跳到主页面
            }else{
                model.addAttribute("messageError", "用户名或密码错误") ;
                return "login" ;
            }
        }
    复制代码
      2.2请求头的值主要通过@RequestHeader注解的参数获取,
    @PostMapping(value = "/header")
    public String header(@RequestHeader(name = "Content-Type") String contentType) {
       return contentType;
    }
    拓展底层:1>参数处理器是RequestHeaderMethodArgumentResolver,需要在注解中指定请求头的Key。
      2.3Cookie的值主要通过@CookieValue注解的参数获取,
    @PostMapping(value = "/cookie")
    public String cookie(@CookieValue(name = "JSESSIONID") String sessionId) {
        return sessionId;}
    拓展底层:1>参数处理器为ServletCookieValueMethodArgumentResolver,需要在注解中指定Cookie的Key
      2.4Model类型参数
    @GetMapping(value = "/model")
    public String model(Model model, ModelMap modelMap) {
        log.info("{}", model == modelMap);
        return "success";
    }
    拓展底层:1>Model类型参数的处理器是ModelMethodProcessor,实际上处理此参数是直接返回ModelAndViewContainer实例中的Model(ModelMap类型),因为要桥接不
    同的接口和类的功能,因此回调的实例是BindingAwareModelMap类型,此类型继承自ModelMap同时实现了Model接口。ModelMap或者Model中添加的属性项会附加到
    HttpRequestServlet中带到页面中进行渲染。
      2.5Errors或者BindingResult参数
    复制代码
    @PostMapping(value = "/errors")
    public String errors(@RequestBody @Validated ErrorsModel errors, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            for (ObjectError objectError : bindingResult.getAllErrors()) {
                log.warn("name={},message={}", objectError.getObjectName(), objectError.getDefaultMessage());
            }
        }
        return errors.toString();}//ErrorsModel@Data@NoArgsConstructorpublic class ErrorsModel {
        @NotNull(message = "id must not be null!")
        private Integer id;
        @NotEmpty(message = "errors name must not be empty!")
        private String name;
    }

    复制代码
    拓展底层:1>Errors其实是BindingResult的父接口,BindingResult主要用于回调JSR参数校验异常的属性项,如果JSR校验异常,一般会抛出
    MethodArgumentNotValidException异常,并且会返回400(Bad Request),见全局异常处理器DefaultHandlerExceptionResolver。Errors类型
    的参数处理器为ErrorsMethodArgumentResolver。
      2.6Value参数
    @GetMapping(value = "/value")
    public String value(@Value(value = "${spring.application.name}") String name) {
        log.info("spring.application.name={}", name);
        return name;
    }
    拓展底层:1>控制器方法的参数可以是@Value注解修饰的参数,会从Environment中装配和转换属性值到对应的参数中(也就是参数的来源并不是请求体),
    参数处理器为ExpressionValueMethodArgumentResolver。
     2.7Map类型参数的范围相对比较广,对应一系列的参数处理器,

    注意区别使用了上面提到的部分注解的Map类型和完全不使用注解的Map类型参数,两者的处理方式不相同。下面列举几个相对典型的Map类型参数处理例子。

    不使用任何注解的Map<String,Object>参数
    这种情况下参数实际上直接回调ModelAndViewContainer中的ModelMap实例,参数处理器为MapMethodProcessor,往Map参数中添加的属性将会带到页面中。

    使用@RequestParam注解的Map<String,Object>参数
    这种情况下的参数处理器为RequestParamMapMethodArgumentResolver,使用的请求方式需要指定ContentType为x-www-form-urlencoded,不能使用application/json的

    @PostMapping(value = "/map")
    public String mapArgs(@RequestParam Map<String, Object> map) {
        log.info("{}", map);
        return map.toString();
    }

    使用@RequestHeader注解的Map<String,Object>参数
    这种情况下的参数处理器为RequestHeaderMapMethodArgumentResolver,作用是获取请求的所有请求头的Key-Value。

    使用@PathVariable注解的Map<String,Object>参数
    这种情况下的参数处理器为PathVariableMapMethodArgumentResolver,作用是获取所有路径参数封装为Key-Value结构。

     

    3-直接POST一个JSON字符串这种方式对于SpringMVC来说是比较友好的,只需要把ContentType设置为application/json,提交一个原始的JSON字符串即可:

    @PostMapping(value = "/user-2")
    public User saveUser2(@RequestBody User user) {
        log.info(user.toString());
        return user;
    }
    拓展底层:1>使用了@RequestBody注解,最终使用到的参数处理器为RequestResponseBodyMethodProcessor,实际上会用到
    MappingJackson2HttpMessageConverter进行参数类型的转换,底层依赖到Jackson相关的包。

    4-带请求路径参数(例如/user/{userId}是一个URL模板(URL模板中的参数占位符是{}),实际请求的URL为/user/1,那么通过匹配实际请求的URL和URL模板就能提取到userId为1)

    复制代码
    @GetMapping(value = "/user/{name}/{age}")
    public String findUser1(@PathVariable(value = "age") Integer age, @PathVariable(value = "name") String name) {
        String content = String.format("name = %s,age = %d", name, age);
        log.info(content);
        return content;
    }
    复制代码
    注意一点是,@PathVariable的解析是按照value(name)属性进行匹配,和URL参数的顺序是无关的
    其实路径参数支持正则表达式,例如我们在使用/sex/sex}接口的时候,要求sex必须是F(Female)或者M(Male)
    @GetMapping(value = "/sex/{sex:M|F}")
    public String findUser2(@PathVariable(value = "sex") String sex){
        log.info(sex);
        return sex;
    }
    拓展底层:1>对应的参数处理器为PathVariableMethodArgumentResolver。

    5-文件上传在使用POSTMAN模拟请求的时候需要选择form-data,POST方式进行提交:
    复制代码
    @PostMapping(value = "/file1")
    public String file1(@RequestPart(name = "file1") MultipartFile multipartFile) {
        String content = String.format("name = %s,originName = %s,size = %d",
                multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getSize());
        log.info(content);
        return content;
    }
    复制代码
    拓展底层:1>可知MultipartFile实例的主要属性分别来自Content-Disposition、content-type和content-length,另外,InputStream用于读取请求体的最后部分
    (文件的字节序列)。参数处理器用到的是RequestPartMethodArgumentResolver(记住一点,使用了@RequestPart和MultipartFile一定是使用此参数处理器)。

    6-批量文件上传,我们一般需要接收一个MultipartFile集合,使用MultipartHttpServletRequest参数,直接调用getFiles方法获取MultipartFile列表

    @PostMapping(value = "/parts")
    public String partArgs(@RequestParam(name = "file") List<MultipartFile> parts) {
        log.info("{}", parts);
        return parts.toString();
    }

     

  • 相关阅读:
    【C++】单例模式【两种实现方式】
    Android studio run 手机或者模拟器安装失败,但是生成了debug.apk
    Centos指令合集
    支付漏洞的原理与防御
    C/C++内存管理相关知识点
    Java之HashMap经典算法-红黑树(插入节点平衡调整,左旋转,右旋转)
    vdsm:添加接口调试demo
    【TB作品】MSP430,G2533单片机,红外发射,红外接收,红外通信,IR发射
    如何入门渗透测试(非常详细),从零基础入门到精通,看完这一篇就够了
    如何写出一篇好文章——不动笔就能学会写文章的训练法
  • 原文地址:https://www.cnblogs.com/origin-zy/p/16382285.html