SpringBoot+Vue3项目实战——SpringBoot篇
项目预备与配置数据库以及其他项目配置
server:
port: 9090
spring:
datasource:
url: jdbc:mysql://localhost:3306/lostarknote
username: root
password: guxiang
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
configuration:
map-underscore-to-camel-case: true遇到题目:找不到"url"....
可能原因:没有扫描到配置文件(yml),在pom.xml中的build标签中添加以下内容
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
启动类相关
@SpringBootApplication:包扫描时,自动扫描启动类所在包及其子包,若需要扫描其他包,需要使用@ComponentScan进行包名指定
Lombok工具:
自动生成getter/setter/toString方法 ,需要引入lombok依赖,然后在实体类上添加@Data注解
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
Result实体类
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Result<T> {
private Integer code;
private String message;
private T data;
public static <E> Result<E> success(E data)
{
return new Result<>(0,"操作成功",data);
}
public static Result success(){
return new Result(0,"操作成功",null);
}
public static Result error(String message) {
return new Result(1,message,null);
}
}
用户模块
注册功能:
1.密码加密
public class MD5Util {
//生成MD5
public static String getMD5(String message) {
String md5 = "";
try {
MessageDigest md = MessageDigest.getInstance("MD5");// 创建一个md5算法对象
byte[] messageByte = message.getBytes("UTF-8");
byte[] md5Byte = md.digest(messageByte); // 获得MD5字节数组,16*8=128位
md5 = bytesToHex(md5Byte); // 转换为16进制字符串
} catch (Exception e) {
e.printStackTrace();
}
return md5;
}
// 二进制转十六进制
public static String bytesToHex(byte[] bytes) {
StringBuffer hexStr = new StringBuffer();
int num;
for (int i = 0; i < bytes.length; i++) {
num = bytes;
if(num < 0) {
num += 256;
}
if(num < 16){
hexStr.append("0");
}
hexStr.append(Integer.toHexString(num));
}
return hexStr.toString().toUpperCase();
}
}
2.参数校验——Spring Validation
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724488370258-2fff5ce4-4b4f-4f36-9081-9bc37070d6bb.png#averageHue=%23faf9f9&clientId=u49647e4d-60aa-4&from=paste&height=322&id=ZWdio&originHeight=643&originWidth=1434&originalType=binary&ratio=1&rotation=0&showTitle=false&size=374144&status=done&style=none&taskId=u2ec4fd8c-0f89-419f-b0c7-11f01e8c88a&title=&width=717
3.全局异常处理器
@RestControllerAdvice
public class GobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result handleException(Exception e)
{
e.printStackTrace();
return Result.error(StringUtils.hasLength(e.getMessage())? e.getMessage() : "操作失败!");
}
}
登录功能
登录认证:JWT令牌
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724489556568-920ef5bd-8334-41de-973d-78709796c5ad.png#averageHue=%23fbf9eb&clientId=u49647e4d-60aa-4&from=paste&height=346&id=u38cdaafe&originHeight=692&originWidth=1456&originalType=binary&ratio=1&rotation=0&showTitle=false&size=402509&status=done&style=none&taskId=u50afbe8a-900d-4dc7-9ff7-862aff42db9&title=&width=728
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724489761881-ba8ccc2c-8a2c-42c8-ad50-b3e93cbd0460.png#averageHue=%23f9f7dc&clientId=u49647e4d-60aa-4&from=paste&height=249&id=uf36d9abc&originHeight=497&originWidth=1388&originalType=binary&ratio=1&rotation=0&showTitle=false&size=307408&status=done&style=none&taskId=u53ed3cc8-741d-44bb-810f-7ec2d992e8f&title=&width=694
JWT工具类
public class JWTUtil {
private static final String SECRET = "guxiang";
public static String generateToken(Map<String, Object> claims){
return JWT.create()
.withClaim("claims", claims)
.withExpiresAt(new Date(System.currentTimeMillis()* 1000 * 60 * 60 * 24))
.sign(Algorithm.HMAC256(SECRET));
}
public static Map<String, Object> parseToken(String token){
return JWT.require(Algorithm.HMAC256(SECRET))
.build()
.verify(token)
.getClaim("claims")
.asMap();
}
}
JWT验证:从请求头中获取token
@RestController
@RequestMapping("/dungeon")
public class DungeonController {
@GetMapping("/list")
public Result<String> list(@RequestHeader("Authorization") String token, HttpServletResponse response) {
//验证token
//若能正常解析(不报错),则验证通过
try {
Map<String, Object> claims = JWTUtil.parseToken(token);
return Result.success("副本数据获取成功!");
}catch (Exception e) {
response.setStatus(401);
return Result.error("未登录!");
}
}
}
进阶:注册拦截器进行验证。
注册一个拦截器进行token的验证,就不用单独在每个业务代码里进行token验证
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//令牌验证
String token = request.getHeader("Authorization");
//若能正常解析(不报错),则验证通过
try {
Map<String, Object> claims = JWTUtil.parseToken(token);
//放行
return true;
}catch (Exception e) {
response.setStatus(401);
return false;
}
}
}@Configuration
public class WebConfigimplements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//登录注册不用拦截
registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","/user/register");
}
}@RestController
@RequestMapping("/dungeon")
public class DungeonController {
@GetMapping("/list")
public Result<String> list() {
//这里不用再验证token,已经统一在拦截器中做验证
return Result.success("副本数据获取成功!");
}
}
登录优化——Redis
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724726267565-351696e4-6933-46fc-917f-64ff425ea432.png#averageHue=%23f3f2f2&clientId=u61fe0d29-1cc1-4&from=paste&height=175&id=uae1f345c&originHeight=350&originWidth=1746&originalType=binary&ratio=2&rotation=0&showTitle=false&size=198953&status=done&style=none&taskId=u491c81bc-e20f-4a79-be30-cd4d1bcb869&title=&width=873
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724726416408-be6d8fb1-7f06-474d-9b95-8319c95d3047.png#averageHue=%23f9f9f6&clientId=u61fe0d29-1cc1-4&from=paste&height=436&id=ub7d169a4&originHeight=872&originWidth=1698&originalType=binary&ratio=2&rotation=0&showTitle=false&size=545601&status=done&style=none&taskId=u0b3ce942-0e7e-464e-b421-d426ec6296e&title=&width=849
获取用户信息
ThreadLocal
[*]获取用户信息需要通过token中存储的username到数据库中查找,需要解析token。
[*]在其他业务可能也需要username的信息,又要解析token,为了避免代码重复,在之前拦截器中解析出的token同一放到线程中(ThreadLocal)。
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724491870223-7d0ab1ec-7a6e-48c4-8e01-b58743ec88cf.png#averageHue=%23ede7e4&clientId=u49647e4d-60aa-4&from=paste&height=363&id=ucf925ff5&originHeight=725&originWidth=697&originalType=binary&ratio=1&rotation=0&showTitle=false&size=158027&status=done&style=none&taskId=u8743cc65-bf61-4218-a89d-49d826f6bed&title=&width=348.5
public class ThreadLocalUtil {
//提供ThreadLocal对象
private static final ThreadLocal THREAD_LOCAL= new ThreadLocal();
public static <T> T get() {
return (T) THREAD_LOCAL.get();
}
public static void set(Object value) {
THREAD_LOCAL.set(value);
}
public static void remove() {
THREAD_LOCAL.remove();
}
}拦截器中将数据存入ThreadLocal中,请求完成后清除ThreadLocal,防止内存泄漏
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//令牌验证
String token = request.getHeader("Authorization");
//若能正常解析(不报错),则验证通过
try {
Map<String, Object> claims = JWTUtil.parseToken(token);
//将数据存储到ThreadLocal中
ThreadLocalUtil.set(claims);
//放行
return true;
}catch (Exception e) {
response.setStatus(401);
return false;
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//清空ThreadLocal中的数据,防止内存泄露
ThreadLocalUtil.remove();
}
}接口中从ThreadLocal中获取数据
@GetMapping("/userInfo")
public Result<User> userInfo(@RequestHeader("Authorization") String token) {
// Map<String, Object> claims = JWTUtil.parseToken(token);
// String username = (String) claims.get("username");
Map<String, Object> map = ThreadLocalUtil.get();
String username = (String) map.get("username");
User loginUser = userService.findByUsername(username);
return Result.success(loginUser);
}
@JsonIgnore
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724491443923-60b7f0f7-1830-4b37-ac0d-463cc4054091.png#averageHue=%23f4f0df&clientId=u49647e4d-60aa-4&from=paste&height=42&id=tFG7D&originHeight=52&originWidth=925&originalType=binary&ratio=1&rotation=0&showTitle=false&size=46240&status=done&style=none&taskId=ub5d6ceeb-108b-4f28-ae6b-7226e15e2a2&title=&width=740.5
更新用户信息
实体类中参数验证
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724493311830-36c13ab6-ab03-4d4b-a3c2-1feffe42d2eb.png#averageHue=%23e2cac4&clientId=u49647e4d-60aa-4&from=paste&height=323&id=uf127c2df&originHeight=645&originWidth=1385&originalType=binary&ratio=1&rotation=0&showTitle=false&size=400992&status=done&style=none&taskId=u4b50e1c4-a384-455b-83d8-94fce765b43&title=&width=692.5
更新用户密码
参数用一个map接收,因为继续的参数名与数据库中不一致
更新用户信息时,参数名与字段名一致,所以用user实体类接收
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724493923725-46d7e988-17dc-4f9e-a9eb-1c3f5903a6d0.png#averageHue=%23fac9b1&clientId=u49647e4d-60aa-4&from=paste&height=93&id=u2b3a0ab8&originHeight=185&originWidth=1089&originalType=binary&ratio=1&rotation=0&showTitle=false&size=61591&status=done&style=none&taskId=ub00a4cd7-67c9-4524-bd3c-1df01ab0708&title=&width=544.5
文章模块
新增文章分类
文章分类列表
@JsonFormat
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724679349182-f53100b5-2caf-4d90-9cfd-042ef4b14959.png#averageHue=%23ecefdc&clientId=u61fe0d29-1cc1-4&from=paste&height=67&id=u10f0438c&originHeight=134&originWidth=568&originalType=binary&ratio=2&rotation=0&showTitle=false&size=99538&status=done&style=none&taskId=ua5905ecd-5d4b-4e8a-ab80-996d13e8858&title=&width=284
文章分类详情
更新文章分类
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724680351712-f2e307a6-5874-4c28-b070-6a1527c03e6b.png#averageHue=%23f7f7f6&clientId=u61fe0d29-1cc1-4&from=paste&height=445&id=u485131d3&originHeight=889&originWidth=1415&originalType=binary&ratio=2&rotation=0&showTitle=false&size=521179&status=done&style=none&taskId=u6e0ee40e-09f4-436d-9ce0-878d99ec623&title=&width=707.5
新增文章
自定义校验
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724719296719-aba8d69b-d381-4f3f-8ba1-73c49c79816f.png#averageHue=%23ebebe2&clientId=u61fe0d29-1cc1-4&from=paste&height=450&id=u0f5a29bb&originHeight=899&originWidth=1592&originalType=binary&ratio=2&rotation=0&showTitle=false&size=832166&status=done&style=none&taskId=ub3ede5b0-8184-4ea3-a0ae-4fba6df3a83&title=&width=796
文章分页查询
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724720216592-e3548263-016c-4a8c-b007-27210f9bc731.png#averageHue=%23fbfbf9&clientId=u61fe0d29-1cc1-4&from=paste&height=128&id=u7528f9d5&originHeight=256&originWidth=527&originalType=binary&ratio=2&rotation=0&showTitle=false&size=77533&status=done&style=none&taskId=u22748546-e440-49ca-b979-d63a1bd3b05&title=&width=263.5
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724720365010-4ff7382b-e85c-4f6b-82e7-4bf81bbc2f75.png#averageHue=%23f8f5e7&clientId=u61fe0d29-1cc1-4&from=paste&height=101&id=ua481604d&originHeight=202&originWidth=742&originalType=binary&ratio=2&rotation=0&showTitle=false&size=112483&status=done&style=none&taskId=uda08f4b9-11ec-40bc-89c7-6a0a4dba6d1&title=&width=371
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724720426641-af539793-2c2b-4302-93e7-8d86af685a69.png#averageHue=%23f5f4f1&clientId=u61fe0d29-1cc1-4&from=paste&height=47&id=u42300824&originHeight=93&originWidth=487&originalType=binary&ratio=2&rotation=0&showTitle=false&size=31870&status=done&style=none&taskId=u828bfa76-790d-47a9-8480-e491fc277c4&title=&width=243.5
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724720549882-4af8332e-ec49-482e-987c-a94abc19572b.png#averageHue=%23f8f7f4&clientId=u61fe0d29-1cc1-4&from=paste&height=100&id=u80b92d17&originHeight=199&originWidth=772&originalType=binary&ratio=2&rotation=0&showTitle=false&size=82885&status=done&style=none&taskId=u7ee6ddd4-0326-48c3-bb12-5abfa4eb631&title=&width=386
文件上传
https://cdn.nlark.com/yuque/0/2024/png/27509659/1724722208238-5ceb4e03-92ee-4878-b928-c30a97225967.png#averageHue=%23fbeadc&clientId=u61fe0d29-1cc1-4&from=paste&height=375&id=u6953d55a&originHeight=749&originWidth=1499&originalType=binary&ratio=2&rotation=0&showTitle=false&size=395148&status=done&style=none&taskId=u68841709-8f89-4e8e-9758-d898fcb8bff&title=&width=749.5
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]