持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的30天,点击查看活动详情
👨🎓作者:Java学术趴
💌公众号:Java学术趴
🚫特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系小编授权。
🙏版权声明:文章里的部分文字或者图片来自于互联网以及百度百科,如有侵权请尽快联系小编。微信搜索公众号Java学术趴联系小编。
☠️每日毒鸡汤:这个社会是存在不公平的,不要抱怨,因为没有用!人总是在反省中进步的!
👋大家好!我是你们的老朋友Java学术趴。
3. SpringBoot中Controller层的注解
3.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注解解决这个问题,如下:
3.2 @RestController
@RestController :从Spring 4.0以后产生的,用来将json/xml数据发送到前台页面,而不是返回视图页面。它相当于@Controller和@ResponseBody。
@RestController加在类上面的注解,使得类里面的每个方法都将json/xml返回数据加返回到前台页面中。梭所以在实际开发中,我们一般都使用这个注解。
3.3 @RequestMapping("路径信息")
@RequestMapping("路径信息") :@RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求。这个注解可以使用在Controller层的类或者方法上。
@RequestMapping中的参数:
- path : 指定路径,和value没有区别,只是path不可以省略,value可以省略。
3.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相当于声明一个根路径,在请求的时候他会把类和方上的路径进行拼接
3.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 规范提供了具大的便利条件。
3.4 @PostMapping("路径信息")
- 用于将Http Post 请求映射到特定处理程序方法的注释。具体来讲就是:@PostMapping是一个做为快捷方式的组合注释@RequestMapping(method = RequestMethod.POST)。
- 这个注解相当于: @RequestMapping(value="/{id}", method=RequestMethod.POST)
3.5 @GetMapping("路径信息")
- 用于将Http Get 请求映射到特定处理程序方法的注释。具体来讲就是:@GetMapping是一个做为快捷方式的组合注释 @RequestMapping(method = RequestMethod.GET)。
- 这个注解相当于: @RequestMapping(value="/{id}", method=RequestMethod.GET)
相似组合注解还有:@PutMapping、@DeleteMapping、@PatchMapping分别对用method的PUT、Delete以及Patch
3.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 = "客户端通信服务端接口")
3.7 @ApiOperation("针对Controller类中某个方法的描述")
@ApiOperation : 这个也是Swagger中的一个注解,作用在Controller类中的方法上,针对这个接口进行描述,会在Swagger的Api文档中进行记录。
参数信息:
- value: 对这个方法进行描述,value可以省略。
- notes : 用于提示内容。
// 用于 Controller 类中的接口上
@ApiOperation(value = "客户端下载对应脚本", notes = "下载脚本")
这两个Swagger注解用于 Controller 类上,还有 @ApiModel()以及@ApiModelProperty()用于实体类上,注意区分
3.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;
所以他会存在一个提醒的下画波浪线,但是不影响使用。
3.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 类型匹配方式。
3.10 @Value
3.10.1 @Value("${...}") -- 配置参数值注入
3.10.1.1 @Value("1")
- 给变量赋一个值。
@Value("张三")
private String name;
// 以上用法相当于
private String name = "张三";
3.10.1.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 的值。
- 如果这三个值都未定义,则报以上的错误。
3.10.2 @Value("#{...}") -- SPEL表达式求值注入
3.10.2.1 @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?
3.10.2.2 @Value("#{...}")
@Value("#{student.name ?: '张三'}")
- 注入 bean student 的属性name值
- 如果student存在并且有属性name,但属性值为null,则注入值“张三”
这个 @Value 注解可以使用在任何层
3.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";
}
3.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){
.....
}
3.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()可以有多个。
3.14 @ExceptionHandler
3.14.1 基本用法
- Spring的@ExceptionHandler可以用来统一处理方法抛出的异常,比如这样:
@ExceptionHandler()
public String handleExeption2(Exception ex) {
System.out.println("抛异常了:" + ex);
ex.printStackTrace();
String resultStr = "异常:默认";
return resultStr;
}
比如上面的handleExeption2()方法,给这个方法加上@ExceptionHandler注解,这个方法就会处理类中其他方法(被@RequestMapping注解)抛出的异常。
3.1.4.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时,才会调用该方法。如果抛出其他的异常的时候,这个方法就不可以接收到这个异常。
3.1.4.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()。
3.1.1.4 注解方法的返回值
标识了@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;
}
这样的操作可以在执行完方法后直接返回字符串本身。
3.1.1.5 错误的操作
使用@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声明的方法单独的提取出来。
3.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();
}
}
3.16 @ResponseStatus
-
@ResponseStatus的作用就是为了改变HTTP响应的状态码。
3.17 @CrossOrigin
3.17.1 跨域介绍
- @CrossOrigin注解:出于安全原因,浏览器禁止Ajax调用驻留在当前源点之外的资源。比如:当你在一个网页中查看你的银行账户,此时你在另一个页面中访问这个银行账户的时候,此时就禁止这个页面向当这个银行账户发送请求。这样就保证了账户的安全。
- 跨源资源共享(CORS)是由大多数浏览器实现的W3C规范,允许您灵活地指定什么样的跨域请求被授权,而不是使用一些不太安全和不太强大的策略,如IFPAME或JSONP。
3.17.2 使用方式
1. 给controller中的某个方法配置CORS
controller方法的CORS配置,您可以向@RequestMapping注解处理程序方法添加一个@CrossOrigin注解,以便启用CORS(默认情况下,@CrossOrigin允许在@RequestMapping注解中指定的所有源和HTTP方法):
为单独的方法配置跨域请求
@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) {
// ...
}
}
3.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;
}
}