微服务这块虽然还没看完, 但是想先把springboot再看一遍后,再去继续学习微服务
项目架构
这是一个多模块Maven项目,采用分层架构:
- sky-common: 公共模块,包含工具类、配置等
- sky-pojo: 实体类模块,包含DTO、VO、Entity等
- sky-server: 核心业务模块,包含Controller、Service、Mapper等
项目细解
启动顺序
-
main → SpringApplication.run
-
扫包 → 发现 @Configuration → 实例化配置类 → 调用 @Bean
-
启动内嵌 Tomcat → DispatcherServlet 注册完成
-
项目可对外提供服务
sky-common模块(公共模块)
constant/: 常量定义
context/: 上下文管理
基础上下文,存储当前线程用户信息
exception/: 自定义异常类
- 包含账号锁定、账号未找到、登录失败等各种业务异常
- 都是继承自RuntimeException,因为java中只有这个类及其子类才是“非受检异常”,不需要显示捕获或声明抛出,而对其他类,编译器会强制检查。
- 用RuntimeException是为了让业务异常“可抛可不捕”,由调用者或全局处理器决定是否处理,避免代码被try-catch淹没
json/: java对象和字符串之间的序列化和反序列化
result/: 结果响应类
utils/: 工具类
JWT工具类
-
createJWT
:用密钥 + 业务数据 → 生成一条防篡改的 Token。 -
parseJWT
:用同样的密钥 → 验证 Token 合法性并取出业务数据。 -
-
-
-
HTTP 请求工具类
HttpClientUtil
是 “项目中所有后端 HTTP 调用的统一交通工具”。- 无论是 调用微信支付、查询物流、请求第三方地图接口、还是内部微服务通信,都靠它完成 GET/POST(表单或 JSON)。
- 它是 “后端项目里的 Postman” —— 任何需要 向外发 HTTP 请求 的地方,都会先想到
HttpClientUtil
。
sky-pojo模块(数据模型模块)
“前端要看的包装成 VO,网络要传的包装成 DTO,数据库表的影子叫 DO/PO,夹在中间跑业务的叫 BO,仓库操作靠 DAO,不想引框架就是 POJO。”
dto/: 数据传输对象
用于不同层之间传输数据,减少接口调用次数
entity/: 实体类
与PO类似,与数据库表结构一一对应
vo/: 视图对象
主要用于前端展示层,封装展示所需的数据
sky-server模块(核心业务模块)
controller/: 控制器
常用注解
功能分组 | 注解 | 作用(专业术语) |
---|---|---|
启动与配置 | @SpringBootApplication | 聚合 @Configuration + @EnableAutoConfiguration + @ComponentScan ,用于启动 Spring Boot 应用。 |
@Configuration | 声明当前类为配置类,内部可定义 @Bean 方法。 | |
@Bean | 将方法返回对象注册为 Spring IoC 容器管理的单例 Bean。 | |
@Value | 将配置文件中的属性值注入到字段或方法参数。 | |
@ConfigurationProperties | 将指定前缀的配置批量绑定到 POJO 并注册为 Bean。 | |
组件声明 | @RestController | 组合 @Controller + @ResponseBody ,控制器方法返回值直接序列化为 JSON。 |
@Controller | 声明控制器层组件,配合视图解析器返回页面。 | |
@Service | 标记业务逻辑层组件,语义化别名。 | |
@Repository | 标记持久层组件,并启用异常转换。 | |
@Component | 通用型组件声明,可被组件扫描。 | |
HTTP 映射 | @RequestMapping | 通用请求映射,可细化方法/路径/媒体类型。 |
@GetMapping | RequestMethod.GET 快捷映射。 | |
@PostMapping | RequestMethod.POST 快捷映射。 | |
@PutMapping | RequestMethod.PUT 快捷映射。 | |
@DeleteMapping | RequestMethod.DELETE 快捷映射。 | |
@PatchMapping | RequestMethod.PATCH 快捷映射。 | |
参数绑定 | @PathVariable | 将 URI 模板变量绑定到方法参数。 |
@RequestParam | 将查询参数或表单字段绑定到方法参数。 | |
@RequestBody | 将 HTTP 请求体反序列化为 Java 对象。 | |
@RequestHeader | 将指定请求头值绑定到方法参数。 | |
@CookieValue | 将指定 Cookie 值绑定到方法参数。 | |
异常处理 | @ControllerAdvice | 定义全局异常处理类,跨控制器生效。 |
@ExceptionHandler | 标注异常处理方法,捕获指定异常。 | |
@ResponseStatus | 指定异常时返回的 HTTP 状态码。 | |
依赖注入 | @Autowired | 按类型自动装配 Bean。 |
@Qualifier | 指定 Bean 名称,解决同类型多 Bean 冲突。 | |
@Resource | JSR-250 按名称装配 Bean。 | |
事务与缓存 | @Transactional | 声明式事务边界,方法级或类级。 |
@Cacheable | 方法结果缓存,下次调用直接返回缓存值。 | |
生命周期 | @PostConstruct | 在 Bean 初始化完成后执行。 |
@PreDestroy | 在 Bean 销毁前执行。 | |
MyBatis | @Mapper | 标记接口为 MyBatis Mapper,自动生成代理实现。 |
@Param | 为 Mapper 接口多参数指定命名。 | |
AOP | @Aspect | 声明切面类,定义横切关注点。 |
@Before | 前置通知,方法执行前织入。 | |
@Around | 环绕通知,可控制方法是否执行。 | |
跨域与 WebSocket | @CrossOrigin | 允许跨域请求,可细化到方法级。 |
@EnableWebSocketMessageBroker | 启用 STOMP 消息代理,支持 WebSocket。 |
自动注入
@Autowired
把 接口变量 注入成 实现类对象;
实现类靠 @Service
(或 @Component
)被 Spring 扫描注册,运行时通过 JDK 动态代理或 CGLIB 完成注入
如果抽象类(接口)有多个实现类,可以通过 @Qualifier
指定具体注入哪个实现类
service/: 业务逻辑层
各种业务接口及其实现类
PageHelper
PageHelper.startPage(...)
是让 下一条 SQL 自动带 LIMIT offset, size
的启动器,拦截 MyBatis 的 SQL 执行器并追加分页语句。
mapper/: 数据访问层
包含各种数据库操作接口和XML映射文件
都是抽象类,接口,
interceptor/: 拦截器
静态请求:
浏览器要的只是“现成的文件”,服务器不用做任何运算,直接把文件内容原样发回去即可,比如css、js、png文件,这些文件通常放在resources/static目录下
动态请求:
浏览器要的并不是“现成的文件”,而是需要服务器先运行一段java(controller方法)才能生成并返回结果。
-
拦截器写在代码里只想拦“需要登录权限”的接口(动态请求)。
-
如果静态资源(.js、.css、*.png)也被拦,浏览器就加载不到样式和图片,页面会“裸奔
config/: 配置类
注册自定义拦截器、静态资源映射等
handler/:异常处理类
注解 | 适用范围 | 说明 | 常见用法示例 | 备注 |
---|---|---|---|---|
@RestControllerAdvice | 所有 @RestController | 全局异常 + 全局数据绑定 + 全局数据预处理,返回值直接写进 HTTP 响应体(相当于 @ControllerAdvice + @ResponseBody)。 | @RestControllerAdvice | 写 REST API 最常用。 |
@ControllerAdvice | 所有 @Controller | 与上面功能相同,但返回值默认走视图解析器(如 JSP、Thymeleaf)。 | @ControllerAdvice | 传统 MVC(页面渲染)场景用。 |
@ExceptionHandler | 单个类内部 | 写在某个 Controller 内部的方法上,只对该 Controller 生效。 | @PostMapping("/login") | 粒度最细,只适合局部异常。 |
@ResponseStatus | 单个异常类 | 直接标在自定义异常类上,遇到该异常就返回指定的 HTTP 状态码及原因短语。 | @ResponseStatus(code = HttpStatus.CONFLICT, reason = "用户名已存在") | 简单场景,无需额外类。 |
@ResponseBody | 方法级 | 与 @ControllerAdvice 或 @ExceptionHandler 搭配,让异常处理方法的返回值直接写进 HTTP 响应体。 | @ControllerAdvice | 等同于 @RestControllerAdvice 。 |
@RestControllerAdvice(basePackages = "...") | 指定包范围 | 只拦截指定包下的控制器,缩小粒度。 | @RestControllerAdvice(basePackages = "com.sky.admin") | 多模块项目常用。 |
aspect/: 切面类
- @Aspect :告诉Spring“这是个切面”
-
@Aspect
+@Component
组合后,Spring 启动时会把它注册成 Bean,并织入到目标方法调用链里。 -
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
表示:拦截com.sky.mapper
包下所有类的所有方法,再加一个条件:方法上必须带着@AutoFill
注解。
annotation/: 自定义注解
1、@Target(METHOD)
约束它只能出现在方法级别;
@Retention(RUNTIME)
保证该注解会被编译进 .class
文件,并且在运行时通过反射可读。
因此,AutoFill
成为一个“可反射的元数据标记”。
2、使用时:@AutoFill(value= OperationType.UPDATE) 注解在方法上
3、@AutoFill
只是一个“标记”,真正让它产生自动填充行为的是切面(Aspect)——切面在运行期扫描到这个标记后,根据 value()
的值做对应的字段填充。
4、所以注解提供“声明”,切面完成“行为”;两者协作实现“声明式自动填充”。