SpringBoot注解整合
SpringBoot面向注解编程笔记
程序示例
一. Application主类
1.application类01: @SpringBootApplication
1 | //程序的主入口 |
注解: @SpringBootApplication
标注这是一个SpringBoot应用,这是一个复合注解
2.application类02 : IOC容器以及组件
1 |
|
这段代码执行后, 就会在控制台打印出所有的组件
二. Controller控制类
1. 控制类01: @RequestMapping,@ResponseBody
1 |
|
这种方法将@ResponseBody注解放在方法前,其实可以在类前放置注解让@ResponseBody作用于所有方法,并且@Controller注解可以和@ResponseBody注解合并为@RestController注解发挥相同作用
注解:@Controller
控制层(controller)注入spring容器
注解@RequestMapping(url)
将url请求和处理请求的控制器方法关联起来,建立映射关系。实现浏览器与服务器之间的映射
注解@ResponseBody
将java对象转为json格式的数据,这样后端返回数据时前端就能接收到json数据而不是object对象
2. 控制类02: @RestController
1 |
|
此时如上所说将@Controller和@ResponseBody合并@RestController简化使用,每个方法都有@ResponseBody作用
注解@RestController:
加在类上面的注解,使得类里面的每个方法都将json/xml返回数据加返回到前台页面中
3. 控制类03: Rest风格请求映射
1 |
|
REST风格的请求映射, 使用HTTP请求动词来表示对资源的操作
4. 控制类04: @GetMapping等
1 |
|
注解@PostMapping, @GetMapping:
REST风格的请求映射更为便捷的注解, 相等于处理get, post请求版的RequestMappin
5. 控制类05: ant风格路径
1 |
|
SpringMVC支持ant风格的路径
?: 表示任意的单个字符, 可使用localhost:8080/aa1a访问antTest01
*: 表示任意的0个或多个字符, 可使用localhost:8080/aabba访问antTest02
**: 表示任意的一层或多层目录, 可使用localhost:8080/bbb/aaa访问antTest03
注意: 在使用**时,
只能使用/**/xxx的形式
6. 控制类06:@RequestMapping占位符获取请求参数
1 |
|
注:
Rest风格的请求路径: /Test01/aaa 传统风格的请求路径: /Test01?id=”aaa”
注:
SpringMVC路径中的占位符常用于restful风格中, 当请求路径中将某些数据通过路径的方式传输到服务器中,就能在对应的@RequestMapping注解的value属性通过占位符{xxxx}表示传输的数据, 再通过@PathVaribale注解, 将占位符中的数据赋值给形参
注解@RequestMapping:
支持占位符, 即上面代码中/{}部分, 占位符必定表示有一个值, 如果请求路径中有占位符, 则所匹配的请求地址中也必须要有这一层路径(不能不写, 用/Test01访问就会报错)
注解@PathVariable:
必须作用与形参上,将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx”) 绑定到操作方法的入参中。
7. 控制类07:@RequestMapping多个占位符
1 |
|
注:
此时就可以通过/Test01/001/admin这种rest风格请求方式来访问handler
8. 控制类08: Servlet的API获取请求参数
1 |
|
注:
Controller中可以直接使用HttpServletRequest的API, 但这样就不能使用rest风格请求路径
9.控制类09: 通过控制器形参获得请求参数
1 |
|
注:
假设前端中有两个text属性名称是userName和id, 一个复选框名称为hobby, userName输入为admin, id输入为001,复选框勾选a b c, 提交后控制台打印id:001 username: admin hobby:[1,2,3]
注:
SpringMVC中, 只要控制器的形参与请求来的参数的名字相同, 就能直接匹配到形参(如果一个属性有多个值, 比如复选框, 那么他们的多个name属性在控制器形参如果用String接收会用逗号,来拼接, 用String[]接收会被封装成String数组)
10.控制类10: @RequestParam
1 |
|
注解@RequestParam:
将请求参数和控制器方法的形参创建映射关系, 给前端的请求参数取别名在后端使用
11.控制类11:@RequestHeader
1 |
|
注解@RequestHeader:
将请求头信息和控制器方法的形参创建映射关系, 用法与@RequestParam相同
12:控制类12:@CookieValue
1 |
|
注解@CookieValue:
将cookie数据和控制器方法的形参创建映射关系, 用法与@RequestParam相同
13:控制类13:通过POJO实体类获取请求参数
1 |
|
注:
这时控制层形参与请求参数的属性建立了映射关系, 可以直接再形参使用user对象, 从来调取浏览器请求参数传过来的值
三. Config配置类
1. Config类01 : javaBean类
前提代码:bean包下的User类和Pet类, 封装了get和set方法, ,User类有参数name和age,pet有参数name
1 | /** |
经过这个配置类的运行, 就能向IOC容器中注册bean组件, 就能在application类02执行时看到控制台打印出这两个组件的名字
注解@Configuration:
告诉SpringBoot这是一个配置类, 这个配置类将user01,Pet01组件放入ioc容器中(注意! @Configuration注解下的类也是注册好的一个组件, 组件名就是config类的类名)
注解@Bean
: 给容器中添加组件,以方法名作为组件的id(也可以直接在@Bean注解中定义组件id), 返回类型就是组件类型, 返回的值就是组件在容器中实例的对象
四. Servlet
1. Servlet示例01 :生命周期
1 | //演示Servlet的生命周期 |
Servlet生命周期:
主要包含init初始化, service执行服务, destroy销毁
2. Servlet示例02 :反射匹配方法
1 | import javax.servlet.http.HttpServlet; |
注:
通过反射创建Servlet的Class对象, 通过getDeclaredMethods();方法获得所有方法, 这样以后就能通过传进来的参数和方法数组遍历比较哪个元素相等后, 再执行这个方法实现代码简化
注:
循环遍历的结果是: index main update delete
注解详解
JAVA基础注解
@Override
定义在java.lang.Override中, 此注解只适用于修饰方法, 表示一个方法声明打算重写超类中的另一个方法
@Deprecaled
定义在java.lang.Deprecated中, 此注解可适用于方法, 类, 属性, 表示不鼓励程序员使用这样的元素, 标注这是一个废弃的方法, 类, 属性, 通常因为它们很危险或者又更好的选择
@SuppressWarnings
定义在java.lang.SuppressWarnings中, 用来抑制编译时的警告信息
@Target
这是一个元注解(可定义在注解上的注解), 定义在java.lang.annotation, 声明该类的注解能作用于哪些位置
@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包@Retention
这是一个元注解(可定义在注解上的注解), 定义在java.lang.annotation,表示注解在什么地方有效, 用于描述注解的生命周期
Retention注解有一个属性value,是RetentionPolicy类型的,Enum RetentionPolicy是一个枚举类型,
这个枚举决定了Retention注解应该如何去保持,也可理解为Rentention 搭配 RententionPolicy使用。 RetentionPolicy有3个值: SOURCE < CLASS < RUNTIME
- 用@Retention(RetentionPolicy.SOURCE )修饰的注解,表示注解的信息会被编译器抛弃,不会留在class 文件中,注解只在源文件中可用
- 用@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中 当程序编译时,注解可在源文件和CLASS字节码文件中可用
- 用@Retention(RetentionPolicy.RUNTIME)修饰的注解,表示注解的信息被保留在class文件(字节码文件) 中当程序编译时,运行时会被虚拟机保留, 注解在运行时可用
@Document
这是一个元注解(可定义在注解上的注解), 定义在java.lang.annotation, 表示该注解将被包含在javadoc中
@Inherited
这是一个元注解(可定义在注解上的注解), 定义在java.lang.annotation, 表示子类可以继承父类的该注解
@SpringBootApplication
- 这是一个复合注解,标注这个类是一个springboot的应用
- 等价于@Configuration、@EnableAutoConfiguration、@ComponentScan三个注解合成
- 如果要更改默认包扫描规则,在注解中添加参数
@SpringBootApplication(ScanBasePackage="指定包层级路径")
@ComponentScan(包路径)
更改默认包扫描规则, 使得对注解参数中的包路径进行扫描
@EnableAutoConfiguration
1 | 自动配置注解 |
@RequestMapping(value = “URL”, method = RequestMethod.xx, params)
配合@Controller创建一个请求映射, 通过访问url来处理请求
支持REST风格的请求映射, 使用HTTP请求动词来表示对资源的操作
1
2
3
4
5
6
7
8
9
10
public String getUser()
return "GET-张三";
}
public String saveUser(){
return "POST-张三";
}
RequestMethod枚举类参数: GET(获取), HEAD, POST(保存), PUT(修改), PATCH, DELETE(删除), OPTIONS, TRACE;
如果用来请求的前端语言不支持GET, POST以外的请求, 就要手动开启HiddenHttpMethodFilter, 并且表单method设置为post, 隐藏域_method=xx就能处理请求
1
2
3
4
5
6
7
8
9<form action="/user" method="get">
<input value="REST-GET 提交" type="submit">
</form>
<form action="/user" method="post">
<input name="_method" type="hidden" value="DELETE">
<input value="REST-DELETE 提交" type="submit">
</form>
- 详细在WebMvcAutoConfiguration的OrderedHiddenHttpMethodFilter方法中
- 手动开启HiddenHttpMethodFilter方法: 配置文件中spring: mvc: hiddenmethod: filter: enable: true开启页面表单的REST功能
REST原理(表单提交要使用REST时)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest requestToUse = request;
if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
//判断: 如果请求为POST并且请求正常
String paramValue = request.getParameter(this.methodParam);
//获取请求参数
if (StringUtils.hasLength(paramValue)) {
//判断: 如果请求参数不为空
String method = paramValue.toUpperCase(Locale.ENGLISH);
//将请求参数转换为大学
if (ALLOWED_METHODS.contains(method)) {
//判断: 查看传进来的请求参数 是否为允许的请求
//ALLOWED_METHODS: 兼容PUT DELETE PATCH
requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
//通过HttpMethodRequestWrapper对原生request进行包装
}
}
}
filterChain.doFilter((ServletRequest)requestToUse, response);
}- 表单提交时会带上
_method=PUT
参数, - 映射请求处理时先被HiddenHttpMethodFilter过滤器拦截, 并在doFilterInternal方法中先检查是不是post请求, 请求是否正常
- 之后执行request.getParameter()方法获取请求参数, 转换为大写后查看请求是否合法
- 通过HttpMethodRequestWrapper对原生request进行包装, 包装模式requestWrapper重写了getMethod方法, 过滤器链放行的时候用wrapper, 以后的方法调用getmethod是调用requesWarpper里面的
- 表单提交时会带上
REST使用客户端工具, 如PostMan直接发送Put, delete等方式请求, 无需Filter(在HTTP层,请求就已经不是post了), 此时spring: mvc: hiddenmethod: filter: enable: 就没有必要开启了
Params: 请求参数属性, 详细ctrl点击链接
headers: 请求头信息属性,详细ctrl点击链接
用于HTTP协义交互的信息被称为HTTP报文,客户端发送的HTTP报文被称为请求报文,服务器发回给客户端的HTTP报文称为响应报文,报文由报文头部和报文体组成。
请求头部(Request Headers):请求头包含许多有关客户端环境和请求正文的信息,例如浏览器支持的语言、请求的服务器地址、客户端的操作系统等。
响应头部(Rsponse Headers):响应头也包含许多有用的信息,包括服务器类型、日期、响应内容的类型及编码,响应内容的长度等等。
如果你安装的是Chrome浏览器,可以通过在网页中 F12 -> Network(网络) -> Name(名称)中点击网页—->右侧查看Headers(标头)即可
浏览器发送请求到后端时各种HTTP状态码出现原因
- 302: 客户端发生了重定向
- 400: 请求参数params错误, 表示请求报文中存在语法错误
- 404: 找不到与请求网址对应Value值的handler(资源无法访问, 多半网址写错), 或者请求头信息错误(浏览器发送的请求头不符合handler中设置的headers属性)
405: 找到了与请求网址对应Value值的handler, 但是请求的方法错误, 请求行中指定的请求方法不能被用于请求相应的资源(网址写对, 但是出现类似用POST请求访问处理GET请求的handler错误)
@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping
注解 | 等价注解 | 功能 |
---|---|---|
@GetMapping(“/user”) | @RequestMapping(value = “/user”,method = RequestMethod.GET) | 处理获取请求 |
@PostMapping(“/user”) | @RequestMapping(value = “/user”,method = RequestMethod.POST) | 处理保存请求 |
@PutMapping(“/user”) | @RequestMapping(value = “/user”,method = RequestMethod.PUT) | 处理整体修改请求 |
@DeleteMapping(“/user”) | @RequestMapping(“value=”/user”,method = RequestMethod.DELETE) | 处理删除请求 |
@PatchMapping(“/user”) | @RequestMapping(value = “/user”,method = RequestMethod.PATCH) | 处理局部修改请求 |
以上五个注解相当于精简版满足REST风格的注解
@PathVariable(“value”)
必须作用与形参上,将 URL 中占位符参数绑定到控制器处理方法的形参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx”) 绑定到操作方法的入参中。
若方法参数名称和需要绑定的url中变量名称一致时,可以简写
1
2
3
4
public String Test01({ String id)
return "success"+id;
}当方法参数名称和需要绑定的url中变量名称不一致时,写成
1
2
3
4
public String Test01({ String UserId)
return "success"+Userid;
}当参数有多个时, 此时就可以通过/Test01/001/admin这种rest风格请求方式来访问handler
1
2
3
4
public String Test01({ String id, String userName)
return "success"+id+userName;
}
@RequestParam(“value”,”name”,required=true/false,”defaultValue”)
- 将请求参数和控制器方法的形参创建映射关系, 作用与形参上, 将请求参数和形参进行匹配
- 注解的value和name属性是同义的, 都表示此形参对应的请求参数的名字
- required属性表示这个参数是否必须传输到后端中, 默认设置为true, 此时此注解作用的形参如果在请求中, 前端没有传值过来, 那么后端就会报400错误, 设置为false则传入参数不是必须的, 就不会报错
- defaultValue表示当没有传请求参数过来时, 后端参数对应形参的默认值, 只能在required属性为false的情况下使用
1 |
|
@RequestHeader(“value”,”name”,required=true/false,”defaultValue”)
- 请求头信息也是key-value的键值对, 所以可以通过@RequestParam取得这个键值对
- 将请求头信息和控制器方法的形参创建映射关系
- required, 和defaultValue的用法和@RequestParam注解相同
1 |
|
@CookieValue(“value”,”name”,required=true/false,”defaultValue”)
- @CookieValue是将cookie数据和控制器方法的形参创建映射关系
- @CookieValue注解一共有三个属性:value、required、defaultValue,用法同@RequestParam
- Cookie是客户端的技术, Session是服务器端的技术, Session依赖于Cookie
- 当服务端创建一个Session时(request.getSession()), 响应报文会携带一个Cookie(Set-Cookie: JSESSIONID=一串随机序列; )
- 创建一个Session后, 服务器还会将HttpSession对象存放到服务器维护的Map集合中, 将Cookie的value(就是那个随机序列)作为Map集合的键, 将HttpSession对象作为Map集合的值,存储在服务器内部, 再把Cookie响应到浏览器
- @CookieValue将Cookie数据和方法形参建立映射关系后, 第一次通过request.getSession()使得响应报文中有Cookie, 那么第二次及之后请求, 请求报文就会携带Cookie(第一次请求无Cookie, 这时候就能利用JSESSIONID获取Cookie中的值
1 |
|
@Configuration(proxyBeanMethods=true/false)
告诉SpringBoot这是一个配置类, 配置类也是一个组件,组件名即为类名
@Configuration注解下的配置类中使用@Bean注解在方法上给IOC容器注册bean组件
proxyBeanMethods: 自动代理属性, 用于处理依赖注入(DI)
proxyBeanMethods属性默认为true, 会保持组件单实例(保证每次拿取的配置类都是同一个)
当proxyBeanMethods属性设置为false时,每次实例出来的组件就是不同的, 当有两个bean组件A和组件B存在组件依赖时(假设组件A在执行时实例了组件B), 组件B getbean出来的对象就和组件A中实例出的组件B不是同一个组件
proxyBeanMethods当设置为true时, 会开启自动代理, 每次都会检查当前@bean注解内是否依赖了其他bean,这样会导致springboot启动加载速度较慢, 因此没有任何组件依赖的情况下, @Configuration的proxyBeanMethods属性设置为false可以提高运行速度
@Bean(“name”)
功能: 给IOC容器中添加bean组件, 用于为程序从外部环境提供对象
使用方法: /*需要类名使用了@Configuration注解*/ @Bean("组件名称") public javabean类型的对象 组件名称(){ return new javabean类型的对象("默认参数"); //根据参数执行构造方法,并返回一个对象 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 结果: 这样就能在其他类中通过ApplicationContext或ConfigurableApplicationContext先引入IOC容器后调用getbean("组件名称")方法获取对应的对象
- 查看容器内有无指定bean组件的方法: ctx.containsBean(name) 如果有组件名为name的组件这个方法就会返回true, 没有则会返回false
#### @Import({Class数组})
- 功能: 给IOC容器中添加组件, 用于为程序提供使用无参构造方法的对象(无初始默认值的方法)
- 注意: 这个注解必须放在容器组件的一个类上, 即使用了@Configuration, @Controller等注解的配置类, @Import注解需要放在这些注解的上方
- ```java
使用方法:
//参数是一个class数组,自己编写的javabean类或是外部jar包的都可以
@Import({User.class,DBHelper.class})
@Configuration
public class MyConfig {
}结果: 这样就能将组件放入IOC容器中, 只是这种方法只能调用javabean类的无参构造器
@Import导入的组件默认的名字是全类名(包名+类名)
@Conditional
- 条件注解, 当满足某个条件时, 下面的配置类才会生效
- 它有很多的子注解, 有@ConditionalOnBean(name= “组件名”),@ConditionalOnMissingBean等等
- 以@ConditionalOnBean(name= “组件名”)为例, 这个注解的作用时只有IOC容器中存在名称为”组件名”的组件时, 下面的配置类才会生效
@ImportResource(“classpath:xxx.xml”)
在spring, springMVC版本中, 将bean注册进IOC容器是采用在Resource文件夹下写xml配置来完成的, 但是springboot并不能识别这些xml文件, 此时如果springboot希望能够使用老版本的xml文件内配置信息, 就可以通过在任意配置类上通过 @ImportResource注解来导入spring配置文件, 通过xml来添加bean组件
@Componen, @Service, @Controller, @Repository
这几个注解放在一起是因为功能基本一样的,都是将类注入到spring容器中,只不过它们使用的场景不同,被@Component,@Service,@Controller,@Repository注解标注的类,这些类会被纳入进spring容器中管理。
注解 | 说明 |
---|---|
@Repository | 持久层,数据库层(dao层)注入spring容器 |
@Service | 业务逻辑层(server)注入spring容器 |
@Controller | 控制层(controller)注入spring容器 |
@Component | 普通实体类pojo注入spring容器 |
只有在容器中的组件, 才会拥有springboot提供的强大功能
pojo:
简单的java对象
@Value, @ConfigurationProperties(prefix =” name”), @PropertySource
这几个注解的作用大体是读取application.properties文件中的配置信息, 将里面的配置信息作为bean组件属性的默认值, 其中@ConfigurationProperties和@Component组合使用与@EnableConfigurationProperties均可做到自动配置
注解 | 说明 |
---|---|
@value | 用于获取bean的属性,一般用于读取配置文件的数据,作用在变量上 |
@ConfigurationProperties | 用于注入Bean属性,然后再通过当前Bean获取注入值,作用在类上(具有@Component注解的配置类上), 将此bean与配置文件前缀prefix为name的值进行绑定 |
@PropertySource | 用于指定要读取的配置文件,可以和@Value或@ConfigurationProperties配合使用 |
@EnableConfigurationProperties(xxx.class)
- 开启xxx这个javaBean的配置绑定功能(与xxx.properties这种类型的配置文件绑定)
- 把xxx这个组件自动注册到容器中
@Async、@EnableAsync
作用于方法上, 告诉spring这是一个异步任务, 比如我们在网站上发送邮件,后台会去发送邮件,此时前台会造成响应不动,直到邮件发送完毕,响应才会成功,所以我们一般会采用多线程的方式去处理这些任务。而在springboot中可以直接使用@Async注解来表明这是一个异步任务, 需要在启动类中标明@EnableAsync来开启异步注解功能, SpringBoot就会自己开一个线程池,进行调用
@Scheduled, @EnableScheduling
开启定时执行某种方法的功能, 比如每天早上自动生成日志, 这种定时任务就需要使用@Scheduled注解, 并且需要搭配cron表达式使用, 需要在启动类中表明@EnableScheduling