当前位置:首页 > 标签
SpringBoot 14 Spring 2 SpringMVC 3 MyBatis 2 Linux 4 阿里云 13 宝塔 1 Docker 3 ElasticSearch 2 Redis 4 Shiro 0 Dubbo 0 Swagger 0 Thymeleaf 6 数据库 11 MySQL 11 外键 2 Gradle 1 Test 0 Tomcat 1 JavaWeb 7 Ajax 1 注解 3 css 2 报错 3 多数据源 1 Java基础 1 源码 2 Servlet 1 JSP 1 环境搭建 8 RabbitMQ 1 七牛云 1 Edit.md 1 图像识别 4 英语 2 Zookeeper 1(转载)接近8000字的Spring/SpringBoot常用注解总结!安排!
- 2020-05-18
- 175
- SpringBoot
非原创
> 原文作者:SnailClimb
本文转载自:https://www.imooc.com/article/304149
## 前言
大家好,我是 Guide 哥!这是我的 221 篇优质原创文章。如需转载,请在文首注明地址,蟹蟹!
本文已经收录进我的 75K Star 的 Java 开源项目 JavaGuide:https://github.com/Snailclimb/JavaGuide
可以毫不夸张地说,这篇文章介绍的 Spring/SpringBoot 常用注解基本已经涵盖你工作中遇到的大部分常用的场景。对于每一个注解我都说了具体用法,掌握搞懂,使用 SpringBoot 来开发项目基本没啥大问题了!
整个目录如下,内容有点多:

为什么要写这篇文章?
最近看到网上有一篇关于 SpringBoot 常用注解的文章被转载的比较多,我看了文章内容之后属实觉得质量有点低,并且有点会误导没有太多实际使用经验的人(这些人又占据了大多数)。所以,自己索性花了大概 两天时间简单总结一下了。
因为我个人的能力和精力有限,如果有任何不对或者需要完善的地方,请帮忙指出!Guide 哥感激不尽!
## 1.`@ SpringBootApplication`
这里先单独拎出 `@ SpringBootApplication` 注解说一下,虽然我们一般不会主动去使用它。
Guide 哥:这个注解是 Spring Boot 项目的基石,创建 SpringBoot 项目之后会默认在主类加上。
```
@SpringBootApplication
public class SpringSecurityJwtGuideApplication {
public static void main(java.lang.String[] args) {
SpringApplication.run(SpringSecurityJwtGuideApplication.class, args);
}
}
```
我们可以把 `@ SpringBootApplication`看作是 `@ Configuration`、`@ EnableAutoConfiguration`、`@ ComponentScan` 注解的集合。
```
package org.springframework.boot.autoconfigure;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
......
}
package org.springframework.boot;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
```
根据 SpringBoot 官网,这三个注解的作用分别是:
- `@ EnableAutoConfiguration`:启用 SpringBoot 的自动配置机制
- `@ ComponentScan`: 扫描被`@ Component` (`@ Service`,`@ Controller`)注解的 bean,注解默认会扫描该类所在的包下所有的类。
- `@ Configuration`:允许在 Spring 上下文中注册额外的 bean 或导入其他配置类
## 2. Spring Bean 相关
### 2.1. `@ Autowired`
自动导入对象到类中,被注入进的类同样要被 Spring 容器管理比如:Service 类注入到 Controller 类中。
```
@Service
public class UserService {
......
}
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
......
}
```
### 2.2. `Component`,`@ Repository`,`@ Service`, `@ Controller`
我们一般使用 `@ Autowired` 注解让 Spring 容器帮我们自动装配 bean。要想把类标识成可用于 `@ Autowired` 注解自动装配的 bean 的类,可以采用以下注解实现:
- `@ Component` :通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。
- `@ Repository` : 对应持久层即 Dao 层,主要用于数据库相关操作。
- `@ Service` : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
- `@ Controller` : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。
### 2.3. `@ RestController`
`@ RestController`注解是`@ Controller`和`@ ResponseBody`的合集,表示这是个控制器 bean,并且是将函数的返回值直 接填入 HTTP 响应体中,是 REST 风格的控制器。
Guide 哥:现在都是前后端分离,说实话我已经很久没有用过`@ Controller`。如果你的项目太老了的话,就当我没说。
单独使用 `@ Controller` 不加 `@ ResponseBody`的话一般使用在要返回一个视图的情况,这种情况属于比较传统的 Spring MVC 的应用,对应于前后端不分离的情况。`@ Controller` +`@ ResponseBody` 返回 JSON 或 XML 形式数据
关于`@ RestController` 和 `@ Controller`的对比,请看这篇文章:
[@ RestController vs @ Controller](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485544&idx=1&sn=3cc95b88979e28fe3bfe539eb421c6d8&chksm=cea247a3f9d5ceb5e324ff4b8697adc3e828ecf71a3468445e70221cce768d1e722085359907&token=1725092312&lang=zh_CN#rd "66")
### 2.4. `@ Scope`
声明 Spring Bean 的作用域,使用方法:
```
@Bean
@Scope("singleton")
public Person personSingleton() {
return new Person();
}
```
四种常见的 Spring Bean 的作用域:
- singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
prototype : 每次请求都会创建一个新的 bean 实例。
- request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
- session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
### 2.5. `Configuration`
一般用来声明配置类,可以使用 @Component注解替代,不过使用Configuration注解声明配置类更加语义化。
```
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
```
## 3. 处理常见的 HTTP 请求类型
**5 种常见的请求类型:
**
- GET :请求从服务器获取特定资源。举个例子:GET /users(获取所有学生)
- POST :在服务器上创建一个新的资源。举个例子:POST /users(创建学生)
- PUT :更新服务器上的资源(客户端提供更新后的整个资源)。举个例子:PUT /users/12(更新编号为 12 的学生)
- DELETE :从服务器删除特定的资源。举个例子:DELETE /users/12(删除编号为 12 的学生)
PATCH :更新服务器上的资源(客户端提供更改的属性,可以看做作是部分更新),使用的比较少,这里就不举例子了。
### 3.1. GET 请求
@ GetMapping("users") 等价于@ RequestMapping(value="/users",method=RequestMethod.GET)
```
@GetMapping("/users")
public ResponseEntity<List<User>> getAllUsers() {
return userRepository.findAll();
}
```
### 3.2. POST 请求
@ PostMapping("users") 等价于@ RequestMapping(value="/users",method=RequestMethod.POST)
关于`@ RequestBody`注解的使用,在下面的“前后端传值”这块会讲到。
```
@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody UserCreateRequest userCreateRequest) {
return userRespository.save(user);
}
```
### 3.3. PUT 请求
@ PutMapping("/users/{userId}") 等价于@ RequestMapping(value="/users/{userId}",method=RequestMethod.PUT)
```
@PutMapping("/users/{userId}")
public ResponseEntity<User> updateUser(@PathVariable(value = "userId") Long userId,
@Valid @RequestBody UserUpdateRequest userUpdateRequest) {
......
}
```
### 3.4. DELETE 请求
@ DeleteMapping("/users/{userId}")等价于@ RequestMapping(value="/users/{userId}",method=RequestMethod.DELETE)
```
@DeleteMapping("/users/{userId}")
public ResponseEntity deleteUser(@PathVariable(value = "userId") Long userId){
......
}
```
### 3.5. PATCH 请求
一般实际项目中,我们都是 PUT 不够用了之后才用 PATCH 请求去更新数据。
```
@PatchMapping("/profile")
public ResponseEntity updateStudent(@RequestBody StudentUpdateRequest studentUpdateRequest) {
studentRepository.updateDetail(studentUpdateRequest);
return ResponseEntity.ok().build();
}
```
## 4. 前后端传值
**掌握前后端传值的正确姿势,是你开始 CRUD 的第一步!
**
### 4.1. `@ PathVariable` 和 `@ RequestParam`
`@ PathVariable`用于获取路径参数,`@ RequestParam`用于获取查询参数。
举个简单的例子:
```
@GetMapping("/klasses/{klassId}/teachers")
public List<Teacher> getKlassRelatedTeachers(
@PathVariable("klassId") Long klassId,
@RequestParam(value = "type", required = false) String type ) {
...
}
```
如果我们请求的 url 是:`/klasses/{123456}/teachers?type=web`
那么我们服务获取到的数据就是:`klassId=123456,type=web`。
### 4.2. @RequestBody
用于读取 Request 请求(可能是 POST,PUT,DELETE,GET 请求)的 body 部分并且Content-Type 为 application/json 格式的数据,接收到数据之后会自动将数据绑定到 Java 对象上去。系统会使用HttpMessageConverter或者自定义的HttpMessageConverter将请求的 body 中的 json 字符串转换为 java 对象。
我用一个简单的例子来给演示一下基本使用!
我们有一个注册的接口:
```
@PostMapping("/sign-up")
public ResponseEntity signUp(@RequestBody @Valid UserRegisterRequest userRegisterRequest) {
userService.save(userRegisterRequest);
return ResponseEntity.ok().build();
}
```
`UserRegisterRequest`对象:
```
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserRegisterRequest {
@NotBlank
private String userName;
@NotBlank
private String password;
@FullName
@NotBlank
private String fullName;
}
```
我们发送 post 请求到这个接口,并且 body 携带 JSON 数据:
```
{"userName":"coder","fullName":"shuangkou","password":"123456"}
```
这样我们的后端就可以直接把 json 格式的数据映射到我们的 UserRegisterRequest 类上。

需要注意的是:一个请求方法只可以有一个`@ RequestBody`,但是可以有多个`@ RequestParam`和`@ PathVariable`。 如果你的方法必须要用两个 `@ RequestBody`来接受数据的话,大概率是你的数据库设计或者系统设计出问题了!
## 5. 读取配置信息
很多时候我们需要将一些常用的配置信息比如阿里云 oss、发送短信、微信认证的相关配置信息等等放到配置文件中。
下面我们来看一下 Spring 为我们提供了哪些方式帮助我们从配置文件中读取这些配置信息。
我们的数据源application.yml内容如下::
```
wuhan2020: 2020年初武汉爆发了新型冠状病毒,疫情严重,但是,我相信一切都会过去!武汉加油!中国加油!
my-profile:
name: Guide哥
email: koushuangbwcx@163.com
library:
location: 湖北武汉加油中国加油
books:
- name: 天才基本法
description: 二十二岁的林朝夕在父亲确诊阿尔茨海默病这天,得知自己暗恋多年的校园男神裴之即将出国深造的消息——对方考取的学校,恰是父亲当年为她放弃的那所。
- name: 时间的秩序
description: 为什么我们记得过去,而非未来?时间“流逝”意味着什么?是我们存在于时间之内,还是时间存在于我们之中?卡洛·罗韦利用诗意的文字,邀请我们思考这一亘古难题——时间的本质。
- name: 了不起的我
description: 如何养成一个新习惯?如何让心智变得更成熟?如何拥有高质量的关系? 如何走出人生的艰难时刻?
```
### 5.1. @value(常用)
使用 `@ Value("${property}")` 读取比较简单的配置信息:
```
@Value("${wuhan2020}")
String wuhan2020;
```
### 5.2. @ ConfigurationProperties(常用)
通过`@ ConfigurationProperties`读取配置信息并与 bean 绑定。
```
@Component
@ConfigurationProperties(prefix = "library")
class LibraryProperties {
@NotEmpty
private String location;
private List<Book> books;
@Setter
@Getter
@ToString
static class Book {
String name;
String description;
}
省略getter/setter
......
}
```
你可以像使用普通的 Spring bean 一样,将其注入到类中使用。
### 5.3. PropertySource(不常用)
`@ PropertySource`读取指定 properties 文件
```
@Component
@PropertySource("classpath:website.properties")
class WebSite {
@Value("${url}")
private String url;
省略getter/setter
......
}
```
更多内容请查看我的这篇文章:
[《10 分钟搞定 SpringBoot 如何优雅读取配置文件?》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486181&idx=2&sn=10db0ae64ef501f96a5b0dbc4bd78786&chksm=cea2452ef9d5cc384678e456427328600971180a77e40c13936b19369672ca3e342c26e92b50&token=816772476&lang=zh_CN#rd)
## 6. 参数校验
.... 待完善(后面的不常用)这里就不继续写了,可以看看原文。
Servlet3.0注解分析
- 2020-04-22
- 168
- JavaWeb
在Servlet3.0出来之后,推出了几个常用的注解来帮助我们简化 web.xml 中的配置
今天我们就来总结一下这些注解的基本使用,以及和 web.xml 原来配置的对应关系。
### 都有哪些注解
要想系统的了解都有哪些注解,最好的方法就是看源码呗。
我们知道,注解时使用在Servlet类上面的,那么我们就直接点进我们导入与Servlet相关的 jar 包里面看一看。

找到 javax.servlet-api-4.0.1.jar 这个 jar 包,发现里面就有我们需要找的注解,下面我们来一一分析一下。
### @ WebServlet
- 这个注解用来标注一个 Servlet,该类需继承自 HttpServlet
- 和我们在 web.xml 中配置的 <servlet> 功能一样
> Java代码
```
@WebServlet(name = "test", urlPatterns = {"/user"})
public class UserServlet extends HttpServlet {
// 逻辑代码
}
```
> web.xml配置
```
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.linkai.servlet.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/user</url-pattern>
</servlet-mapping>
```
### @ WebFilter
- 用来配置过滤器的注解
### @ WebListener
- 用来配置监听器的注解
### @ WebInitParam
- 用来给Servlet传递参数的注解
在 @ WebServlet 中,我们看到这样一个方法
```
WebInitParam [] initParams() default {};
```
显然@ WebInitParam应该是给Servlet初始化传递参数的,而且这个参数要放在@ WebServlet里面 未完,待续。。。666
SpringBoot项目中Ajax详解,结合@RequestBody和@ResponseBody
- 2020-04-14
- 183
- SpringBoot
### 基本介绍
@ ResponseBody 和 @ RequestBody 经常在 Controller 层中使用,今天就结合Ajax来详解的介绍一下这两个注解。
#### @ RequestBody 用在参数前面
#####(1)前端Ajax传递的是JSON字符串
当前端发送的Ajax请求是传递的数据data是一个**JSON字符串**时,后端 Controller 层就可以使用 **@ ResponseBody** 注解结合 **Map** 来接收参数。
> 前端
```
var inputTextObj = {
"text": inputText
};
$.ajax("/admin/tagGetSearchResult", {
type: 'post',
dataType: 'json',
data: JSON.stringify(inputTextObj), //转换为字符串
contentType : "application/json", // 记得加上这个
});
```
> 后端
```
@RequestMapping("/tagGetSearchResult")
@ResponseBody
public String getSearchResult(@RequestBody HashMap<String, String> map) {
String inputText = map.get("text"); // 获得Map里面的值(inputText)
List<Tag> tags = tagService.queryLike(inputText);
String str = JSON.toJSONString(tags);
return str;
}
```
#####(2)前端Ajax传递的是JSON对象
如果发送的Ajax的data是JSON对象,则后端可以直接使用 @ RequestParam 注解来接收参数,不需要使用 @ ResponseBody
> 前端
```
var dataObj = {
"title": $('#article-title').val(),
"blogid": tempBid,
"my-editormd-markdown-doc": $("#my-editormd-markdown-doc").text(),
"type": $('#my-type').val(),
"original": original + '',
"ifComment": ifComment + '',
"tag": tagNames, // 标签名称
"published": '0',
};
$.ajax("/admin/updateBlog", {
type: "POST",
data: dataObj, // 注意:这里传递的是一个 json 对象,后端需要利用 @RequestParam 注解
dataType: "text", // 返回的类型为纯文本字符串类型
traditional: true,
});
```
> 后端
```
@RequestMapping("/updateBlog")
@ResponseBody
public String updateBlog(@RequestParam("blogid") String bid,
@RequestParam("title") String title,
@RequestParam("my-editormd-markdown-doc") String bcontent,
@RequestParam("type") String typeName,
@RequestParam("original") String orginal,
@RequestParam("ifComment") String ifComment,
@RequestParam("tag") String[] tags,
@RequestParam("published") String published) {
// 逻辑代码...
}
```
#### @ ResponseBody 用在方法前面
表示直接返回一个字符串,处理Ajax请求时,如果后端查询出来的是一个 List 集合,那么可以转换为 JSON 字符串,结合 @ ResponseBody 返回。
- 具体可以看上面第(1)小点的后端代码
- 上面的 `JSON.toJSONString(tags);` 的 JSON 是使用的阿里巴巴的 FastJson,需要导入对应的依赖,如下:
```
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
```