一、基本注解
1. Lombok
Lombok 为实体类提供一些常用的 get 与 set 方法注解,在使用相关注解前需要引入对应依赖。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
其常用的注解及其描述参考下表:
| 注解 | 作用 |
|---|---|
| @Data | 作用于类上,提供类所有字段的 get 和 set 以及 equals、toString 等方法。 |
| @NoArgsConstructor | 作用于类上,无参构造器,为实体类提供无参构造函数。 |
| @AllArgsConstructor | 作用于类上,全参构造器,为实体类提供包含全部参数的构造函数。 |
2. 异步注解
(1) @EnableAsync
作用于启动类,项目开启异步调用,通常配合 @Async 使用。
(2) @Async
作用于方法,表示调用该方法的线程与此方法异步执行。通俗的讲,当多线程同时调用多个异步方法,则不同线程之间为交替执行。
3. 缓存注解
常用的缓存注解及其描述信息参考下表:
| 方法 | 作用 |
|---|---|
| @EnableCaching | 作用于启动类,用于开启项目缓存,可以配合 Redis 进行使用。 |
| @CacheConfig | 作用于实现缓存方法的类上,通过 cacheNames 设置统一前缀。 |
| @Cacheable | 根据 Key 读取缓存,若缓存中存在数据则返回缓存数据并跳过方法执行,若缓存中不存在对应数据则继续执行方法并将结果存入缓存。 |
| @CacheEvict | 根据 Key 值删除对应缓存。 |
| @CachePut | 将方法的返回值存入缓存中,但和 @Cacheable 不同是其在方法执行之前不会进行缓存读取,只是单纯的将每次方法返回值存入缓存中。 |
| @Caching | 用于嵌套多种缓存,如同时进行多组缓存写入和删除。 |
上述注解相应的使用示例如下:
@CacheConfig(cacheNames = "users")
public class UserServiceImpl implements UserService {
@Cacheable(key = "#Id")
public User query(String Id) {
return this.userDao.query(Id);
}
@CacheEvict(key = "#user.Id")
public User update(User user) {
return this.userDao.update(user);
}
@CachePut(key = "#Id")
public User query(String Id) {
return this.userDao.query(Id);
}
@Caching(
cacheable = {
@Cacheable(key = "#Id"),
@Cacheable(key = "'list'")
},
evict = {
@CacheEvict(key = "#Id"),
@CacheEvict(key = "'list'")
},
put = {
@CachePut(key = "#Id"),
}
)
public User query(String Id) {
return this.userDao.query(Id);
}
}
二、接口设计
1、路由注解
(1) @Controller
通过视图控制器可以重定向到指定页面。
(2) @RequestMapping
提供路由信息,负责 URL 到 Controller 中的具体函数的映射,常用于页面跳转控制。
@Controller
public class UserController {
/**
* 当访问 localhost:8080/register 时触发
*/
@RequestMapping("/register")
public String toRegister() {
return "register";
}
}
(3) @RestController
@RestController 等价于 @Controller 与 @ResponseBody 的合集,用于标注控制层组件,常配合 @GetMapping 等注解用于接口开发。
@RestController
public class UserController {
/**
* 接口地址 localhost:8080/login
*/
@PostMapping("/login")
public void Login() {
// put content here
}
}
上述示例与下列代码等价,其中 @RequestMapping 也可换成 @GetMapping 等注解。
@Controller
@ResponseBody
public class UserController {
/**
* 接口地址 localhost:8080/login
*/
@RequestMapping("/login")
public void Login() {
// put content here
}
}
2、请求注解
针对 HTTP 的 GET 与 POST 等请求方式, Spring 中提供了一系列对应方式的注解。
| 注解 | 作用 |
|---|---|
| @GetMapping | 对应 HTTP 的 GET 请求,获取资源。 |
| @PostMapping | 对应 HTTP 的 POST 请求,创建资源。 |
| @PutMapping | 对应 HTTP 的 PUT 请求,提交所有资源属性以修改资源。 |
| @PatchMapping | 对应 HTTP 的 PATCH 请求,提交资源部分修改的属性。 |
| @DeleteMapping | 对应 HTTP 的 DELETE 请求,删除服务器端的资源。 |
3、参数注解
(1) 无注解
当不添加任何注解时,参数是以 Key-Value 形式拼接于请求 Url 中进行接收的,可以传空值或者什么都不传。当添加以下注解时默认参数必填。
(2) @RequestBody
前端以 JSON 对象的数据封装至请求体传输,@RequestBody 可以将其解析为实体对象,传入的对象键名必须和实体类字段名一致。
// 传入的 Json 数据
{
"Id": 1234,
"name": "Alex"
}
// 对应的实体类
public class User {
private String Id;
private String name;
}
// 接口测试类
public class TestController {
@GetMapping("/test")
public User test(@RequestBody User user) {
return user;
}
}
(3) @RequestParam
参数以 Key-Value 形式拼接于请求 Url 中,当传入多个参数时必须使用注解区分,required 用于指定该参数是否必填,默认为 true。
@GetMapping("/get")
public String demo(// 默认参数必填
@RequestParam(value = "id") String Id,
// 参数非必填
@RequestParam(value = "name", required = false) String name,
// 非必填,为空时默认值为:male
@RequestParam(value = "gender", required = false, defaultValue = "male") String gender) {
return Id + name + gender + "";
}
(4) @PathVariable
获取传入参数至地址栏,假如下面传入的参数为 user ,最终的访问 url 即为:/user。
@GetMapping("/{path}")
public int Test(@PathVariable String path){
// do something
}
三、项目配置
1. @Service
服务层注解,可以理解就是对 DAO 层进行的再次封装,封装成一个服务以供使用。
当 @Service 没有指定值默认 bean 名称与所实现的接口类一致。
/**
* 等价于 @Service("userService")
*/
@Service
public class UserServiceImpl implements UserService {
}
2. @Mapper
作用于类上,编译后为单独的接口注入容器。
@Mapper
public interface UserMapper {
}
(1) @MapperScan
作用于启动类,当工程中包含多个 Mapper 接口时,每一个都使用 @Mapper 显然过于麻烦。@MapperScan 用于指定 Mapper 所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类。
// 自动扫描包 xyz.ibudai.dao 中带 @Mapper 注解的类
@MapperScan("xyz.ibudai.dao")
public class HealthcareApplication {
public static void main(String[] args) {
SpringApplication.run(HealthcareApplication.class, args);
}
}
3. @Component
标注一个类为 Spring 容器的 Bean ,把 pojo 实例化到 spring 容器中,相当于配置文件中的 bean 注入。
在 Spring 工程中,项目的结构模型可以大致分为以下三类。在具体使用时,若业务场景都并非下述三种,为了区分业务就可以使用 @Component,但如果你在服务层不使用 @Service 偏要用 @Component ,在代码实现层面没有问题,但为了提高代码可读性及规范化,应尽量避免此类情况。
(Ⅰ) DAO 层
在这层主要负责处理数据库交互等操作,在代码实现上如果使用 JPA 的话即通过 @Repository 实现,若使用 MyBatis 则使用 @Mapper 标识。
(Ⅱ) 服务层
顾名思义,就是为数据提供服务,从数据库读取的数据大部分情况下都很难直接使用,所以这层主要负责将获取的根据需求进行变化,在代码上通常使用 @Service 注解实现。
(Ⅲ) Web 层
这一层就涉及到与前台页面数据交互,通常在该层与前端的数据规范,在代码上使用 @Controller 注解实现。