6

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

 2 years ago
source link: https://www.cnblogs.com/origin-zy/p/16382285.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

 

1767106-20220616160525717-1250774946.png

 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();
}

Recommend

  • 41
    • www.cnblogs.com 6 years ago
    • Cache

    springmvc 请求参数解析细节

    springmvc 的请求流程,相信大家已经很熟悉了,不熟悉的同学可以参考下资料! 有了整体流程的概念,是否对其中的实现细节就很清楚呢?我觉得不一定,比如:单是参数解析这块,就是个大学问呢? 首先,我们从最靠近请求末...

  • 27

    Elasticsearch常常作为日志存储和分析的工具,在企业级应用中常常使用。Elasticsearch提供强大的搜索、分析功能,已经是后端技术栈不可缺少的一部分。在维护ElastciSearch集群的时候,对Elasticsearch进行了一些调优和分析,现整理成文,纯属拙见,如果有不合理之...

  • 37
    • www.throwable.club 5 years ago
    • Cache

    SpringMVC请求参数接收总结(一)

    在日常使用 SpringMVC 进行开发的时候,有可能遇到前端各种类型的请求参数,这里做一次相对全面的总结。 SpringMVC 中处理控制器参数的接口是 HandlerMethodArgumentResolver ,此接口有众多子类...

  • 23

    最近做了一些预研的工作,主要是一些技术调研,报告呈现的过程当中收到了许多建设性的建议,同时包含一点自己的拙见,如果能给你带来一些思考,那最好不过。明确面向对象一篇好的文章,一份好的报告一定要考虑一下的你面向对象,...

  • 34

    本篇文章讲述响应的处理,关于请求的处理可以看我第一篇文章 链接地址: https://segmentfault.com/a/11... 前期准备 使用环境

  • 8
    • zofun.github.io 3 years ago
    • Cache

    跟踪SpringMVC请求过程

    跟踪SpringMVC请求过程 2020-05-20 所有的请求都被拦截到DispatcherServle...

  • 6

    编辑导语:知识产权作为国家保护的一大重要权利,在互联网产品中也显得十分重要。本文对知识产权行业进行介绍,从行业背景出发,分析互联网产品中的知识产权,提出了自己的一些见解,期待与你一同交流。 大家好,可以叫我玛卡...

  • 5

    Netty整合SpringMVC,实现高效的HTTP服务请求 首先,你必须要了解netty,说简单点:客户端通过TCP链接和服务器建立长连接,client和server都是通过管道(ChannelPipeline)的addLast方法的...

  • 7

    2022-03-08 该篇文章大概记录了我在 Datawhale 的 “实际工作中数据和模型的价值 " 的相关分享。

  • 7

    1、请求处理参数 1.1 请求参数 @RequestParam 1.1.1 不使用 @RequestParam 注解 请求参数处理,不使用参数注解: 1.如果

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK