• 【Java框架】SpringMVC(二)——SpringMVC数据交互


    前后端数据交互

    • Spring MVC框架是控制层框架,主要负责处理前后端之间的数据交互工作,包括从请求中获取入参数据,并向前端返回处理结果。
    • Spring MVC框架是如何处理数据交互问题的?

    @RequestMapping注解

    • @RequestMapping注解负责把不同的请求映射到对应的控制器方法上。
    • @RequestMapping注解不仅可以作用于控制器的方法上,还可以标注到控制器类上。
    • @RequestMapping注解添加到Controller类上时,表示当前控制器下所有接口的访问路径有相同的前缀

    基于@RequestMapping注解设置接口的请求方式

    • 在Web项目开发中,通常会使用GET类型请求访问查询接口,使用POST类型请求访问保存方法,@RequestMapping注解可以为接口设置访问类型

      @Controller
      public class HelloController {
          @RequestMapping(value = "/hello",method = {RequestMethod.GET,RequestMethod.POST})
          public String hello(){
              return "index";
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 除了使用method属性设置接口访问类型外,SpringMVC框架还提供了@GetMapping、@PostMapping等注解实现类似功能。如下接口如果使用POST以外的请求类型进行访问,就会报错

      	@Controller
      	public class HelloController {
      	    @PostMapping("/hello")
      	    public String hello(){
      	        return "index";
      	    }
      	}
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    在这里插入图片描述
    浏览器url访问默认是get请求

    @RequestMapping注解的常用属性

    属性名描述
    value指定请求的实际访问地址,默认@RequestMapping(“url”)的值url即为value的值。指定的地址可以是 URI Template 模式。
    method指定请求的method类型,主要有 GET、POST、DELETE、PUT等;
    params指定request中必须包含某些参数值,包含才让该方法处理请求。
    headers指定request中必须包含某些指定的header值,包含才能让该方法处理请求。
    consumes指定处理请求的提交内容类型(Content-Type),例如:application/json, text/html;
    produces指定返回的内容类型,当且仅当request请求头中的(Accept)类型中包含该指定类型才返回;

    一个方法配置多个接口

    访问/,/hello,/hi都是访问这个hello方法

    @Controller
    public class HelloController {
        @RequestMapping(value = {"/","/hello","/hi"})
        //@RequestMapping(path = {"/","/hello","/hi"})// path也可以
        public String hello(){
            return "index";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    method属性

    • 如果没有指定method属性,则表示任何形式的请求都可以访问该接口
    • 如果设置了method的值,就只能支持设置值的请求方式,其它请求方式不支持,就会报405错误 – Method Not Allowed
    • 可以指定一种或者多种(数组形式)请求方式
          //@RequestMapping(value = "/hello",method = {RequestMethod.POST,RequestMethod.GET})
          @RequestMapping(value = "/hello",method = RequestMethod.POST)
          public String hello(){
              return "index";
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5

    params属性

    指定request中必须包含某些参数值,包含才让该方法处理请求。

    	//请求中的参数who值为world才执行该方法
    	//@RequestMapping(value = "/hello",params = {"who=world"})
    	//请求中的参数who值不为world才执行该方法
        @RequestMapping(value = "/hello",params = {"who!=world"})
        public String hello(String who){
            System.out.println("hello" + who);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    headers属性

    指定request请求作用域中必须包含某些指定的header值,包含才能让该方法处理请求。

        @RequestMapping(value = "/hello",headers={"context-type=text/plain","context-type=text/html"})
        public String hello(){
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4

    上述访问,如果请求头中不包含context-type=text/plain,context-type=text/html这两个属性,那么就不能访问到该方法,报404错误。

    consumes属性

        @RequestMapping(value = "/hello", method = RequestMethod.POST, consumes="application/json")
        public String hello(){
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4

    方法仅处理request Content-Type为“application/json”类型的请求。

    produces属性

        @RequestMapping(value = "/hello",  method = RequestMethod.GET, produces="application/json")
        @ResponseBody
        public String hello(){
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    方法仅处理request请求中Accept头中包含了"application/json"的请求,同时暗示了返回的内容类型为application/json;

    SpringMVC中的参数传递

    • 在前面的课程中,使用Servlet接收前端请求时,通常会用到HttpServletRequest对象接收参数,代码如下:
      String realName=request.getParameter(“realName”);
      Integer id=request.getParameter(“id”);
      
      • 1
      • 2
    • 每一个参数都需要编写代码进行接收,且需要手动转换参数的类型,判断参数值是否为空,给开发人员带来了很大的工作量。怎么解决?
    • Spring MVC框架提供了@RequestParam注解,可以自动完成以上绝大部分工作。

    默认单个简单参数

        @RequestMapping(value = "/hello")
        public String hello(String who){
            System.out.println("hello" + who);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    此时who这个参数可传可不传,但如果传参参数名必须是who

    默认多个简单参数

        @RequestMapping(value = "/hello")
        public String hello(String who,String count){
            System.out.println("hello" + who + ","+ count);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    此时who、count都可传可不传,但如果传参参数名必须是who和count,顺序无所谓

    默认参数中有基本数据类型

        @RequestMapping(value = "/hello")
        public String hello(int count){
            System.out.println("hello,"+ count);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    • 按理说,count可传可不传,但是不传参数,则形参默认值为null,而这个count是几本数据类型,无法将null转换,因此就会报错。
    • 因此,接口中不要用基本数据类型作为参数,尽量使用包装类

    @RequestParam注解设置参数

        @RequestMapping(value = "/hello")
        public String hello(@RequestParam String who){
            System.out.println("hello" + who);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 此时,访问这个接口时,就必须传参了,并且参数名只能是who

    @RequestParam注解设置参数非必传

    required属性,默认值true表示必传,false表示非必传

        @RequestMapping(value = "/hello")
        public String hello(@RequestParam(required = false) String who){
            System.out.println("hello" + who);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    @RequestParam注解设置参数名称

    name属性

        @RequestMapping(value = "/hello")
        public String hello(@RequestParam(name = "paramName",required = false) String who){
            System.out.println("hello" + who);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 此时,访问这个接口时,就必须传参了,并且参数名只能是paramName

    @RequestParam注解设置参数默认值

    defaultvalue属性

        @RequestMapping(value = "/hello")
        public String hello(@RequestParam(defaultValue = "springmvc") String who){
            System.out.println("hello" + who);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 此时,访问这个接口时,如果不传who,那么who就会用springmvc作为默认值

    传对象/Map

    通常传对象都是用Post请求或者Put请求

        @PostMapping(value = "/hello")
        public String hello(User user){
            System.out.println("hello:" + user);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 此时传参时只需要让参数名与对象的属性名相同,就可以将参数映射到对象中
    • 如果是form表单,只需要让表单各组件的name值与对象属性名相同即可

    传数组

        @GetMapping(value = "/hello")
        public String hello(String[] hobbys){
            for (String hobby : hobbys) {
                System.out.println(hobby);
            }
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 此时传参时,直需要将多个参数值用逗号分割即可
      在这里插入图片描述

    传List集合

    需要加上@RequestParam才行,否则报错

        @GetMapping(value = "/hello")
        public String hello(@RequestParam List<String> hobbys){
            for (String hobby : hobbys) {
                System.out.println(hobby);
            }
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    传JSON

    示例

        @GetMapping(value = "/hello")
        public String hello(@RequestBody List<User> userList){
            userList.forEach(System.out::println);
            return "index";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置转换适配器,否则会报错HttpMediaTypeNotSupportedException: Content type 'application/json' not supp

        
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
            <property name="messageConverters">
                <list>
                    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">bean>
                list>
            property>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试
    在这里插入图片描述

    SpringMVC响应数据

    Spring MVC提供了多种方式输出模型数据

    • 使用ModelAndView对象
          @GetMapping(value = "/hello")
          public ModelAndView hello(){
              ModelAndView mv = new ModelAndView();
              mv.setViewName("index");//设置返回的逻辑视图名
              mv.addObject("msg","hello world");//设置后端向前端传递的数据
              return mv;
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 使用Model对象(推荐)
      在Model中增加模型数据,若不指定key,则默认使用对象的类型作为key
          @GetMapping(value = "/hello")
          public String hello(Model model){
              model.addAttribute("msg","Hello,SpringMVC");
              return "index";
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 使用Map对象
      Model其实就是一个Map的数据结构,可以使用Map作为处理方法入参
      返回的Map必须放在参数中作为形参,可以改变内容,但不能指向新的Map
          @GetMapping(value = "/hello")
          public String hello(Map<String,Object> returnMap){
              returnMap.put("msg","Hello,SpringMVC");
              return "index";
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5

    思考:如果是Ajax请求,期望服务端响应的不是页面而是数据,应该怎么处理?

    使用@ResponseBody注解

        @GetMapping(value = "/hello")
        @ResponseBody
        public User hello(){
            User user = new User();
            user.setUserName("周杰伦");
            user.setUserCode("zjl");
            return user;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    配置:添加消息转换器

    	<mvc:annotation-driven>
            <mvc:message-converters>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>application/json;charset=UTF-8value>
                        list>
                    property>
                bean>
                <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/html;charset=UTF-8value>
                            <value>application/jsonvalue>
                        list>
                    property>
                    <property name="features">
                        <list>
                            
                            <value>WriteDateUseDateFormatvalue>
                        list>
                    property>
                bean>
            mvc:message-converters>
        mvc:annotation-driven>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    @ResponseBody生效范围

    • 加在方法上,只对该方法生效
    • 加在Controller类上,则该Controller中的所有方法都不再返回页面,而是返回数据
      @Controller
      @ResponseBody
      public class HelloController {
      	...
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5

    RestController

    作用不再解释了,直接看源码,一目了然
    在这里插入图片描述

    SpringMVC参数传递时的Rest风格

    REST(Representational State Transfer),表现形式状态转换

    • 传统风格资源描述形式
    • http://localhost/user/getById?id=1
    • http://localhost/user/saveUser
    • REST风格描述形式
    • http://localhost/user/1
    • http://localhost/user

    优点:

    • 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
    • 书写简化

    分类

    method操作类型
    GET查询
    POST新增
    PUT修改
    DELETE删除

    代码示例

    package cn.smbms.controller;
    
    import cn.smbms.pojo.User;
    import org.springframework.web.bind.annotation.*;
    
    /**
     * @author: zjl
     * @datetime: 2024/4/19
     * @desc:
     */
    @RestController
    @RequestMapping("/user")
    public class UserController {
        @GetMapping("/{id}")
        public Integer getById(@PathVariable Integer id) {
            System.out.println("根据id查询" + id);
            return id;
        }
    
        @PostMapping("/change")
        public User insert(@RequestBody User user){
            System.out.println("新增用户" + user);
            return user;
        }
    
        @PutMapping("/change")
        public User update(@RequestBody User user){
            System.out.println("更新用户" + user);
            return user;
        }
    
        @DeleteMapping("/{id}")
        public Integer delete(@PathVariable Integer id){
            System.out.println("删除用户" + id);
            return id;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    对应的访问方式

    查询:

    http://localhost:9090/smbms/user/1
    在这里插入图片描述

    删除:

    http://localhost:9090/smbms/user/1
    在这里插入图片描述

    新增

    http://localhost:9090/smbms/user/change
    在这里插入图片描述

    修改

    http://localhost:9090/smbms/user/change
    在这里插入图片描述

  • 相关阅读:
    【025】mongoose V6.4开启debug日志打印
    win10 安装Elasticsearch 安装 Kibana
    乐信面试经历
    Docker-安装(Linux,Windows)
    Java基础 --- 注解
    【多目标进化优化】NSGAII 算法原理与代码实现
    msf编码免杀
    ModuleNotFoundError: No module named ‘sklearn.cross_validation‘
    Java设计模式-原型模式
    深入理解JVM虚拟机_1 JVM类加载器设计原理
  • 原文地址:https://blog.csdn.net/weixin_37833693/article/details/137958524