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

目录

前后端数据交互

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

@RequestMapping注解

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

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

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

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

    java 复制代码
    	@Controller
    	public class HelloController {
    	    @PostMapping("/hello")
    	    public String hello(){
    	        return "index";
    	    }
    	}

浏览器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方法

java 复制代码
@Controller
public class HelloController {
    @RequestMapping(value = {"/","/hello","/hi"})
    //@RequestMapping(path = {"/","/hello","/hi"})// path也可以
    public String hello(){
        return "index";
    }
}

method属性

  • 如果没有指定method属性,则表示任何形式的请求都可以访问该接口

  • 如果设置了method的值,就只能支持设置值的请求方式,其它请求方式不支持,就会报405错误 -- Method Not Allowed

  • 可以指定一种或者多种(数组形式)请求方式

    java 复制代码
        //@RequestMapping(value = "/hello",method = {RequestMethod.POST,RequestMethod.GET})
        @RequestMapping(value = "/hello",method = RequestMethod.POST)
        public String hello(){
            return "index";
        }

params属性

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

java 复制代码
	//请求中的参数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";
    }

headers属性

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

java 复制代码
    @RequestMapping(value = "/hello",headers={"context-type=text/plain","context-type=text/html"})
    public String hello(){
        return "index";
    }

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

consumes属性

java 复制代码
    @RequestMapping(value = "/hello", method = RequestMethod.POST, consumes="application/json")
    public String hello(){
        return "index";
    }

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

produces属性

java 复制代码
    @RequestMapping(value = "/hello",  method = RequestMethod.GET, produces="application/json")
    @ResponseBody
    public String hello(){
        return "index";
    }

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

SpringMVC中的参数传递

  • 在前面的课程中,使用Servlet接收前端请求时,通常会用到HttpServletRequest对象接收参数,代码如下:

    java 复制代码
    String realName=request.getParameter("realName");
    Integer id=request.getParameter("id");
  • 每一个参数都需要编写代码进行接收,且需要手动转换参数的类型,判断参数值是否为空,给开发人员带来了很大的工作量。怎么解决?

  • Spring MVC框架提供了@RequestParam注解,可以自动完成以上绝大部分工作。

默认单个简单参数

java 复制代码
    @RequestMapping(value = "/hello")
    public String hello(String who){
        System.out.println("hello" + who);
        return "index";
    }

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

默认多个简单参数

java 复制代码
    @RequestMapping(value = "/hello")
    public String hello(String who,String count){
        System.out.println("hello" + who + ","+ count);
        return "index";
    }

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

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

java 复制代码
    @RequestMapping(value = "/hello")
    public String hello(int count){
        System.out.println("hello,"+ count);
        return "index";
    }
  • 按理说,count可传可不传,但是不传参数,则形参默认值为null,而这个count是几本数据类型,无法将null转换,因此就会报错。
  • 因此,接口中不要用基本数据类型作为参数,尽量使用包装类

@RequestParam注解设置参数

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

@RequestParam注解设置参数非必传

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

java 复制代码
    @RequestMapping(value = "/hello")
    public String hello(@RequestParam(required = false) String who){
        System.out.println("hello" + who);
        return "index";
    }

@RequestParam注解设置参数名称

name属性

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

@RequestParam注解设置参数默认值

defaultvalue属性

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

传对象/Map

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

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

传数组

java 复制代码
    @GetMapping(value = "/hello")
    public String hello(String[] hobbys){
        for (String hobby : hobbys) {
            System.out.println(hobby);
        }
        return "index";
    }
  • 此时传参时,直需要将多个参数值用逗号分割即可

传List集合

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

java 复制代码
    @GetMapping(value = "/hello")
    public String hello(@RequestParam List<String> hobbys){
        for (String hobby : hobbys) {
            System.out.println(hobby);
        }
        return "index";
    }

传JSON

示例

java 复制代码
    @GetMapping(value = "/hello")
    public String hello(@RequestBody List<User> userList){
        userList.forEach(System.out::println);
        return "index";
    }

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

xml 复制代码
    <!--处理器适配器 -->
    <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>

测试

SpringMVC响应数据

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

  • 使用ModelAndView对象

    java 复制代码
        @GetMapping(value = "/hello")
        public ModelAndView hello(){
            ModelAndView mv = new ModelAndView();
            mv.setViewName("index");//设置返回的逻辑视图名
            mv.addObject("msg","hello world");//设置后端向前端传递的数据
            return mv;
        }
  • 使用Model对象(推荐)
    在Model中增加模型数据,若不指定key,则默认使用对象的类型作为key

    java 复制代码
        @GetMapping(value = "/hello")
        public String hello(Model model){
            model.addAttribute("msg","Hello,SpringMVC");
            return "index";
        }
  • 使用Map对象
    Model其实就是一个Map的数据结构,可以使用Map作为处理方法入参
    返回的Map必须放在参数中作为形参,可以改变内容,但不能指向新的Map

    java 复制代码
        @GetMapping(value = "/hello")
        public String hello(Map<String,Object> returnMap){
            returnMap.put("msg","Hello,SpringMVC");
            return "index";
        }

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

使用@ResponseBody注解

java 复制代码
    @GetMapping(value = "/hello")
    @ResponseBody
    public User hello(){
        User user = new User();
        user.setUserName("周杰伦");
        user.setUserCode("zjl");
        return user;
    }

配置:添加消息转换器

xml 复制代码
	<mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json</value>
                    </list>
                </property>
                <property name="features">
                    <list>
                        <!--   Date的日期转换器 -->
                        <value>WriteDateUseDateFormat</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

@ResponseBody生效范围

  • 加在方法上,只对该方法生效

  • 加在Controller类上,则该Controller中的所有方法都不再返回页面,而是返回数据

    java 复制代码
    @Controller
    @ResponseBody
    public class HelloController {
    	...
    }

RestController

作用不再解释了,直接看源码,一目了然

SpringMVC参数传递时的Rest风格

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

优点:

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

分类

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

代码示例

java 复制代码
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;
    }
}

对应的访问方式

查询:

http://localhost:9090/smbms/user/1

删除:

http://localhost:9090/smbms/user/1

新增

http://localhost:9090/smbms/user/change

修改

http://localhost:9090/smbms/user/change

相关推荐
一只叫煤球的猫2 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
bobz9652 小时前
tcp/ip 中的多路复用
后端
bobz9652 小时前
tls ingress 简单记录
后端
皮皮林5514 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
你的人类朋友4 小时前
什么是OpenSSL
后端·安全·程序员
bobz9654 小时前
mcp 直接操作浏览器
后端
前端小张同学6 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook6 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康7 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在7 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net