一. SpringBoot 中 Controller 层的注解

1.1 @Controller 注解

@Controller : 加在类上面的注解,使得类里面的每个方法都返回一个视图页面。
在这里插入图片描述
但是在实际开发中,我们一般只是让后端的方法返回给前端是查询的数据,而不是一个新的视图页面。如果使用 @Controller 注解必须结合 @ResponseBody,让这个方法返回给前端的不是一个视图,而只是给前端传递查询到的数据。

可以把 @ResponseBody 注解加到 Controller 类上或者是 Controller 层的方法上。

  • @ResponseBody 添加到类上:代表这个类中国所有的方法都返回的数据,而不是视图。
  • @ResponseBody 添加到方法上:代表只有这个方法返回的是数据,其他没有声明的返回的还是视图。

@Controller
public class HelloController {@GetMapping(value="/hello")
@ResponseBody
public String say(){//返回json 数据  
    return "gril";
}
  
@GetMapping(value="/hello1")
public String say1(){//返回视图
    return "sys/index1";
}

为了解决这个麻烦的操作,SpringBoot 中提供了 @RestController 注解解决这个问题,如下:

1.2 @RestController

@RestController :从 Spring 4.0 以后产生的,用来将 json/xml数据发送到前台页面,而不是返回视图页面。它相当于 @Controller 和 @ResponseBody。

@RestController 加在类上面的注解,使得类里面的每个方法都将 json/xml 返回数据加返回到前台页面中。梭所以在实际开发中,我们一般都使用这个注解。

1.3 @RequestMapping(“路径信息”)

@RequestMapping(“路径信息”) :@RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些 URL 请求。这个注解可以使用在 Controller 层的类或者方法上。

@RequestMapping 中的参数:
在这里插入图片描述
path : 指定路径,和 value 没有区别,只是 path 不可以省略,value 可以省略。

1.3.1 注解在 Controller 类上

将 @RequestMapping 注解在 Controller 类上,这时类的注解是相对于 Web 根目录,而方法上的是相对于类上的路径。

注意: @RequestMapping(“/index”) 等同于 @RequestMapping(value = “/index”)


@RestController
@RequestMapping("/user")
// @RequestMapping(value = "/user")
public class UserController {
 
    @RequestMapping("/login")
    public String login() {
        return "success";
    }
}
// 此时请求的实际路径是:/user/login
// 在类上的@RequestMapping相当于声明一个根路径,在请求的时候他会把类和方上的路径进行拼接
1.3.2 注解在 Controller 类的方法上

method 属性
通过 method 属性来指定请求的类型:有 GET(查)、POST(增)、PUT(改)、DELETE(删),由于浏览器表单无法发送 DELETE 和 PUT 请求,如果使用的话需要进行处理,所以我们在开发中一般使用 CET 和 POST 请求方式完成请求任务。

通过 @RequestMapping(value=“/login”,method=RequestMethod.GET) 来指定 login()方法 仅处理通过 GET 方式发来的请求


@RestController
@RequestMapping(path = "/user")
public class UserController {
    
    // 通过 method 属性来指定请求的类型,此时只能使用GET请求访问,使用POST会报错。
    @RequestMapping(path = "/login", method=RequestMethod.GET)
    public String login() {
        return "success";
    }
}

通过 @RequestMapping(value=“/login”,method=RequestMethod.POST) 来指定 login()方法 仅处理通过 POST 方式发来的请求


@RestController
@RequestMapping(path = "/user")
public class UserController {
 
    // 通过 method 属性来指定请求的类型,此时只能使用POST请求访问,使用GET会报错。
    @RequestMapping(path = "/login", method=RequestMethod.POST)
    public String login() {
        return "success";
    }
}

由于在 RequestMapping 注解类中 method() 方法返回的是 RequestMethod 数组,所以可以给 method 同时指定多个请求方式,例如


@RestController
@RequestMapping(path = "/user")
public class UserController {
     // 该方法将同时接收通过GET和POST方式发来的请求
    @RequestMapping(path = "/login", method={RequestMethod.POST,RequestMethod.GET})
    public String login() {
        return "success";
    }
}

Params属性
@RequestMapping 的 params 属性,该属性表示请求参数,也就是追加在 URL 上的键值对,多个请求参数以 &隔开,例如

http://localhost/SpringMVC/user/login?username=kolbe&password=123456

则这个请求的参数为 username=kolbe 以及 password=123456,@RequestMapping 中可以使用 params 来限制请求参数,来实现进一步的过滤请求,举个例子:


@Controller
@RequestMapping(path = "/user")
public class UserController {
        
     // 该方法将接收 /user/login 发来的请求,且请求参数必须为 username=kolbe&password=123456
    @RequestMapping(path = "/login", params={"username=kolbe","password=123456"})
    public String login() {
        return "success";
    }
}

该例中则表示 UserController 中的 login() 方法仅处理 /user/login 发来的请求,且必须带有 username=kolbe&password=123456 的请求参数,否则浏览器将返回 HTTP 404 的错误。

headers 属性:
@RequestMapping 的 headers 属性,该属性表示请求头。
在这里插入图片描述
通过 @RequestMapping 中的 headers 属性,可以限制客户端发来的请求。


@Controller
@RequestMapping(path = "/user")
public class UserController {
     // 表示只接收 localhost:8080 发来的请求,不会处理其他请求
    @RequestMapping(path = "/login", headers="Host=localhost:8080")
    public String login() {
        return "success";
    }
}

带有占位符的 URL
带占位符的 URL 是 Spring 3.0 新增的功能,可以通过 @PathVariable 将 URL 中的占位符绑定到控制器的处理方法的参数中,占位符使用{}括起来。


@Controller
@RequestMapping(path = "/user")
public class UserController {
     // 当只存在一个参数的时候,可以省略@PathVariable("id")注解,但是后边的参数名必须和{}中的占位符名字一致,否则找不到会报错。
    // 当给定 @PathVariable("id") 的时候括号中的参数名字必须和{}中占位符的名字一致。此时后边的参数可以随便定义其他的名字比如:@PathVariable("id") Integer param
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public String show(@PathVariable("id") Integer id) {
        return "success";
    }
}

在这个控制器中 show() 方法将可以接收 user/1、user/2、user/3 等等的路径请求,请求的方法必须为 GET,使用 @PathVariable 为应用实现 REST 规范提供了具大的便利条件。

1.4 @PostMapping(“路径信息”)

用于将 Http Post 请求映射到特定处理程序方法的注释。具体来讲就是:@PostMapping 是一个做为快捷方式的组合注释 @RequestMapping(method = RequestMethod.POST)。

这个注解相当于: @RequestMapping(value=“/{id}”, method=RequestMethod.POST)

1.5 @GetMapping(“路径信息”)

用于将 Http Get 请求映射到特定处理程序方法的注释。具体来讲就是:@GetMapping 是一个做为快捷方式的组合注释 @RequestMapping(method = RequestMethod.GET)。

这个注解相当于: @RequestMapping(value=“/{id}”, method=RequestMethod.GET)

相似组合注解还有:@PutMapping、@DeleteMapping、@PatchMapping 分别对用 method 的 PUT、Delete 以及 Patch

1.6 @Api(tags = “针对这个 Controller 类的描述”)

@Api :这个注解是 Swagger 中的一个注解,专门用于在 Controller 类上,针对这个 Controller 接口类生成一个文档的描述,在之后生成的 Swagger 的 Api 文档中会对这个 Controller 进行介绍。

参数信息:
tags: 生成的 api 文档会根据 tags 分类,直白的说就是这个 controller 中的所有接口生成的接口文档都会在 tags 这个 list 下;tags 如果有多个值,会生成多个 list,每个 list 都显示所有接口。

@Api(tags = "列表1")
@Api(tags = {"列表1","列表2"})

value : 它的作用和 tags 是一样的,只是不可以生成多个 list,只能生成一个。

// 用于 Controller 类上
@Api(tags = "客户端通信服务端接口")

1.7 @ApiOperation(“针对 Controller 类中某个方法的描述”)

@ApiOperation : 这个也是 Swagger 中的一个注解,作用在 Controller 类中的方法上,针对这个接口进行描述,会在 Swagger 的 Api 文档中进行记录。

参数信息:
value: 对这个方法进行描述,value 可以省略。
notes : 用于提示内容。

// 用于 Controller 类中的接口上
@ApiOperation(value = "客户端下载对应脚本", notes = "下载脚本")

这两个 Swagger 注解用于 Controller 类上,还有 @ApiModel()以及 @ApiModelProperty()用于实体类上,注意区分

1.8 @Autowired

@Autowired : spring 可以自动帮你把 bean 里面引用的对象的 setter/getter 方法省略,它会自动帮你 set/get。他会帮你完成对该 Bean 对象的自动装配。

@Autowired 这个注解是属于 SpringBoot 的

@Autowired 自动创建和装配的原理: 默认加在 IOC 容器中的组件,容器会调用无参构造器创建对象,在进行初始化赋值等操作,如果只有有参构造,Spring 会调用有参构造,有参构造函数会自动注入。

@Autowired 使用的地方:

  • 构造器 : 如果组件只有一个有参构造器,这个有参构造器的 @Autowrite 可以省略,参数位置组件还是可以自动从容器中获取。
  • 方法:@Bean 或者方法参数,参数从容器中获取;默认不写 @Autowrite 效果是一样的,都能自动装配。
  • 参数 :可以自动注入。
  • 属性 :可以自动注入。

注意:使用 @Autowrite 声明的对象一般声明为 private

package com.sue.cache.service;import org.springframework.stereotype.Service;@Service
public class TestService1 {
    public void test1() {
    }
}package com.sue.cache.service;import org.springframework.stereotype.Service;@Service
public class TestService2 {//自动装配一个 Service 层的实例对象
    @Autowired
    private TestService1 testService1;public void test2() {
    }
}

@Autowride 的使用原理,他是在返回数据的时候使用 DI 技术实现的。DAO 层不用使用 @Autowited,因为这层不需要实体类
在这里插入图片描述
注意:

  • spring 是按照类型装配的,也就是我们所说的byType方式。
  • 如果要修改为根据 byName进行自动装配,需要和 @Qualifier() 注解 配套使用
    @Autowired() 
    @Qualifier("baseDao")     
    private BaseDao baseDao;   

byName : 会搜索整个配置文件中的bean,如果有相同名称的bean则自动装配,否则显示异常。(类名)
byType : 会搜索整个配置文件中的bean,如果有相同类型的bean则自动装配,否则显示异常。(类的类别)

@Autowired 注解的required参数默认是 true,表示开启自动装配,有些时候我们不想使用自动装配功能,可以将该参数设置成 false。
required = true :开启自动装配(默认)
required = false : 关闭自动装配(需手动开启)

在 IDEA 中 @Autowired 存在下划线,但是可以正常使用。这是为什么呢?

因为 @Autowired 是基于构造函数的,正确的使用方式应该是使用构造函数的饿方式声明一个类对象。才是 @Autowired 注解的正确用法。

private final CategoryMapper categoryMapper;public CategoryServiceImpl(CategoryMapper categoryMapper) {
    this.categoryMapper = categoryMapper;
}

但是在实际开发中,我们都直接使用 @Autowired 来简化开发的难度。

@Autowired
private CategoryMapper categoryMapper;

所以他会存在一个提醒的下画波浪线,但是不影响使用。

1.9 @Resource

@Resource :@Resource 注解和 @Autowired 注解一样,都是为了装配 Bean,但是两者在使用上又有少许区别。@Resource 默认按照名字装配 Bean,即会按照 name 属性的值来找到具有相同 id 的 Bean Definition 并注入。如果 @Resource 没有指定 name 属性,则会根据这个将要被注入的属性的名字来进行 Bean 装配。

我们先来定义一个 Bean(通过注解的方式定义)

@Component(value = "renlei")
public class Person {
    String name;
 
    Integer age;
}

然后我们再来定义一个类 House,并引用上面的 Person,使容器对它自动装配

使用 @Resource(name = “renlei”) 中 name 属性值去对应 @Component(value = “renlei”) 中的 value 值

@Component
public class House {
    
    //@Resource的name属性的值与Person类的@Component的value值相对应【都是 renlei】,所以可以进行装配
    @Resource(name = "renlei")
    private Person p1;
   
    //@Resource的name属性的值与Person类的@Component的value值不对应,一个是relei,一个是person,所以装配失败
    @Resource(name = "person")
    private Person p1;

    //@Reource 没有指定name的值,所以容器会拿这个p1变量的名字去Bean池子中查找id为renlei的bean并装配到这个renlei变量中。装配成功
    @Reource
    private Person renlei;
 
    // @Reource 没有指定name的值,所以容器会拿这个p1变量的名字去Bean池子中查找id为p1的bean并装配到这个          p1变量中。如果找不到,就按照类型来进行装配,都是Person类,所以装配成功
    // 注意:这里存在一个先更具 byName方式匹配之后根据 byType方式匹配,都不成功的时候才会报错。
    @Reource
    private Person p1;
    
}

@Resource 这个注解是属于 J2EE 的。用于属性或者方法上,一般用于属性上。

@Resource 注解使用的过程:

  • 当启动 spring 容器的时候,spring 容器加载了配置文件
  • 在 spring 配置文件中,只要遇到 bean 的配置,就会为该 bean 创建对象
  • 在纳入 spring 容器的范围内查找所有的 bean,看哪些 bean 的属性或者方法上加有 @Resource
  • 找到 @Resource 注解以后,判断该注解 name 的属性是否为""(name 没有写)
    • 如果没有写 name 属性,则会让属性的名称的值和 spring 中 ID 的值做匹配,如果匹配成功则赋值如果匹配不成功,则会按照类型进行匹配,如果匹配不成功,则报错。

    • 如果有 name 属性,则会按照 name 属性的值和 spring 的 bean 中 ID 进行匹配,匹配成功,则赋值,不成功则报错。

注意:@Resource 先使用 byName 进行匹配,匹配不成功给则使用 byType 方式,如果还是匹配失败,则报错。在实际开发中,我们一般都给 @Service、@Controller 以及 @Repository 的 value 属性,所以在项目中使用的 @Resource 注解都是使用的 byType 类型匹配方式。

1.10 @Value

1.10.1 @Value(“${…}”) – 配置参数值注入
@Value("1")
给变量赋一个值。

@Value("张三")
private String name;// 以上用法相当于
private String name = "张三";
1.10.2 @Value(“${…}”) – 配置参数值注入

@Value :项目启动时,用于读取配置文件给静态文件赋值。读取 SpringBoot 的主配置文件中的属性值。

使用方式:
application.yml 配置文件

student:
    name:张三
    age:20
    room:java

在代码层获取这个变量值

@Value("${student.name}")
private String name;// 此时的name等于张三

如果配置参数 student.name 在配置文件中未定义则注入失败,抛出异常 IllegalArgumentException

java.lang.IllegalArgumentException: 
Could not resolve placeholder 'server.error.path' in value "${server.error.path}"

@Value(“{…:{…}}”) 嵌套使用

@Value("${student.name:${studnet.age:/student.room}}")
private String info;
  • 注入配置参数 student.name 的值。
  • 当 student.name 值未定义,注入配置参数 studnet.age 的值。
  • 如果 student.name 和 studnet.age 都没有定义,则使用 student.room 的值。
  • 如果这三个值都未定义,则报以上的错误。
1.10.3 @Value(“#{…}”) – SPEL 表达式求值注入

@Value(“#{1}”)

@Value("#{"张三"}")
private String name;// 此时的name等于张三

注入 bean student 属性 name 的值

如果 student 不存在或者其属性 name 不存在,则抛出异常 SpelEvaluationException

org.springframework.expression.spel.SpelEvaluationException: 
EL1008E: Property or field 'student' cannot be found on object of type 
'org.springframework.beans.factory.config.BeanExpressionContext' 
- maybe not public or not valid?

@Value(“#{…}”)

@Value("#{student.name ?: '张三'}")
  • 注入 bean student 的属性 name 值
  • 如果 student 存在并且有属性 name,但属性值为 null,则注入值“张三”

这个 @Value 注解可以使用在任何层

1.11 @PathVariable

@PathVariable : 映射 URL 绑定的占位符。

带占位符的 URL 是 Spring3.0 新增的功能,URL 中的 {xxx} 占位符可以通过 @PathVariable(“xxx”) 绑定到操作方法的入参中。

@RequestMapping("/user/{id}")
public String testPathVariable(@PathVariable("id") String id){
    System.out.println("路径上的占位符的值="+id);
    return "success";
}

当 URL 中只存在一个一个占位符的时候,可以省略这个 @PathVariable 注解,此时后面参数名必须和占位符的名字一致。

@RequestMapping("/user/{id}")
// 这个参数名必须是id,和占位符一致才可以识别到。
public String testPathVariable(String id){
    System.out.println("路径上的占位符的值="+id);
    return "success";
}

当给定 @PathVariable 注解的时候,这个注解中的值必须和占位符名一致,此时后面的参数名可以自定义。

@RequestMapping("/user/{id}")
// @PathVariable("id") 中的参数名必须和占位符一致,此时后面的参数可以任意给定。
public String testPathVariable(@PathVariable("id") String myId){
    System.out.println("路径上的占位符的值="+myId);
    return "success";
}

当存在多个占位符的时候,此时不可以省略 @PathVariable 注解,并且要把其中的参数和占位符相对应。

@RequestMapping("/user/{id}/{name}")
public String testPathVariable(@PathVariable("id") String myId, @PathVariable("name") String myName,){
    System.out.println("路径上的占位符的值="+id);
    return "success";
}

1.12 @RequestParam

@RequestParam : 这个注解是用于后端接收数据的。接收的参数是来自 requestHeader 中,即请求头。通常用于 GET 请求,像 POST、DELETE 等其它类型的请求也可以使用。比如常见的 url:http://localhost:8081/spring-boot-study/novel/findByAuthorAndType?author=唐家三少 &type=已完结

@RequestMapping(value = "add",method = RequestMethod.GRT)
public void addPeople(@RequestParam(value = "name", required = fasle,default = "Java学术趴") String name,@RequestParam(value = "age") Integer age){
  .....
}

1.13 @RequestBody

@RequestBody :这个注解也是用于后端接收数据的。接收的参数是来自 requestBody 中,即请求体。通常用于接收 POST、DELETE 等类型的请求数据,GET 类型也可以适用。一般用于处理非 Content-Type: application/x-www-form-urlencoded 编码格式的数据,比如:application/json、application/xml 等类型的数据。

application/json类型的数据而言,使用注解 @RequestBody 可以将 body 里面所有的 json 数据传到后端,后端再进行解析。

@RequestMapping(value = "add",method = RequestMethod.GRT)
public void addPeople(@RequestBody People people){
  .....
}

在后端的同一个接收方法里,@RequestBody 与 @RequestParam()可以同时使用,@RequestBody 最多只能有一个,而 @RequestParam()可以有多个。

1.14 @ExceptionHandler

1.14.1 基本用法

Spring 的 @ExceptionHandler 可以用来统一处理方法抛出的异常,比如这样:

@ExceptionHandler()
public String handleExeption2(Exception ex) {
    System.out.println("抛异常了:" + ex);
    ex.printStackTrace();
    String resultStr = "异常:默认";
    return resultStr;
}

比如上面的 handleExeption2()方法,给这个方法加上 @ExceptionHandler 注解,这个方法就会处理类中其他方法(被 @RequestMapping 注解)抛出的异常。

1.14.2 注解的参数

@ExceptionHandler 注解中可以添加参数,参数是某个异常类的 class,代表这个方法专门处理该类异常,比如这样:

@ExceptionHandler(NumberFormatException.class)
public String handleExeption(Exception ex) {
    System.out.println("抛异常了:" + ex);
    ex.printStackTrace();
    String resultStr = "异常:NumberFormatException";
    return resultStr;
}

此时注解的参数是 NumberFormatException.class,表示只有方法抛出 NumberFormatException 时,才会调用该方法。如果抛出其他的异常的时候,这个方法就不可以接收到这个异常。

1.14.3 就近原则

当异常发生时,Spring 会选择最接近抛出异常的处理方法。

比如之前提到的 NumberFormatException,这个异常有父类 RuntimeException,RuntimeException 还有父类 Exception,如果我们分别定义异常处理方法,@ExceptionHandler 分别使用这三个异常作为参数,比如这样:

@ExceptionHandler(NumberFormatException.class)
public String handleExeption(Exception ex) {
    System.out.println("抛异常了:" + ex);
    ex.printStackTrace();
    String resultStr = "异常:NumberFormatException";
    return resultStr;
}
 
@ExceptionHandler()
public String handleExeption2(Exception ex) {
    System.out.println("抛异常了:" + ex);
    ex.printStackTrace();
    String resultStr = "异常:默认";
    return resultStr;
}
 
@ExceptionHandler(RuntimeException.class)
public String handleExeption3(Exception ex) {
    System.out.println("抛异常了:" + ex);
    ex.printStackTrace();
    String resultStr = "异常:RuntimeException";
    return resultStr;
}

那么,当代码抛出 NumberFormatException 时,调用的方法将是注解参数 NumberFormatException.class 的方法,也就是 handleExeption(),而当代码抛出 IndexOutOfBoundsException 时,调用的方法将是注解参数 RuntimeException 的方法,也就是 handleExeption3()。

1.14.5 注解方法的返回值

标识了 @ExceptionHandler 注解的方法,返回值类型和标识了 @RequestMapping 的方法是统一的,可参见 @RequestMapping 的说明,比如默认返回 Spring 的 ModelAndView 对象,也可以返回 String,这时的 String 是 ModelAndView 的路径,而不是字符串本身。

有些情况下我们会给标识了 @RequestMapping 的方法添加 @ResponseBody,比如使用 Ajax 的场景,直接返回字符串,异常处理类也可以如此操作,添加 @ResponseBody 注解后,可以直接返回字符串,比如这样:

@ExceptionHandler(NumberFormatException.class)
@ResponseBody
public String handleExeption(Exception ex) {
    System.out.println("抛异常了:" + ex);
    ex.printStackTrace();
    String resultStr = "异常:NumberFormatException";
    return resultStr;
}

这样的操作可以在执行完方法后直接返回字符串本身。

1.14.6 错误的操作

使用 @ExceptionHandler 时尽量不要使用相同的注解参数。

如果我们定义两个处理相同异常的处理方法:

@ExceptionHandler(NumberFormatException.class)
@ResponseBody
public String handleExeption(Exception ex) {
    System.out.println("抛异常了:" + ex);
    ex.printStackTrace();
    String resultStr = "异常:NumberFormatException";
    return resultStr;
}
 
@ExceptionHandler(NumberFormatException.class)
@ResponseBody
public String handleExeption2(Exception ex) {
    System.out.println("抛异常了:" + ex);
    ex.printStackTrace();
    String resultStr = "异常:默认";
    return resultStr;
}

两个方法都处理 NumberFormatException,这种定义方式编译可以通过,而当 NumberFormatException 真正被抛出时,Spring 会给我们报错:

java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class java.lang.NumberFormatException]: {public java.lang.String TestController.handleExeption(java.lang.Exception), public java.lang.String TestController.handleExeption2(java.lang.Exception)}
    at org.springframework.web.method.annotation.ExceptionHandlerMethodResolver.addExceptionMapping(ExceptionHandlerMethodResolver.java:102) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.web.method.annotation.ExceptionHandlerMethodResolver.<init>(ExceptionHandlerMethodResolver.java:66) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE]

3.18 @ModelAttribute
@ModelAttribute 注解常用在 Controller 层的方法上,被 @ModelAttribute 声明的方法在 Controller 层每个方法执行之前都会执行,因此对于一个 Controller 层包含多个 URL 的时候,要谨慎使用。在开发中,我们一般都是把被 @ModelAttribute 声明的方法单独的提取出来。

​### 1.15 @ControllerAdvice
@ControllerAdvice 是 @Controller 注解的一个增强,这个注解是 Spring 里面的东西,可以处理全局异常。当然在 Spring Boot 中也可以使用,但是 Spring Boot 中有它全自动化配置的异常处理,因为是全自动化的,因此也可以自己定制,比如定制它的异常页面,异常信息提示,异常视图。需要配合 @ModelAttribute 一起使用。

@ControllerAdvice
public class MyAdviceException {
     //MaxUploadSizeExceededException,这个是异常类,这里可以枚举多个异常
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public void myexcept(MaxUploadSizeExceededException e, HttpServletResponse response){
         response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        writer.write("文件太大,请重新选择");
        writer.flush();
        writer.close();}
}

1.16 @ResponseStatus

@ResponseStatus 的作用就是为了改变 HTTP 响应的状态码。

1.17 @CrossOrigin

1.17.1 跨域介绍

@CrossOrigin 注解:出于安全原因,浏览器禁止 Ajax 调用驻留在当前源点之外的资源。比如:当你在一个网页中查看你的银行账户,此时你在另一个页面中访问这个银行账户的时候,此时就禁止这个页面向当这个银行账户发送请求。这样就保证了账户的安全

跨源资源共享(CORS)是由大多数浏览器实现的 W3C 规范,允许您灵活地指定什么样的跨域请求被授权,而不是使用一些不太安全和不太强大的策略,如 IFPAME 或 JSONP。

1.17.2 使用方式

1.给 controller 中的某个方法配置 CORS

controller 方法的 CORS 配置,您可以向 @RequestMapping 注解处理程序方法添加一个 @CrossOrigin 注解,以便启用 CORS(默认情况下,@CrossOrigin 允许在 @RequestMapping 注解中指定的所有源和 HTTP 方法):

1.为单独的方法配置跨域请求

@RestController
@RequestMapping("/account") public class AccountController {
 
 @CrossOrigin
 @GetMapping("/{id}") 
 public Account retrieve(@PathVariable Long id) { // ...
   
 }
  
 @DeleteMapping("/{id}")
 public void remove(@PathVariable Long id) { // ...
   
 }
}

@CrossOrigin 注解中的参数

  • origins : 允许可访问的域列表
  • maxAge:准备响应前的缓存持续的最大时间(以秒为单位)。

2.为整个 controller 启用 @CrossOrigin
在这个例子中,对于 retrieve()和 remove()处理方法都启用了跨域支持,还可以看到如何使用 @CrossOrigin 属性定制 CORS 配置。

@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account") public class AccountController {
 
 @GetMapping("/{id}") public Account retrieve(@PathVariable Long id) { // ...
   
 }
 
 @DeleteMapping("/{id}") public void remove(@PathVariable Long id) { // ...
   
 }
}

3.同时使用 controller 和方法级别的 CORS 配置,Spring 将合并两个注释属性以创建合并的 CORS 配置。

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account") public class AccountController {
 
 @CrossOrigin(origins = "http://domain2.com")
 @GetMapping("/{id}") 
 public Account retrieve(@PathVariable Long id) { 
   // ...
 }
 
 @DeleteMapping("/{id}") 
 public void remove(@PathVariable Long id) { 
   // ...
 }
}

1.18 @InitBinder

@InitBinder : 在实际操作中经常会碰到表单中的日期 字符串和 Javabean 中的日期类型的属性自动转换, 而 springMVC 默认不支持这个格式的转换,所以必须要手动配置, 自定义数据类型的绑定才能实现这个功能。

@InitBinder 用于在 @Controller 中标注于方法,表示为当前控制器注册一个属性编辑器或者其他,只对当前的 Controller 有效。

@RequestMapping("test")
@Controller
public class TestController {@InitBinder
    public     void InitBinder(WebDataBinder binder){
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        CustomDateEditor dateEditor = new CustomDateEditor(df, true);
        binder.registerCustomEditor(Date.class,dateEditor);
    }@RequestMapping(value="/param",method=RequestMethod.GET)
    @ResponseBody
    public Map<String,Object> getFormatData(Date date) throws ParseException{
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("name", "zhangsan");
        map.put("age", 22);
        map.put("date",date);
        return map;
    }
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐