Springboot+Vue博客项目总结
文章目录
Springboot+Vue博客项目总结
1.工程搭建
1.1 新建maven工程
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.mszlu<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>blog-parent<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.0-SNAPSHOT<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>parent</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-parent<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>2.5.0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>relativePath</span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>parent</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>properties</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>project.build.sourceEncoding</span><span class="token punctuation">></span></span>UTF-8<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>project.build.sourceEncoding</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>project.reporting.outputEncoding</span><span class="token punctuation">></span></span>UTF-8<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>project.reporting.outputEncoding</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>java.version</span><span class="token punctuation">></span></span>1.8<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>java.version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>properties</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependencies</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token comment"><!-- 排除 默认使用的logback --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>exclusions</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>exclusion</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-logging<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>exclusion</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>exclusions</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token comment"><!-- log4j2 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-log4j2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-aop<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-mail<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-web<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-test<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>scope</span><span class="token punctuation">></span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>scope</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-data-redis<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.alibaba<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>fastjson<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.2.76<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>mysql<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mysql-connector-java<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-configuration-processor<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>optional</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>optional</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.apache.commons<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>commons-lang3<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>commons-collections<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>commons-collections<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>3.2.2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.baomidou<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mybatis-plus-boot-starter<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>3.4.3<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.projectlombok<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>lombok<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token comment"><!-- https://mvnrepository.com/artifact/joda-time/joda-time --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>joda-time<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>joda-time<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>2.10.10<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependencies</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>build</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>plugins</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>plugin</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-maven-plugin<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>plugin</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>plugins</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>build</span><span class="token punctuation">></span></span>
</project>
1.2 application.properties配置
#server
server.port= 8888
spring.application.name=mszlu_blog
# datasource
spring.datasource.url=jdbc:mysql://localhost:3306/blogxpp?useUnicode=true&characterEncoding=UTF-8&serverTimeZone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#mybatis-plus
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#定义前缀表名,因为数据库中的表带ms_。这样实体类的表不用加前缀就可以匹配
mybatis-plus.global-config.db-config.table-prefix=ms_
1.3 配置分页插件
不知道的可以查看MyBatis-Plus官网关于分页插件的介绍
@Configuration
//扫包,将此包下的接口生成代理实现类,并且注册到spring容器中
@MapperScan("com.xpp.blog.dao.mapper")
public class MybatisPlusConfig {
//集成分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
1.4 配置解决跨域
解决跨域问题可以参考:SpringBoot解决跨域的5种方式
前后端端口不一样,需要解决跨域问题。
这里解决的方法是重写WebMvcConfigurer
:
@Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private LoginInterceptor loginInterceptor;
<span class="token comment">//跨域配置,前端和后端端口不一样</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">addCorsMappings</span><span class="token punctuation">(</span><span class="token class-name">CorsRegistry</span> registry<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//8080前端使用的端口号</span> registry<span class="token punctuation">.</span><span class="token function">addMapping</span><span class="token punctuation">(</span><span class="token string">"/**"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">allowedOrigins</span><span class="token punctuation">(</span><span class="token string">"http://localhost:8080"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
1.5 添加启动类
@SpringBootApplication
public class BlogApp {
public static void main(String[] args) {
SpringApplication.run(BlogApp.class,args);
}
}
2.统一异常处理
不管是controller
层还是service
,dao
层,都有可能报异常,如果是预料中的异常,可以直接捕获处理,如果是意料之外的异常,需要统一进行处理,进行记录,并给用户提示相对比较友好的信息。
@ControllerAdvice
:对加了@Controller
的方法进行拦截处理,AOP的实现@ExceptionHandler
:统一处理某一类异常,从而减少代码重复率和复杂度,比如要获取自定义异常可以@ExceptionHandler(BusinessException.class)
//作用:对加了@Controller的方法进行拦截处理,AOP的实现
@ControllerAdvice
public class AllExceptionHandler {
//进行一次处理,处理Exception.class的异常
@ExceptionHandler(Exception.class)
//返回json数据,不加的话直接返回页面
@ResponseBody
public Result doException(Exception e){
e.printStackTrace();
return Result.fail(-999,"系统异常");
}
}
3.登录功能实现
3.1 接口说明
接口url:/login
请求方式:POST
请求参数:
参数名称 | 参数类型 | 说明 |
---|---|---|
account | string | 账号 |
password | string | 密码 |
返回数据:
{
"success": true,
"code": 200,
"msg": "success",
"data": "token"
}
3.2 JWT
可以参考:JWT整合Springboot
登录使用JWT
技术:
- jwt 可以生成 一个加密的
token
,做为用户登录的令牌,当用户登录成功之后,发放给客户端。 - 请求需要登录的资源或者接口的时候,将
token
携带,后端验证token
是否合法。
jwt 有三部分组成:A.B.C
- A:
Header
,{“type”:“JWT”,“alg”:“HS256”} 固定 - B:
playload
,存放信息,比如,用户id,过期时间等等,可以被解密,不能存放敏感信息 - C:
签证
,A和B加上秘钥加密而成,只要秘钥不丢失,可以认为是安全的。
jwt 验证,主要就是验证C部分是否合法。
依赖包:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
工具类:
public class JWTUtils { //密钥 private static final String jwtToken = "123456Mszlu!@#$$";
<span class="token comment">//生成token</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">createToken</span><span class="token punctuation">(</span><span class="token class-name">Long</span> userId<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span><span class="token class-name">Object</span><span class="token punctuation">></span></span> claims <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> claims<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">"userId"</span><span class="token punctuation">,</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">JwtBuilder</span> jwtBuilder <span class="token operator">=</span> <span class="token class-name">Jwts</span><span class="token punctuation">.</span><span class="token function">builder</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">signWith</span><span class="token punctuation">(</span><span class="token class-name">SignatureAlgorithm</span><span class="token punctuation">.</span>HS256<span class="token punctuation">,</span> jwtToken<span class="token punctuation">)</span> <span class="token comment">// 签发算法,秘钥为jwtToken</span> <span class="token punctuation">.</span><span class="token function">setClaims</span><span class="token punctuation">(</span>claims<span class="token punctuation">)</span> <span class="token comment">// body数据,要唯一,自行设置</span> <span class="token punctuation">.</span><span class="token function">setIssuedAt</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 设置签发时间</span> <span class="token punctuation">.</span><span class="token function">setExpiration</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">24</span> <span class="token operator">*</span> <span class="token number">60</span> <span class="token operator">*</span> <span class="token number">60</span> <span class="token operator">*</span> <span class="token number">60</span> <span class="token operator">*</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 一天的有效时间</span> <span class="token class-name">String</span> token <span class="token operator">=</span> jwtBuilder<span class="token punctuation">.</span><span class="token function">compact</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> token<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//检查token是否合法</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span> <span class="token function">checkToken</span><span class="token punctuation">(</span><span class="token class-name">String</span> token<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">Jwt</span> parse <span class="token operator">=</span> <span class="token class-name">Jwts</span><span class="token punctuation">.</span><span class="token function">parser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setSigningKey</span><span class="token punctuation">(</span>jwtToken<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token class-name">Map</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span><span class="token punctuation">)</span> parse<span class="token punctuation">.</span><span class="token function">getBody</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">String</span> token<span class="token operator">=</span><span class="token class-name">JWTUtils</span><span class="token punctuation">.</span><span class="token function">createToken</span><span class="token punctuation">(</span><span class="token number">100L</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span> map <span class="token operator">=</span> <span class="token class-name">JWTUtils</span><span class="token punctuation">.</span><span class="token function">checkToken</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>map<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"userId"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
3.3 Controller
@RestController
@RequestMapping("login")
public class loginController {
@Autowired
private LoginService loginService;
@PostMapping
public Result login(@RequestBody LoginParam loginParam){
//登录->验证用户
return loginService.login(loginParam);
}
}
3.4 Service
关于这里StringUtils的用法:Java之StringUtils的常用方法
md5加密的依赖包:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
@Service public class LoginServiceImpl implements LoginService { @Autowired private SysUserService sysUserService;
<span class="token annotation punctuation">@Autowired</span> <span class="token keyword">private</span> <span class="token class-name">RedisTemplate</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">></span></span> redisTemplate<span class="token punctuation">;</span> <span class="token comment">//加密盐</span> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> slat <span class="token operator">=</span> <span class="token string">"mszlu!@#"</span><span class="token punctuation">;</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token class-name">Result</span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token class-name">LoginParam</span> loginParam<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//1.检查参数是否合法</span> <span class="token class-name">String</span> account <span class="token operator">=</span> loginParam<span class="token punctuation">.</span><span class="token function">getAccount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">String</span> password <span class="token operator">=</span> loginParam<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isBlank</span><span class="token punctuation">(</span>account<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isAllBlank</span><span class="token punctuation">(</span>password<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token class-name">ErrorCode</span><span class="token punctuation">.</span>PARAMS_ERROR<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">ErrorCode</span><span class="token punctuation">.</span>PARAMS_ERROR<span class="token punctuation">.</span><span class="token function">getMsg</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//用md5加密</span> password <span class="token operator">=</span> <span class="token class-name">DigestUtils</span><span class="token punctuation">.</span><span class="token function">md5Hex</span><span class="token punctuation">(</span>password <span class="token operator">+</span> slat<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//2.根据用户名何密码去user表中查询 是否存在</span> <span class="token class-name">SysUser</span> sysUser <span class="token operator">=</span> sysUserService<span class="token punctuation">.</span><span class="token function">findUser</span><span class="token punctuation">(</span>account<span class="token punctuation">,</span> password<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//3.如果不存在 登录失败</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>sysUser <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token class-name">ErrorCode</span><span class="token punctuation">.</span>ACCOUNT_PWD_NOT_EXIST<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">ErrorCode</span><span class="token punctuation">.</span>ACCOUNT_PWD_NOT_EXIST<span class="token punctuation">.</span><span class="token function">getMsg</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//4.如果存在 使用jwt 生成token 返回给前端</span> <span class="token class-name">String</span> token <span class="token operator">=</span> <span class="token class-name">JWTUtils</span><span class="token punctuation">.</span><span class="token function">createToken</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//5.toekn放入redis,设置过期时间。登录认证的时候先认证token字符串是否合法,在认证redsi认证是否合法</span> redisTemplate<span class="token punctuation">.</span><span class="token function">opsForValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"TOKEN_"</span> <span class="token operator">+</span> token<span class="token punctuation">,</span> JSON<span class="token punctuation">.</span><span class="token function">toJSONString</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span>DAYS<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
/**
* 根据account和password查询用户表
* @param account
* @param password
* @return
*/
@Override
public SysUser findUser(String account, String password) {
LambdaQueryWrapper<SysUser> queryWrapper=new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getAccount,account);
queryWrapper.eq(SysUser::getPassword,password);
//需要id,account,头像avatar,naickname昵称
queryWrapper.select(SysUser::getId,SysUser::getAccount,SysUser::getAvatar,SysUser::getNickname);
queryWrapper.last("limit 1");
SysUser sysUser = sysUserMapper.selectOne(queryWrapper);
return sysUser;
}
3.5 登录参数,redis配置
接受前端传来的登录参数:
@Data public class LoginParam {
<span class="token keyword">private</span> <span class="token class-name">String</span> account<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">String</span> password<span class="token punctuation">;</span>
}
配置redis:
spring.redis.host=localhost
spring.redis.port=6379
5.获取用户信息
5.1 接口说明
接口url:/users/currentUser
请求方式:GET
请求参数:
参数名称 | 参数类型 | 说明 |
---|---|---|
Authorization | string | 头部信息(TOKEN) |
返回数据:
{
"success": true,
"code": 200,
"msg": "success",
"data": {
"id":1,
"account":"1",
"nickaname":"1",
"avatar":"ss"
}
}
5.2 Controller
@RestController @RequestMapping("users") public class UserController { @Autowired private SysUserService sysUserService;
<span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">"currentUser"</span><span class="token punctuation">)</span> <span class="token keyword">public</span> <span class="token class-name">Result</span> <span class="token function">currentUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@RequestHeader</span><span class="token punctuation">(</span><span class="token string">"Authorization"</span><span class="token punctuation">)</span> <span class="token class-name">String</span> token<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> sysUserService<span class="token punctuation">.</span><span class="token function">findUserByToken</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
5.3 Service
/** * 根据token查询用户信息 * @param token * @return */ @Override public Result findUserByToken(String token) { /** * 1.token合法性校验:是否为空,解析是否成功,redis是否存在 * 2.如果校验失败,返回错误 * 3.如果成功,返回对应的结果 LoginUserVo */
<span class="token class-name">SysUser</span> sysUser<span class="token operator">=</span>loginService<span class="token punctuation">.</span><span class="token function">checkToken</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span>sysUser<span class="token operator">==</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token class-name">ErrorCode</span><span class="token punctuation">.</span>TOKEN_ERROR<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">,</span><span class="token class-name">ErrorCode</span><span class="token punctuation">.</span>TOKEN_ERROR<span class="token punctuation">.</span><span class="token function">getMsg</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token class-name">LoginUserVo</span> loginUserVo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LoginUserVo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> loginUserVo<span class="token punctuation">.</span><span class="token function">setId</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> loginUserVo<span class="token punctuation">.</span><span class="token function">setNickname</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">.</span><span class="token function">getNickname</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> loginUserVo<span class="token punctuation">.</span><span class="token function">setAccount</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">.</span><span class="token function">getAccount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> loginUserVo<span class="token punctuation">.</span><span class="token function">setAvatar</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">.</span><span class="token function">getAvatar</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span>loginUserVo<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
/**
* 校验token是否合法
*
* @param token
* @return
*/
@Override
public SysUser checkToken(String token) {
if (StringUtils.isAllBlank(token)) {
return null;
}
Map<String, Object> stringObjectMap = JWTUtils.checkToken(token);
if (stringObjectMap == null) {
return null;
}
String userJson = redisTemplate.opsForValue().get("TOKEN_" + token);
if (StringUtils.isBlank(userJson)) {
return null;
}
SysUser sysUser = JSON.parseObject(userJson, SysUser.class);
return sysUser;
}
6.登录拦截器
每次访问需要登录的资源的时候,都需要在代码中进行判断,一旦登录的逻辑有所改变,代码都得进行变动,非常不合适。
那么可不可以统一进行登录判断呢?
可以,使用拦截器,进行登录拦截,如果遇到需要登录才能访问的接口,如果未登录,拦截器直接返回,并跳转登录页面。
6.1 拦截器实现
@Slf4j @Component public class LoginInterceptor implements HandlerInterceptor { @Autowired private LoginService loginService;
<span class="token comment">/** * 在执行controlle方法之前执行 * * @param request * @param response * @param handler * @return * @throws Exception */</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">preHandle</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> request<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> response<span class="token punctuation">,</span> <span class="token class-name">Object</span> handler<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">/** * 1、需要判断请求的接口和路径是否为 HandlerMethod(controller方法) * 2、如果token是否为空,如果为空,为登录 * 3、如果token不为空,登录验证 loginService->checkToken * 4、如果认证成功,放行 */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token punctuation">(</span>handler <span class="token keyword">instanceof</span> <span class="token class-name">HandlerMethod</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//handler可能是RequestResourceHandler 放行</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token class-name">String</span> token <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token string">"Authorization"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"=================request start==========================="</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">String</span> requestURI <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getRequestURI</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"request uri:{}"</span><span class="token punctuation">,</span> requestURI<span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"request method:{}"</span><span class="token punctuation">,</span> request<span class="token punctuation">.</span><span class="token function">getMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"token:{}"</span><span class="token punctuation">,</span> token<span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"=================request end==========================="</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isBlank</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//未登录</span> <span class="token class-name">Result</span> result <span class="token operator">=</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token class-name">ErrorCode</span><span class="token punctuation">.</span>NO_LOGIN<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"未登录"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> response<span class="token punctuation">.</span><span class="token function">setContentType</span><span class="token punctuation">(</span><span class="token string">"application/json;charset=utf-8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> response<span class="token punctuation">.</span><span class="token function">getWriter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>JSON<span class="token punctuation">.</span><span class="token function">toJSONString</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token class-name">SysUser</span> sysUser <span class="token operator">=</span> loginService<span class="token punctuation">.</span><span class="token function">checkToken</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>sysUser <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//未登录</span> <span class="token class-name">Result</span> result <span class="token operator">=</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token class-name">ErrorCode</span><span class="token punctuation">.</span>NO_LOGIN<span class="token punctuation">.</span><span class="token function">getCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"未登录"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> response<span class="token punctuation">.</span><span class="token function">setContentType</span><span class="token punctuation">(</span><span class="token string">"application/json;charset=utf-8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> response<span class="token punctuation">.</span><span class="token function">getWriter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>JSON<span class="token punctuation">.</span><span class="token function">toJSONString</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//登录验证成功</span> <span class="token comment">//用ThreadLocal保存用户信息</span> <span class="token class-name">UserThreadLocal</span><span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">afterCompletion</span><span class="token punctuation">(</span><span class="token class-name">HttpServletRequest</span> request<span class="token punctuation">,</span> <span class="token class-name">HttpServletResponse</span> response<span class="token punctuation">,</span> <span class="token class-name">Object</span> handler<span class="token punctuation">,</span> <span class="token class-name">Exception</span> ex<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//如果不删除,ThreaLocal中用完的信息会有内存泄漏的风险</span> <span class="token class-name">UserThreadLocal</span><span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
6.2 使拦截器生效
@Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private LoginInterceptor loginInterceptor;
<span class="token comment">//跨域配置,前端和后端端口不一样</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">addCorsMappings</span><span class="token punctuation">(</span><span class="token class-name">CorsRegistry</span> registry<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> registry<span class="token punctuation">.</span><span class="token function">addMapping</span><span class="token punctuation">(</span><span class="token string">"/**"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">allowedOrigins</span><span class="token punctuation">(</span><span class="token string">"http://localhost:8080"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//使拦截器生效</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">addInterceptors</span><span class="token punctuation">(</span><span class="token class-name">InterceptorRegistry</span> registry<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//拦截test接口,后续实际遇到需要拦截的接口时,在配置为真正的拦截接口</span> registry<span class="token punctuation">.</span><span class="token function">addInterceptor</span><span class="token punctuation">(</span>loginInterceptor<span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">addPathPatterns</span><span class="token punctuation">(</span><span class="token string">"/test"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
测试:
@RestController @RequestMapping("test") public class TestController {
<span class="token annotation punctuation">@RequestMapping</span> <span class="token keyword">public</span> <span class="token class-name">Result</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
7.ThreadLocal保存用户信息
public class UserThreadLocal { private UserThreadLocal(){
<span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">ThreadLocal</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">SysUser</span><span class="token punctuation">></span></span> LOCAL<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">ThreadLocal</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//存入</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token class-name">SysUser</span> sysUser<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> LOCAL<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>sysUser<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//取出</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">SysUser</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> LOCAL<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//删除</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> LOCAL<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
8. 使用线程池更新阅读次数
可以参考:在SpringBoot中实现异步事件驱动
8.1 线程池配置
@ControllerAdvice
@EnableAsync //开启多线程
public class ThreadPoolConfig {
@Bean("taskExecutor")
public Executor asyncServiceExecutor(){
ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
//设置核心线程数
executor.setCorePoolSize(5);
//设置最大线程数
executor.setMaxPoolSize(20);
//设置队列大小
executor.setQueueCapacity(Integer.MAX_VALUE);
//设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
//设置默认线程名称
executor.setThreadNamePrefix("小皮皮博客项目");
//等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
//执行初始化
executor.initialize();
return executor;
}
}
8.2 使用
@Autowired
private ThreadService threadService;
/**
-
查看文章详情
-
@param articleId
-
@return
*/
@Override
public Result findArticleById(Long articleId) {
Article article = articleMapper.selectById(articleId);ArticleVo articleVo = copy(article, true, true, true, true);
//查看完文章了,新增阅读数,有没有问题呢?
//查看完文章之后,本应该直接返回数据了,这时候做了一个更新操作,更新时加写锁,阻塞其他的读操作,性能就会比较低(没办法解决,增加阅读数必然要加锁)//更新增加了此次接口的耗时(考虑减少耗时)如果一旦更新出问题,不能影响查看操作
//线程池解决,可以吧更新操作更新到主线程中执行,和主线程就不相关了
threadService.updateArticleViewCount(articleMapper, article);
return Result.success(articleVo);
}
@Component
public class ThreadService {
//如果我们想在调用一个方法的时候开启一个新的线程开始异步操作,我们只需要在这个方法上加上@Async注解,当然前提是,这个方法所在的类必须在Spring环境中。
@Async("taskExecutor")
//期望此操作在线程池执行。不会影响原有的主线程
public void updateArticleViewCount(ArticleMapper articleMapper, Article article) {
Article articleUpdate = new Article();
int viewCounts = article.getViewCounts();
articleUpdate.setViewCounts(viewCounts + 1);
LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Article::getId, article.getId());
//为了在多线程的环境下,线程安全 CAS思想,防止此时修改的时候已经被修改了(乐观锁)
queryWrapper.eq(Article::getViewCounts, viewCounts);
//第一个参数用于生成set条件,第二个生成where语句
//update article set view_count =100 where view_count==99 and id =xxx
articleMapper.update(articleUpdate, queryWrapper);
try {
Thread.sleep(5000);
System.out.println("更新完成了!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这里的update
用法:
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
参数说明:
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 (set 条件值,可为 null) |
Wrapper | updateWrapper | 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) |
@Async
注解:如果我们想在调用一个方法的时候开启一个新的线程开始异步操作,我们只需要在这个方法上加上@Async
注解,当然前提是,这个方法所在的类必须在Spring环境中。
9.评论
9.1 接口说明
接口url:/comments/create/change
请求方式:POST
请求参数:
参数名称 | 参数类型 | 说明 |
---|---|---|
articleId | long | 文章id |
content | string | 评论内容 |
parent | long | 父评论id |
toUserId | long | 被评论的用户id |
返回数据:
{
"success": true,
"code": 200,
"msg": "success",
"data": null
}
9.2 加入到登录拦截器中
@Override
public void addInterceptors(InterceptorRegistry registry) {
//拦截test接口,后续实际遇到需要拦截的接口时,在配置为真正的拦截接口
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/test").addPathPatterns("/comments/create/change");
}
9.3 Controller
构建评论参数对象:
package com.mszlu.blog.vo.params;
import lombok.Data;
@Data
public class CommentParam {
<span class="token keyword">private</span> <span class="token class-name">Long</span> articleId<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token class-name">String</span> content<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token class-name">Long</span> parent<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token class-name">Long</span> toUserId<span class="token punctuation">;</span>
}
@PostMapping("create/change")
public Result comment(@RequestBody CommentParam commentParam){
return commentsService.comment(commentParam);
}
9.4 Service
@Override
public Result comment(CommentParam commentParam) {
SysUser sysUser = UserThreadLocal.get();
Comment comment = new Comment();
comment.setArticleId(commentParam.getArticleId());
comment.setAuthorId(sysUser.getId());
comment.setContent(commentParam.getContent());
comment.setCreateDate(System.currentTimeMillis());
Long parent = commentParam.getParent();
if(parent==null||parent==0){
comment.setLevel(1);
}else{
comment.setLevel(2);
}
comment.setParentId(parent==null?0:parent);
Long toUserId = commentParam.getToUserId();
comment.setToUid(toUserId==null?0:toUserId);
commentMapper.insert(comment);
return Result.success(null);
}
//防止前端 精度损失 把id转为string
//分布式id 比较长,传到前端 会有精度损失,必须转为string类型 进行传输,就不会有问题了
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
10.AOP统一记录日志
关于AOP的文章可以参考:
自己实现一个日志注解
//Type代表可以放在类上面,METHOD代表可以放在方法上 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LogAnnotation {
<span class="token class-name">String</span> <span class="token keyword">module</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">default</span> <span class="token string">""</span><span class="token punctuation">;</span> <span class="token class-name">String</span> <span class="token function">operator</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">default</span> <span class="token string">""</span><span class="token punctuation">;</span>
}
统一日志处理切面
@Component @Aspect //切面 定义通知和切点的关系 @Slf4j public class LogAspect { @Pointcut("@annotation(com.xpp.blog.common.aop.LogAnnotation)") public void pt(){ }
<span class="token comment">//环绕通知</span> <span class="token annotation punctuation">@Around</span><span class="token punctuation">(</span><span class="token string">"pt()"</span><span class="token punctuation">)</span> <span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">log</span><span class="token punctuation">(</span><span class="token class-name">ProceedingJoinPoint</span> point<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Throwable</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">long</span> beginTime <span class="token operator">=</span> <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//执行方法</span> <span class="token class-name">Object</span> result <span class="token operator">=</span> point<span class="token punctuation">.</span><span class="token function">proceed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//执行时长</span> <span class="token keyword">long</span> time<span class="token operator">=</span><span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span>beginTime<span class="token punctuation">;</span> <span class="token comment">//保存日志</span> <span class="token function">recordLog</span><span class="token punctuation">(</span>point<span class="token punctuation">,</span>time<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> result<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">recordLog</span><span class="token punctuation">(</span><span class="token class-name">ProceedingJoinPoint</span> joinPoint<span class="token punctuation">,</span> <span class="token keyword">long</span> time<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">MethodSignature</span> signature <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">MethodSignature</span><span class="token punctuation">)</span> joinPoint<span class="token punctuation">.</span><span class="token function">getSignature</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">Method</span> method <span class="token operator">=</span> signature<span class="token punctuation">.</span><span class="token function">getMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">LogAnnotation</span> logAnnotation <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">getAnnotation</span><span class="token punctuation">(</span><span class="token class-name">LogAnnotation</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"=====================log start================================"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"module:{}"</span><span class="token punctuation">,</span>logAnnotation<span class="token punctuation">.</span><span class="token keyword">module</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"operation:{}"</span><span class="token punctuation">,</span>logAnnotation<span class="token punctuation">.</span><span class="token function">operator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//请求的方法名</span> <span class="token class-name">String</span> className <span class="token operator">=</span> joinPoint<span class="token punctuation">.</span><span class="token function">getTarget</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">String</span> methodName <span class="token operator">=</span> signature<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"request method:{}"</span><span class="token punctuation">,</span>className <span class="token operator">+</span> <span class="token string">"."</span> <span class="token operator">+</span> methodName <span class="token operator">+</span> <span class="token string">"()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
// //请求的参数
Object[] args = joinPoint.getArgs();
String params = JSON.toJSONString(args[0]);
log.info(“params:{}”,params);
<span class="token comment">//获取request 设置IP地址</span>
<span class="token class-name">HttpServletRequest</span> request <span class="token operator">=</span> <span class="token class-name">HttpContextUtils</span><span class="token punctuation">.</span><span class="token function">getHttpServletRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"ip:{}"</span><span class="token punctuation">,</span> <span class="token class-name">IpUtils</span><span class="token punctuation">.</span><span class="token function">getIpAddr</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"excute time : {} ms"</span><span class="token punctuation">,</span>time<span class="token punctuation">)</span><span class="token punctuation">;</span>
log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"=====================log end================================"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
使用
@PostMapping("")
//加上该注解代表要对此接口记录日志
@LogAnnotation(module = "文章", operator = "获取文章列表")
public Result listArticles(@RequestBody PageParams params) {
return articleService.listArticle(params);
}
11.文章图片上传
11.1 接口说明
接口url:/upload
请求方式:POST
请求参数:
参数名称 | 参数类型 | 说明 |
---|---|---|
image | file | 上传的文件名称 |
返回数据:
{
"success":true,
"code":200,
"msg":"success",
"data":"https://static.mszlu.com/aa.png"
}
导入七牛云依赖:
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>[7.7.0, 7.7.99]</version>
</dependency>
11.2 Controller
@RestController
@RequestMapping("upload")
public class UploadController {
@Autowired
private QiniuUtils qiniuUtils;
@PostMapping
public Result upload(@RequestParam("image")MultipartFile file){
//原始文件名称 比如xpp.png
String originalFilename = file.getOriginalFilename();
//得到一个唯一的文件名称
String fileName=UUID.randomUUID().toString()+"."+ StringUtils.substringAfterLast(originalFilename,".");
//上传文件
boolean upload = qiniuUtils.upload(file, fileName);
if(upload){
return Result.success(QiniuUtils.url+fileName);
}
return Result.fail(20001,"上传失败");
}
}
11.3 使用七牛云
配置上传文件的大小:
# 上传文件总的最大值
spring.servlet.multipart.max-request-size=20MB
# 单个文件的最大值
spring.servlet.multipart.max-file-size=2MB
@Component public class QiniuUtils { //填自己七牛云绑定的域名 public static final String url = "xxxxxxxxxxxx"; //从配置文件读取 @Value("${qiniu.accessKey}") private String accessKey; @Value("${qiniu.accessSecretKey}") private String accessSecretKey;
<span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">upload</span><span class="token punctuation">(</span><span class="token class-name">MultipartFile</span> file<span class="token punctuation">,</span><span class="token class-name">String</span> fileName<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token comment">//构造一个带指定 Region 对象的配置类</span> <span class="token class-name">Configuration</span> cfg <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Configuration</span><span class="token punctuation">(</span><span class="token class-name">Region</span><span class="token punctuation">.</span><span class="token function">huanan</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//...其他参数参考类注释</span> <span class="token class-name">UploadManager</span> uploadManager <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UploadManager</span><span class="token punctuation">(</span>cfg<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//...生成上传凭证,然后准备上传</span> <span class="token class-name">String</span> bucket <span class="token operator">=</span> <span class="token string">"xppll"</span><span class="token punctuation">;</span> <span class="token comment">//默认不指定key的情况下,以文件内容的hash值作为文件名</span> <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> uploadBytes <span class="token operator">=</span> file<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">Auth</span> auth <span class="token operator">=</span> <span class="token class-name">Auth</span><span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>accessKey<span class="token punctuation">,</span> accessSecretKey<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">String</span> upToken <span class="token operator">=</span> auth<span class="token punctuation">.</span><span class="token function">uploadToken</span><span class="token punctuation">(</span>bucket<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">Response</span> response <span class="token operator">=</span> uploadManager<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>uploadBytes<span class="token punctuation">,</span> fileName<span class="token punctuation">,</span> upToken<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//解析上传成功的结果</span> <span class="token class-name">DefaultPutRet</span> putRet <span class="token operator">=</span> JSON<span class="token punctuation">.</span><span class="token function">parseObject</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span><span class="token function">bodyString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">DefaultPutRet</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> ex<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
12.AOP实习统一缓存处理(优化)
内存的访问速度 远远大于 磁盘的访问速度 (1000倍起)
自定义注解:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Cache {
//过期时间
long expire() default 1*60*1000;
//缓存标识 key
String name() default "";
}
定义切面:
@Aspect @Component @Slf4j public class CacheAspect {
<span class="token annotation punctuation">@Autowired</span> <span class="token keyword">private</span> <span class="token class-name">RedisTemplate</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">></span></span> redisTemplate<span class="token punctuation">;</span> <span class="token comment">//切点</span> <span class="token annotation punctuation">@Pointcut</span><span class="token punctuation">(</span><span class="token string">"@annotation(com.xpp.blog.common.cache.Cache)"</span><span class="token punctuation">)</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">pt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span><span class="token punctuation">}</span> <span class="token comment">//环绕通知</span> <span class="token annotation punctuation">@Around</span><span class="token punctuation">(</span><span class="token string">"pt()"</span><span class="token punctuation">)</span> <span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">around</span><span class="token punctuation">(</span><span class="token class-name">ProceedingJoinPoint</span> pjp<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">Signature</span> signature <span class="token operator">=</span> pjp<span class="token punctuation">.</span><span class="token function">getSignature</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//类名</span> <span class="token class-name">String</span> className <span class="token operator">=</span> pjp<span class="token punctuation">.</span><span class="token function">getTarget</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getSimpleName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//调用的方法名</span> <span class="token class-name">String</span> methodName <span class="token operator">=</span> signature<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">Class</span><span class="token punctuation">[</span><span class="token punctuation">]</span> parameterTypes <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Class</span><span class="token punctuation">[</span>pjp<span class="token punctuation">.</span><span class="token function">getArgs</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args <span class="token operator">=</span> pjp<span class="token punctuation">.</span><span class="token function">getArgs</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//参数</span> <span class="token class-name">String</span> params <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span> <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator"><</span>args<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span><span class="token punctuation">(</span>args<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> params <span class="token operator">+=</span> JSON<span class="token punctuation">.</span><span class="token function">toJSONString</span><span class="token punctuation">(</span>args<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> parameterTypes<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> args<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span> parameterTypes<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isNotEmpty</span><span class="token punctuation">(</span>params<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//加密 以防出现key过长以及字符转义获取不到的情况</span> params <span class="token operator">=</span> <span class="token class-name">DigestUtils</span><span class="token punctuation">.</span><span class="token function">md5Hex</span><span class="token punctuation">(</span>params<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token class-name">Method</span> method <span class="token operator">=</span> pjp<span class="token punctuation">.</span><span class="token function">getSignature</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getDeclaringType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getMethod</span><span class="token punctuation">(</span>methodName<span class="token punctuation">,</span> parameterTypes<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//获取Cache注解</span> <span class="token class-name">Cache</span> annotation <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">getAnnotation</span><span class="token punctuation">(</span><span class="token class-name">Cache</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//缓存过期时间</span> <span class="token keyword">long</span> expire <span class="token operator">=</span> annotation<span class="token punctuation">.</span><span class="token function">expire</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//缓存名称</span> <span class="token class-name">String</span> name <span class="token operator">=</span> annotation<span class="token punctuation">.</span><span class="token function">name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//先从redis获取</span> <span class="token class-name">String</span> redisKey <span class="token operator">=</span> name <span class="token operator">+</span> <span class="token string">"::"</span> <span class="token operator">+</span> className<span class="token operator">+</span><span class="token string">"::"</span><span class="token operator">+</span>methodName<span class="token operator">+</span><span class="token string">"::"</span><span class="token operator">+</span>params<span class="token punctuation">;</span> <span class="token class-name">String</span> redisValue <span class="token operator">=</span> redisTemplate<span class="token punctuation">.</span><span class="token function">opsForValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>redisKey<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isNotEmpty</span><span class="token punctuation">(</span>redisValue<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"走了缓存~~~,{},{}"</span><span class="token punctuation">,</span>className<span class="token punctuation">,</span>methodName<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> JSON<span class="token punctuation">.</span><span class="token function">parseObject</span><span class="token punctuation">(</span>redisValue<span class="token punctuation">,</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token class-name">Object</span> proceed <span class="token operator">=</span> pjp<span class="token punctuation">.</span><span class="token function">proceed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> redisTemplate<span class="token punctuation">.</span><span class="token function">opsForValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>redisKey<span class="token punctuation">,</span>JSON<span class="token punctuation">.</span><span class="token function">toJSONString</span><span class="token punctuation">(</span>proceed<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Duration</span><span class="token punctuation">.</span><span class="token function">ofMillis</span><span class="token punctuation">(</span>expire<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"存入缓存~~~ {},{}"</span><span class="token punctuation">,</span>className<span class="token punctuation">,</span>methodName<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> proceed<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> throwable<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> throwable<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token class-name">Result</span><span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">999</span><span class="token punctuation">,</span><span class="token string">"系统错误"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
使用:
@PostMapping("hot")
@Cache(expire = 5 * 60 * 1000,name = "hot_article")
public Result hotArticle(){
int limit = 5;
return articleService.hotArticle(limit);
}
注意:像文章列表这样的接口用了缓存,刷新页面的时候浏览次数,评论次数不会变!!!
13.年月归档中MySQL查询
13.1 Controller
/**
* 文档归档
* @return
*/
@PostMapping("listArchives")
public Result listArchives() {
return articleService.listArchives();
}
13.2 Service
/**
* 文章归档(年月归档)
*
* @return
*/
@Override
public Result listArchives() {
List<Archives> archivesList = articleMapper.listArchives();
return Result.success(archivesList);
}
13.3 具体sql实现
查看数据库表发现是bigint
型
- 这里用一一个时间戳函数
FROM_UNIXTIME()
转化为日期类型,13位及以上bigint
要先除以1000 - 在用
YEAR()
和MONTH()
函数取出对应的年,月
<!--按年月分组统计每组个数,返回year,month,count-->
<select id="listArchives" resultType="com.xpp.blog.dao.dos.Archives">
SELECT YEAR(FROM_UNIXTIME(create_date / 1000)) YEAR,
MONTH(FROM_UNIXTIME(create_date / 1000)) MONTH,
COUNT(*) COUNT
FROM ms_article
GROUP BY YEAR, MONTH;
</select>
int viewCounts = article.getViewCounts();
Article articleUpdate=new Article();
articleUpdate.setViewCounts(viewCounts+1);
LambdaUpdateWrapper<Article> updateWrapper=new LambdaUpdateWrapper<>();
updateWrapper.eq(Article::getId,article.getId());
//设置一个 为了在多线程的环境下,线程安全 CAS思想,防止此时修改的时候已经被修改了(乐观锁)
updateWrapper.eq(Article::getViewCounts,viewCounts);
//update article set view_count =100 where view_count==99 and id =xxx
articleMapper.update(articleUpdate,updateWrapper);
try {
Thread.sleep(5000);
System.out.println("更新完成了");
}catch (InterruptedException e){
e.printStackTrace();
}
14.对后端进行返回统一的标准格式
14.1 定义返回对象
/** * 封装返回给前端的信息 */ @Data @AllArgsConstructor public class Result {
<span class="token comment">//请求是否成功</span> <span class="token keyword">private</span> <span class="token keyword">boolean</span> success<span class="token punctuation">;</span> <span class="token comment">//状态码</span> <span class="token keyword">private</span> <span class="token keyword">int</span> code<span class="token punctuation">;</span> <span class="token comment">//本次接口调用的结果描述</span> <span class="token keyword">private</span> <span class="token class-name">String</span> msg<span class="token punctuation">;</span> <span class="token comment">//本次返回的数据</span> <span class="token keyword">private</span> <span class="token class-name">Object</span> data<span class="token punctuation">;</span> <span class="token comment">/** * @param data 返回给前端的数据 * @return */</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">Result</span> <span class="token function">success</span><span class="token punctuation">(</span><span class="token class-name">Object</span> data<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Result</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> <span class="token string">"success"</span><span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">Result</span> <span class="token function">fail</span><span class="token punctuation">(</span><span class="token keyword">int</span> code<span class="token punctuation">,</span> <span class="token class-name">String</span> msg<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Result</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> code<span class="token punctuation">,</span> msg<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
14.2 定义状态码
可以将所有的状态码封装为一个枚举类,方便管理:
public enum ErrorCode {
<span class="token function">PARAMS_ERROR</span><span class="token punctuation">(</span><span class="token number">10001</span><span class="token punctuation">,</span> <span class="token string">"参数有误"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">ACCOUNT_PWD_NOT_EXIST</span><span class="token punctuation">(</span><span class="token number">10002</span><span class="token punctuation">,</span> <span class="token string">"用户名或密码不存在"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">TOKEN_ERROR</span><span class="token punctuation">(</span><span class="token number">10003</span><span class="token punctuation">,</span> <span class="token string">"token不合法"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">ACCOUNT_EXIST</span><span class="token punctuation">(</span><span class="token number">10004</span><span class="token punctuation">,</span> <span class="token string">"账户已存在"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">NO_PERMISSION</span><span class="token punctuation">(</span><span class="token number">70001</span><span class="token punctuation">,</span> <span class="token string">"无访问权限"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">SESSION_TIME_OUT</span><span class="token punctuation">(</span><span class="token number">90001</span><span class="token punctuation">,</span> <span class="token string">"会话超时"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">NO_LOGIN</span><span class="token punctuation">(</span><span class="token number">90002</span><span class="token punctuation">,</span> <span class="token string">"未登录"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token keyword">int</span> code<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">String</span> msg<span class="token punctuation">;</span> <span class="token class-name">ErrorCode</span><span class="token punctuation">(</span><span class="token keyword">int</span> code<span class="token punctuation">,</span> <span class="token class-name">String</span> msg<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>code <span class="token operator">=</span> code<span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>msg <span class="token operator">=</span> msg<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//get,set方法...</span>
}
15.项目亮点总结
-
jwt + redis
- token令牌的登录方式,访问认证速度快,session共享,安全性
- redis做了令牌和用户信息的对应管理,①进一步增加了安全性 ②登录用户做了缓存 ③灵活控制用户的过期(续期,踢掉线等)
-
threadLocal使用了保存用户信息,请求的线程之内,可以随时获取登录的用户,做了线程隔离。在使用完ThreadLocal之后,做了value的删除,防止了内存泄漏
-
线程安全- update table set value = newValue where id=1 and value=oldValue(CAS)
-
线程池应用非常广,面试7个核心参数(对当前的主业务流程无影响的操作,放入线程池执行)
-
权限系统(重点内容)
-
统一日志记录,统一缓存处理
最后喜欢的小伙伴,记得三连哦!😏🍭😘
![](https://i-blog.csdnimg.cn/blog_migrate/f1865d482bfc2a8f9b374e2b9ff223b5.png)
![表情包](https://i-blog.csdnimg.cn/blog_migrate/3df739fbf0a0daf6dcc4d6d06cae3040.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
创建独立的Spring应用程序直接嵌入Tomcat,Jetty或Undertow(无需部署WAR文件)提供“初始”的POM文件内容,以简
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
此项目为一个springboot+vue入门级小项目,视频地址为:https://www.bilibili.com/video/BV1Nt4y127Jh
业务简单,对提升业务能力没什么大的帮助,更多的是可以熟悉开发流程和编码。
1.表结构
仅仅三张表,分别为用户表,省份表和景点表,其中省份表和景点表为一对多的关系。
用户表(t_user):
省份表(t_province):
景点表(t_place):
2.相关配置
server.port=8989
</dl>
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
项目作者博客:https://blog.csdn.net/MarkerHub/article/details/106417097
后端内容编辑所遇问题
1、Spring Boot 类似Error creating bean with name “XXX”的错误
注意yml配置文件注意空格 和对齐形式
2、在idea中手动配置连接数据库
原因:服务器返回无效时区
解决方案1:
  在mysql命令执
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
前言:
技术准备
开发流程
项目展示
前言:
项目学习地址,点击了解:https://how2j.cn
天猫整站 Springboot 版本,就是这样一个实践项目。 我会带着大家,从零开始,把整个项目构建出来。成熟的项目规划与设计
本教程作者,也就是我~ 有8年企业开发管理经验,7年教学经验,曾参与管理开发几十个商业项目。将展示如何合理设计与规划这样一个规模的电商项目,既做到功能丰富,又让开发节奏有条不紊。基于Springboot 框架技术
本项目使用 Springboot 框架进行系统
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
前言
有了一个基于 ElementUI 的电商后台管理系统,在开发一个相似的后台就会轻松很多。最近 Vue3 出来了,等这个后端管
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
技术栈:SpringBoot,Vue。后端功能相对简单,主要是增删查改,代码有些冗余,算是对之前SpringBoot知识的巩固。
项目配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://