SpringMVC系列--注解

其他网址

springmvc 注解总结 - SpringMVC中文官网

@RequestMapping

1.1、@RequestMapping 标注位置

        RequestMapping是一个用来处理请求地址映射的注解,将请求映射到对应的控制器方法中,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

        RequestMapping请求路径映射,如果标注在某个controller的类级别上,则表明访问此类路径下的方法都要加上其配置的路径;如果标注在方法上,表明哪个具体的方法来接受处理某次请求。最常用是标注在方法上,表明哪个具体的方法来接受处理某次请求。如下所示:

@Controller
@RequestMapping(value="/book")
public class BookController {
    @RequestMapping(value="/title")
    public String getTitle(){
        return "title";
    }           
    
    @RequestMapping(value="/content")
    public String getContent(){
        return "content";
    } 
}

由于BookController类加了value="/book"的@RequestMapping的注解,所以相关路径都要加上"/book",即请求的url分别为:

  • (1) http://localhost:8080/book/title
  • (2) http://localhost:8080/book/content

注意:@RequestMapping的value值前后是否有"/"对请求的路径没有影响,即value="book" 、"/book"、"/book/"其效果是一样的。

1.2、RequestMapping的属性value:

属性value指定请求的实际url,分为以下几种情况:

(1)url可以是普通的具体值。如前面的value="/book",

(2)url也可以含某变量的一类值,如下所示:

@RequestMapping(value="/get/{bookId}")
public String getBookById(@PathVariable String bookId,Model model){
    model.addAttribute("bookId", bookId);
    return "book";
} 

路径中的bookId可以当变量,@PathVariable注解即提取路径中的变量值。

(3)ant风格

  • @RequestMapping(value="/get/id?"):可匹配"/get/id1"或"/get/ida",但不匹配"/get/id"或"/get/idaa";
  • @RequestMapping(value="/get/id*"):可匹配"/get/idabc"或"/get/id",但不匹配"/get/idabc/abc";
  • @RequestMapping(value="/get/id/*"):可匹配"/get/id/abc",但不匹配"/get/idabc";
  • @RequestMapping(value="/get/id/**/{id}"):可匹配"/get/id/abc/abc/123"或"/get/id/123",也就是Ant风格和URI模板变量风格可混用。

(4)含正则表达式的一类值

@RequestMapping(value="/get/{idPre:\\d+}-{idNum:\\d+}"):可以匹配"/get/123-1",但不能匹配"/get/abc-1",这样可以设计更加严格的规则。可以通过@PathVariable 注解提取路径中的变量(idPre,idNum)

(5)或关系

@RequestMapping(value={"/get","/fetch"}):即 /get或/fetch 都会映射到该方法上。

1.3、RequestMapping的method属性:

method:指定请求的method类型,包括 GET、POST、PUT、DELETE 等;

@RequestMapping(value="/get/{bookid}",method={RequestMethod.GET,RequestMethod.POST})

1.4、RequestMapping的params属性:

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

@RequestMapping(params="action=del"),请求参数包含"action=del",如:"http://localhost:8080/book?action=del"

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {

  @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {    
    // implementation omitted
  }
}

仅处理请求中包含了名为"myParam",值为"myValue"的请求。

1.5、RequestMapping的headers属性:

headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。@RequestMapping(value="/header/id", headers = "Accept=application/json")

上述注解表示请求的URL必须为 "/header/id 且请求头中必须有"Accept =application/json"参数即可匹配。

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {

@RequestMapping(value = "/pets", method = RequestMethod.GET, headers="Referer=http://www.ifeng.com/")
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {    
    // implementation omitted
  }
}

上述代码仅处理请求的header中包含了指定"Refer"请求头和对应值为"http://www.ifeng.com/"的请求。

1.6、RequestMapping的consumes属性:

consumes:指定处理请求的提交内容类型(Content-Type),例如 application/json,text/html 等。

@Controller
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {    
    // implementation omitted
}

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

1.7、RequestMapping的produces属性:

produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。 

@Controller
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {    
    // implementation omitted
}

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

1.8 RequestMapping的name属性:

此属性基本用不到,想了解见:

你知道@RequestMapping的name属性有什么用吗?【享学Spring MVC】 - YourBatman - 博客园

获得请求参数注解

@RequestParam

@RequestParam用于将请求参数区数据映射到功能处理方法的参数上。

示例

public String requestparam1(@RequestParam(value="user_name" String username)

请求中包含username参数(如/requestparam1?user_name=zhang),则username自动设为zhang。

@RequestParam有以下三个参数:

  • value:请求的参数名字。请求参数名和形参名不同时,要用该项来指定请求参数名。相同时可以不使用。
  • required:参数是否是必需的。默认是true(必需有);若为true而没有改参数则报400,BadRequest
  • defaultValue:参数默认值。请求中没有相应名字的参数时,形参的值就为该默认值。设置该参数时,自动将required设为false。

 请求参数是否是必须的

public String requestparam4(@RequestParam(value="username",required=false) String username)

上边表示请求中可以没有名字为username的参数,如果没有默认为null,此处需要注意如下几点:原子类型:必须有值,否则抛出异常,如果允许空值请使用包装类代替。Boolean包装类型:默认Boolean.FALSE,其他引用类型默认为null。

@PathVariable绑定URI模板变量值

@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。每个占位符/{}/{}中的值,必须和@PathVariable的value的值相同

@RequestMapping(value="/users/{userId}/topics/{topicId}")
public String test(
       @PathVariable(value="userId") int userId, 
       @PathVariable(value="topicId") int topicId)   

        如请求的URL为"控制器URL/users/123/topics/456",则自动将URL中模板变量{userId}和{topicId}绑定到通过@PathVariable注解的value同名参数上,即入参后userId=123、topicId=456。

@RequestBody

简介

 @RequestBody 将HTTP请求正文转换为适合的HttpMessageConverter对象。@ResponseBody 将内容或对象作为 HTTP 响应正文返回,并调用适合HttpMessageConverter的Adapter转换对象,写入输出流。

@RequestBody作用:

(1)该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上; 
(2)再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。

@RequestBody使用时机:

(1)GET、POST方式提时,根据request header Content-Type的值来判断:

application/x-www-form-urlencoded,不能处理(即使用@RequestBody不能处理这种格式的数据);
multipart/form-data,可选(@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
其他格式,必须(其他格式包括application/json, application/xml等,必须使用@RequestBody来处理);

(2)PUT方式提交时,根据request header Content-Type的值来判断:application/x-www-form-urlencoded,必须;multipart/form-data,不能处理;其他格式,必须;

说明:request的body部分的数据编码格式由header部分的Content-Type指定;

@CookieValue

@CookieValue注解用于将请求的cookie数据映射到功能处理方法的参数上。有value,name,required,defaultValue四个属性

@RequestMapping(value="/testCookieValue")
public String testCookieValue(@CookieValue(value="JSESSIONID") String cookieValue){
    System.out.println("执行了...");
    System.out.println(cookieValue);
    return "success";
}

响应注解

@ResponseBody

简介

@Responsebody表示该方法的返回结果直接写入HTTP response body中。一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@Responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中。比如前端异步获取json数据,后端加上@Responsebody后,会直接返回json数据。

@ResponseBody原理:

该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。

@ResponseBody使用时机:

返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

属性

@ModelAttribute

作用

        ModelAttribute可以应用在方法参数上或方法上,它的作用主要是当注解在方法参数上时会将注解的参数对象添加到Model中;当注解在请求处理方法Action上时会将该方法变成一个非请求处理的方法,但其它Action被调用时会首先调用该方法。

使用场景

        当@ModelAttribute注解用于方法时,与其处于同一个处理类的所有请求方法执行前都会执行一次此方法,这可能并不是我们想要的,因此,我们使用更多的是将其应用在请求方法的参数上,而它的一部分功能与@RequestParam注解是一致的,只不过@RequestParam用于绑定单个参数值,而@ModelAttribute注解可以绑定所有名称匹配的,此外它自动将绑定后的数据添加到模型中,无形中也给我们提供了便利,这也可能是它命名为ModelAttribute的原因。

@ModelAttribute用在参数上

        @ModelAttribute注释方法的一个参数表示应从模型model中取得。若在model中未找到,那么这个参数将先被实例化后加入到model中。若在model中找到,则请求参数名称和model属性字段若相匹配就会自动填充。这个机制对于表单提交数据绑定到对象属性上很有效。

        当@ModelAttribute注解用于方法参数时,它有了双重功能,即"存/取"。首先,它从模型中取出数据并赋予对应的参数,如果模型中尚不存在,则实例化一个,并存放于模型中;其次,一旦模型中已存在此数据对象,接下来一个很重要的步骤便是将请求参数绑定到此对象上(请求参数名映射对象属性名),这是Spring MVC提供的一个非常便利的机制--数据绑定。

@RequestMapping(value = "/login.htm", method = RequestMethod.GET)
public String doLogin(@ModelAttribute("baseMember") BaseMember member) {
    member.setLoginName("loginName");
    return "home";
}

        上述代码中,如果模型中尚不存在键名为"baseMember"的数据,则首先会调用BaseMember类的默认构造器创建一个对象,如果不存在默认构造器会抛出异常。因此,给实体类提供一个默认构造器是一个好的编程习惯。当请求路径的请求参数或提交的表单与BaseMember的属性名匹配时,将自动将其值绑定到baseMember对象中,非常的便利!这可能是我们使用@ModelAttribute最主要的原因之一。

        比如:请求路径为http://localhost:8080/spring-web/login.htm?loginName=myLoginName,baseMember对象中的loginName属性的值将被设置为myLoginName。

@ModelAttribute用在方法上

        被@ModelAttribute注释的方法表示这个方法的目的是增加一个或多个模型(model)属性。这个方法和被@RequestMapping注释的方法一样也支持@RequestParam参数,但是它不能直接被请求映射。实际上,控制器中的@ModelAttribute方法是在同一控制器中的@RequestMapping方法被调用之前调用的。

        被@ModelAttribute注释的方法用于填充model属性,例如,为下拉菜单填充内容,或检索一个command对象(如,Account),用它来表示一个HTML表单中的数据。一个控制器可以有任意数量的@ModelAttribute方法。所有这些方法都在@RequestMapping方法被调用之前调用。

        有两种类型的@ModelAttribute方法。一种是:只加入一个属性,用方法的返回类型隐含表示。另一种是:方法接受一个Model类型的参数,这个model可以加入任意多个model属性。

(1)@ModelAttribute注释void返回值的方法

@Controller
@RequestMapping(value="/test")
public class TestController {
    
    /**
     * 1.@ModelAttribute注释void返回值的方法
      * @param abc
     * @param model
     */
    @ModelAttribute
    public void populateModel(@RequestParam String abc, Model model) {
        model.addAttribute("attributeName", abc);
    }
    
    @RequestMapping(value = "/helloWorld")
    public String helloWorld() {
       return "test/helloWorld";
    }
}

        这个例子,在获得请求/helloWorld 后,populateModel方法在helloWorld方法之前先被调用,它把请求参数(/helloWorld?abc=text)加入到一个名为attributeName的model属性中,在它执行后helloWorld被调用,返回视图名helloWorld和model已由@ModelAttribute方法生产好了。这个例子中model属性名称和model属性对象由model.addAttribute()实现,不过前提是要在方法中加入一个Model类型的参数。

(2)@ModelAttribute注释返回具体类的方法

/**
 * 2.@ModelAttribute注释返回具体类的方法
 * @param id
 * @return
 */
@ModelAttribute
public User getUserInfo(String id){
    if(id!=null && !id.equals("")){
        return userService.getUserInfo(id);
    }
    return null;
}

        这种情况,model属性的名称没有指定,它由返回类型隐含表示,如这个方法返回User类型,那么这个model属性的名称是user。这个例子中model属性名称有返回对象类型隐含表示,model属性对象就是方法的返回值。它无须要特定的参数。

(3)@ModelAttribute(value="")注释返回具体类的方法

@Controller
@RequestMapping(value="/test")
public class TestController {
    
    /**
     * 3.@ModelAttribute(value="")注释返回具体类的方法
      * @param abc
     * @return
     */
    @ModelAttribute("str")
    public String getParam(@RequestParam String param) {
        return param;
    }
    
    @RequestMapping(value = "/helloWorld")
    public String helloWorld() {
       return "test/helloWorld";
    }
}

这个例子中使用@ModelAttribute注释的value属性,来指定model属性的名称。model属性对象就是方法的返回值。它无须要特定的参数。完整的代码:

package demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import demo.model.User;
import demo.service.IUserService;

@Controller
@RequestMapping(value="/test")
public class TestController {
    
    @Autowired
    private IUserService userService;
    
    /**
     * 1.@ModelAttribute注释void返回值的方法
      * @param abc
     * @param model
     */
    @ModelAttribute
    public void populateModel(@RequestParam String abc, Model model) {
        model.addAttribute("attributeName", abc);
    }
    
    /**
     * 2.@ModelAttribute注释返回具体类的方法
      * @param id
     * @return
     */
    @ModelAttribute
    public User getUserInfo(String id){
        if(id!=null && !id.equals("")){
            return userService.getUserInfo(id);
        }
        return null;
    }
    
    /**
     * 3.@ModelAttribute(value="")注释返回具体类的方法
      * @param abc
     * @return
     */
    @ModelAttribute("str")
    public String getParam(@RequestParam String param) {
        return param;
    }
    
    @RequestMapping(value = "/helloWorld")
    public String helloWorld() {
       return "test/helloWorld";
    }
}

Jsp前台取值:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head> 
    <title>helloWorld</title>
  </head>
  
  <body>
       1.The attributeValue is:  ${attributeName}
       <br/><br/>
       
       2.用户信息:<br/>
       姓名:${user.user_name}<br/>
       年龄:${user.user_age}<br/>
       邮箱:${user.user_email}<br/><br/>
      
      3.The param is:  ${str}
  </body>
</html>

页面效果图:

URL格式:http://localhost/SSMDemo/test/helloWorld?abc=text&id=1&param=aaa 

注:当url或者post中不包含参数abc和参数param时,会报错。

(4)@ModelAttribute和@RequestMapping同时注释一个方法

@Controller
@RequestMapping(value="/test")
public class TestController {

    @RequestMapping(value = "/helloWorld")
    @ModelAttribute("attributeName")
    public String helloWorld() {
       return "hi";
    }
}

        这时这个方法的返回值并不是表示一个视图名称,而是model属性的值,视图名称由RequestToViewNameTranslator根据请求"/helloWorld"转换为helloWorld。Model属性名称由@ModelAttribute(value="")指定,相当于在request中封装了key=attributeName,value=hi。
Jsp页面:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head> 
    <title>helloWorld</title>
  </head>
  
  <body>
      The attributeValue is:  ${attributeName}
  </body>
</html>

@SessionAttributes

简介

        在默认情况下,ModelMap中的属性作用域是request级别,也就是说,当本次请求结束后,ModelMap 中的属性将销毁。如果希望在多个请求中共享ModelMap中的属性,必须将其属性转存到session 中,这样 ModelMap 的属性才可以被跨请求访问。Spring 允许我们有选择地指定 ModelMap 中的哪些属性需要转存到 session 中,以便下一个请求属对应的 ModelMap 的属性列表中还能访问到这些属性。这一功能是通过类定义处标注 @SessionAttributes 注解来实现的。

Controller

@Controller
@RequestMapping("/anno")
@SessionAttributes(value={"msg"})   // 把Mapmodel中名字为msg的属性存入到session属性列表中
public class AnnoController {
@RequestMapping(value="/testSessionAttributes")
    public String testSessionAttributes(Model model){
        System.out.println("testSessionAttributes...");
        // 底层会存储到request域对象中
        model.addAttribute("msg","testSessionAttributes");
        return "success";
    }

	@RequestMapping(value="/getSessionAttributes")
	public String getSessionAttributes(ModelMap modelMap){
	    System.out.println("getSessionAttributes...");
	    String msg = (String) modelMap.get("msg");
	    System.out.println(msg);
	    return "success";
	}

	@RequestMapping(value="/delSessionAttributes")
	public String delSessionAttributes(SessionStatus status){
	    status.setComplete();//删除session域中的存入的数据
	    return "success";
	}
}

success.html

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>入门成功</h3>
    ${ msg }
    ${sessionScope}
</body>
</html>

测试1

访问:http://localhost:8080/anno/testSessionAttributes/

前端

测试2

访问:http://localhost:8080/anno/getSessionAttributes/

后端打印

getSessionAttributes...
testSessionAttributes

 测试3

访问:http://localhost:8080/anno/getSessionAttributes/

测试4

再次访问:http://localhost:8080/anno/getSessionAttributes/

后端打印

getSessionAttributes...
null

前端

参数验证

其他网址

Springboot @Validated和@Valid的区别 及使用_大菠萝一号-CSDN博客_@valid

简介

        JSR:Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。 

@Valid

简介

@Valid @Validated
简介 Hibernate-validator实现了java的JSR303声明了@Valid这类接口。(此处的Hibernate 不是 Hibernate ORM) 对@Valid进行了二次封装
所属依赖/包

依赖:org.hibernate.validator.hibernate-validator

包名:

javax.validation.Valid

javax.validation.constraints.NotBlank...

依赖:org.springframework.spring-context

包名:

org.springframework.validation.annotation.Validated

没有NotBlank、NotNull等注解。也需要引入org.hibernate.validator.hibernate-validator

使用位置

方法、参数、构造函数、成员属性(field)。

不能用于类。

类、方法、参数。

不能用于构造函数与成员属性(field)。

功能

可用于嵌套验证。

没有分组功能。

不能用于嵌套验证。

有分组功能。

所需依赖(有的地方说,springboot已经有@Valid,但我发现并没有):

        <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.1.2.Final</version>
        </dependency>

字段注解(所属包:javax.validation.constraints.*)

字段注解

说明

@AssertFalse

限制必须为false

@AssertTrue

限制必须为true

@DecimalMax(value)

限制必须为一个不大于指定值的数字

@DecimalMin(value)

限制必须为一个不小于指定值的数字

@Digits(integer,fraction)

限制必须为一个小数,且整数部分的位数不能超过integer,

小数部分的位数不能超过fraction

@Email

验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

@Future

限制必须是一个将来的日期

@Max(value)

限制必须为一个不大于指定值的数字

@Min(value)

限制必须为一个不小于指定值的数字

@Past

限制必须是一个过去的日期

@Pattern(value)

限制必须符合指定的正则表达式

@NotEmpty

验证注解的元素值不为null或者空(isEmpty()方法)。

可用于字符串,Collection,Map,数组

@NotBlank

验证注解的元素值不为null且包含除了空格之外至少一个字符。

只用于字符串

@Null

限制只能为null

@NotNull

限制必须不为null

@Past

验证注解的元素值(日期类型)比当前时间早

@Size(max,min)

限制字符长度必须在min到max之间

@Validated

简介

spring-boot-starter-web中已有rg.springframework.validation.annotation.Validated。但没有NotBlank、NotNull等注解。也需要引入org.hibernate.validator.hibernate-validator。

自定义校验器

public class User {
    private String id;
 
    @MyConstraint(message = "这是一个测试")
    private String username;
}

 注解的具体内容:

@Constraint(validatedBy = {MyConstraintValidator.class})
@Target({ELementtype.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyConstraint {
    String message();
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {}; 
}

 校验器:

public class MyConstraintValidator implements ConstraintValidator<MyConstraint, Object> {
    @Autowired
    private UserService userService;
    
    @Override
    public void initialie(@MyConstraint constarintAnnotation) {
        System.out.println("my validator init");
    }
    
    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        userService.getUserByUsername("seina");
        System.out.println("valid");
        return false;
    }
}

对List的验证

其他网址

@Validated和@Valid校验参数、级联属性、List_慕课手记

@Valid与@Validated只能校验JavaBean,而List不是JavaBean所以校验会失败,介绍三种解决办法。

方法1:对List进行Wrapper

既然List不是JavaBean,那我们就把它封装成JavaBean,我们定义一个ListWrapper类如下:

import lombok.Getter;
import lombok.Setter;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

@Setter
@Getter
public class ListWrapper {
	@Valid
	private List list;

	public ListWrapper() {
	    list = new ArrayList<>();
	}

	public  ListWrapper(List<E> list) {
	    this.list = list;
	}
}

 Controller

// 使用包装类对list进行验证
@PostMapping("/insert/all")
public ServerResponse<String> insertList(@Valid @RequestBody ListWrapper<UserEntity> listWrapper, 
                                         BindingResult bindingResult) {
    if(bindingResult.hasErrors()) {
        log.error(bindingResult.getFieldError().toString());
        return ServerResponse.createByErrorMessage(bindingResult.getFieldError().getDefaultMessage());
    }

    userService.insertList(listWrapper.getList());
    return ServerResponse.createBySuccess();
}

由于对list进行了包装,如果我们传参的时候[{},{}…]要改为{“list”: [{},{}…]}。

方法2:使用@Validated+@Valid

在controller类上面增加@Validated注解,并且删除方法参数中的BindingResult bindingResult(因为这个参数已经没有用了,异常统一有controller返回了)

可以看到可以对参数进行校验了,但还还有一个问题,那就是这个不是我们想要的返回格式,它controller自己返回的格式,所以我们需要做一个统一异常处理,代码如下:
 

import com.wyq.firstdemo.common.ServerResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

@Slf4j
@RestControllerAdvice
public class ControllerExceptionHandler {
	@ExceptionHandler
	@ResponseBody
	public ServerResponse<String> handle(ConstraintViolationException exception) {
	    log.error(String.valueOf(exception));
	    Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();
	    StringBuilder builder = new StringBuilder();
	    for (ConstraintViolation violation : violations) {
	        builder.append(violation.getMessage());
	        break;
	    }
	    return ServerResponse.createByErrorMessage(builder.toString());
	}
}

经过统一异常处理,我们这边的返回结果就是我们想要的格式了

方法3:自定义一个List

先上代码后说明,先定义一个ValidList 

import javax.validation.Valid;
import java.util.*;

public class ValidList implements List {

	@Valid
	private List<E> list;

	public ValidList() {
	    this.list = new ArrayList<>();
	}

	public ValidList(List<E> list) {
	    this.list = list;
	}

	public List<E> getList() {
	    return list;
	}

	public void setList(List<E> list) {
	    this.list = list;
	}

	@Override
	public int size() {
	    return list.size();
	}

	@Override
	public boolean isEmpty() {
	    return list.isEmpty();
	}

	//覆写list的所有方法(全都直接调用list的方法,例如上边的list.isEmpty)
	...
}

        对比方法3和方法1,有没有觉得代码有点相似,新建一个类,并且让他实现List接口,使这个类即具有了JavaBean的特性,又具有了List的特性,比方法1简单优雅很多。

只需要把List换成ValidList就可以了,还不需要多统一异常处理。

©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值