SpringMVC

SpringMVC

本文分为以下几个部分:

Controller 和 RestController

RequestParam 和 RequestBody

结语

Controller 和 RestController

新建一个 SpringMVC 项目,配置相应 controller 扫描包、jsp 文件位置。

笔者此处配置了 test.jsp 文件

<h1>
    我是test
</h1>

配置两个 controller

@Controller
public class Controller1 {

    @RequestMapping("/c1")
    public String test1(){
        return "test";
    }

}
@RestController
public class Controller2 {

    @RequestMapping("/rc2")
    public String test1(){
        return "test";
    }

}

启动项目,访问两个 controller,@Controller 注解示例图如下,正常访问 test.jsp 页面

image-20210823113315179

@RestController 注解示例图如下,并 没有正常访问 test.jsp 页面:

image-20210823113830948

查看对应源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {

	@AliasFor(annotation = Component.class)
	String value() default "";

}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {

	@AliasFor(annotation = Controller.class)
	String value() default "";

}

相比之下, RestController 比 Controller 多了一个 @ResponseBody 注解,其他无差,导致访问 RestController 的方法不走视图解析器,直接把返回值响应回去。

所以

@RestController

相当于

@Controller

@ResponseBody

我们再看 @ResponseBody

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {

}

@ResponseBody 不仅可以用于 ElementType.TYPE(class),也能用于 ElementType.METHOD (方法),刚才@RestController就是用于 class 上方,等同于整个class 都不走视图解析器。

所以如果在一个 @Controller 的方法中,想要部分直接把返回值响应回去,直接在方法上添加 @ResponseBody 即可。

@RequestMapping("/c2")
@ResponseBody
public String test2(){
    return "test";
}

image-20210823134843619

RequestParam 和 RequestBody

Get 方法传参为链接地址传值,此处说的均为 POST 方法请求

RequestParam

我们先来看普通的处理 post 方法,编写一个form表单来仿造post方法

image-20210823141419448

后台编写对应的 p1 controller方法

@RestController
public class Controller3 {

    @PostMapping("/p1")
    public String test1(String username,String password){
        return username + ":" + password;
    }

}

查看对应效果

image-20210823141851110

image-20210823141943254

由于配置的是 RestController,所以直接返回字符串。

如果有些前端不讲武德,将 password 改成 name="pwd" ,但后端没变化,依旧访问 p1 请求,此时会得到

image-20210823143056659

后端可能存在使用password较为频繁,但此时如果修改传参为 String pwd,难免会有些麻烦,此时采用@RequestParam("pwd") String password 来指定前端传的值

@PostMapping("/p2")
public String test2(@RequestParam("username") String userName,
                    @RequestParam("pwd") String password){
    return userName + ":" + password;
}

image-20210823143512573

此时,前端把 pwd 又改成了 password,不动后台代码的情况。

image-20210823144330306

直接报错,原因是没有传pwd这个key,后台解析的时候需要pwd,但无法获取

image-20210823144252004

点击RequestParam查看源码

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {

    //参数,和value一样,可以看成别名
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    //是否必须存在
    boolean required() default true;

    //默认值
    String defaultValue() default ValueConstants.DEFAULT_NONE;
}

required改成 false,同时将请求参数改成 name = "pwd" 或者 value ="pwd",此时就算前端不传该值,也不会报错。

@PostMapping("/p2")
public String test2(@RequestParam(value = "username",required = false) String userName,
                    @RequestParam(name = "pwd",required = false) String password){
    return userName + ":" + password;
}

此时不会报错,直接显示null

image-20210823143056659

RequestBody

直接修改controller的方法

@PostMapping("/p3")
public String test3(@RequestBody String body){
    return body;
}

前台 form 提交至p3

启动项目访问

image-20210823154031290

由于前端传过来会变成一个字符串,所以建议使用 JSON 传输数据。

使用 ajax 传输json字符串

f

ajax访问p3,返回的结果为刚才传输的json字符串

image-20210823164536674

解析 JSON 虽然不麻烦,但是可以改成自动装配,添加一个 DTO 文件

package com.yb.dto;

/**
 * @author yb
 * @version 1.0
 * @date 2021/8/23 15:41
 * @description 前端传输配置类
 */
public class UserDTO {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public UserDTO() {
    }

    public UserDTO(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    public String toString() {
        return "UserDTO{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

新增controller方法,将ajax 请求P4,会自动装配值 UserDTO 中

@PostMapping("/p4")
public String test4(@RequestBody UserDTO user){
    return user.toString();
}

image-20210823164839612

结语

  • @RestController 比 @Controller 只多配置了 @ResponseBody ,配置了 @ResponseBody 则不走视图解析器。
  • @RequestParam 可以看成是前端传输字段时候的一个获取方法,当字段名和前端传输的字段相同时,可以不配置 @RequestParam。当配置 @RequestParam 报错时,可以看看是否该字段不存在(不存在和为空是两个概念)。
  • @RequestBody 是直接将前端所有数据放在一个中获取,通常前端使用JSON时候接收,当然不知道前端传的啥,可以使用RequestBody来接收试试(一个方法只存在一个@RequestBody)
posted @ 2021-08-23 16:56  抱糖果彡  阅读(60)  评论(0编辑  收藏  举报