SpringBoot+Vue3项目实战——SpringBoot篇

打印 上一主题 下一主题

主题 546|帖子 546|积分 1638

项目预备与配置


数据库以及其他项目配置
  1. server:
  2.   port: 9090
  3. spring:
  4.   datasource:
  5.     url: jdbc:mysql://localhost:3306/lostarknote
  6.     username: root
  7.     password: guxiang
  8.     driver-class-name: com.mysql.cj.jdbc.Driver
  9. mybatis:
  10.   configuration:
  11.     map-underscore-to-camel-case: true
复制代码
遇到题目:找不到"url"....
可能原因:没有扫描到配置文件(yml),在pom.xml中的build标签中添加以下内容
  1. <resources>
  2.     <resource>
  3.         <directory>src/main/java</directory>
  4.         <includes>
  5.             <include>**/*.yml</include>
  6.             <include>**/*.properties</include>
  7.             <include>**/*.xml</include>
  8.         </includes>
  9.         <filtering>false</filtering>
  10.     </resource>
  11.     <resource>
  12.         <directory>src/main/resources</directory>
  13.         <includes>
  14.             <include>**/*.yml</include>
  15.             <include>**/*.properties</include>
  16.             <include>**/*.xml</include>
  17.         </includes>
  18.         <filtering>false</filtering>
  19.     </resource>
  20. </resources>
复制代码
启动类相关

@SpringBootApplication:包扫描时,自动扫描启动类所在包及其子包,若需要扫描其他包,需要使用@ComponentScan进行包名指定

Lombok工具:

自动生成getter/setter/toString方法 ,需要引入lombok依赖,然后在实体类上添加@Data注解
  1. <dependency>
  2.     <groupId>org.projectlombok</groupId>
  3.     <artifactId>lombok</artifactId>
  4.     <version>1.18.30</version>
  5. </dependency>
复制代码
Result实体类
  1. @NoArgsConstructor
  2. @AllArgsConstructor
  3. @Data
  4. public class Result<T> {
  5.     private Integer code;
  6.     private String message;
  7.     private T data;
  8.     public static <E> Result<E> success(E data)
  9.     {
  10.         return new Result<>(0,"操作成功",data);
  11.     }
  12.     public static Result success(){
  13.         return new Result(0,"操作成功",null);
  14.     }
  15.     public static Result error(String message) {
  16.         return new Result(1,message,null);
  17.     }
  18. }
复制代码
用户模块


注册功能:


1.密码加密
  1. public class MD5Util {
  2.     //生成MD5
  3.     public static String getMD5(String message) {
  4.         String md5 = "";
  5.         try {
  6.             MessageDigest md = MessageDigest.getInstance("MD5");  // 创建一个md5算法对象
  7.             byte[] messageByte = message.getBytes("UTF-8");
  8.             byte[] md5Byte = md.digest(messageByte);              // 获得MD5字节数组,16*8=128位
  9.             md5 = bytesToHex(md5Byte);                            // 转换为16进制字符串
  10.         } catch (Exception e) {
  11.             e.printStackTrace();
  12.         }
  13.         return md5;
  14.     }
  15.     // 二进制转十六进制
  16.     public static String bytesToHex(byte[] bytes) {
  17.         StringBuffer hexStr = new StringBuffer();
  18.         int num;
  19.         for (int i = 0; i < bytes.length; i++) {
  20.             num = bytes[i];
  21.             if(num < 0) {
  22.                 num += 256;
  23.             }
  24.             if(num < 16){
  25.                 hexStr.append("0");
  26.             }
  27.             hexStr.append(Integer.toHexString(num));
  28.         }
  29.         return hexStr.toString().toUpperCase();
  30.     }
  31. }
复制代码
2.参数校验——Spring Validation



3.全局异常处理器
  1. @RestControllerAdvice
  2. public class GobalExceptionHandler {
  3.     @ExceptionHandler(Exception.class)
  4.     public Result handleException(Exception e)
  5.     {
  6.         e.printStackTrace();
  7.         return Result.error(StringUtils.hasLength(e.getMessage())? e.getMessage() : "操作失败!");
  8.     }
  9. }
复制代码
登录功能


登录认证:JWT令牌




JWT工具类
  1. public class JWTUtil {
  2.     private static final String SECRET = "guxiang";
  3.     public static String generateToken(Map<String, Object> claims){
  4.         return JWT.create()
  5.                 .withClaim("claims", claims)
  6.                 .withExpiresAt(new Date(System.currentTimeMillis()* 1000 * 60 * 60 * 24))
  7.                 .sign(Algorithm.HMAC256(SECRET));
  8.     }
  9.     public static Map<String, Object> parseToken(String token){
  10.         return JWT.require(Algorithm.HMAC256(SECRET))
  11.                 .build()
  12.                 .verify(token)
  13.                 .getClaim("claims")
  14.                 .asMap();
  15.     }
  16. }
复制代码
JWT验证:从请求头中获取token
  1. @RestController
  2. @RequestMapping("/dungeon")
  3. public class DungeonController {
  4.     @GetMapping("/list")
  5.     public Result<String> list(@RequestHeader("Authorization") String token, HttpServletResponse response) {
  6.         //验证token
  7.         //若能正常解析(不报错),则验证通过
  8.         try {
  9.             Map<String, Object> claims = JWTUtil.parseToken(token);
  10.             return Result.success("副本数据获取成功!");
  11.         }catch (Exception e) {
  12.             response.setStatus(401);
  13.             return Result.error("未登录!");
  14.         }
  15.     }
  16. }
复制代码
进阶:注册拦截器进行验证。

注册一个拦截器进行token的验证,就不用单独在每个业务代码里进行token验证
  1. @Component
  2. public class LoginInterceptor implements HandlerInterceptor {
  3.     @Override
  4.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  5.         //令牌验证
  6.         String token = request.getHeader("Authorization");
  7.         //若能正常解析(不报错),则验证通过
  8.         try {
  9.             Map<String, Object> claims = JWTUtil.parseToken(token);
  10.             //放行
  11.             return true;
  12.         }catch (Exception e) {
  13.             response.setStatus(401);
  14.             return false;
  15.         }
  16.     }
  17. }
复制代码
  1. @Configuration
  2. public class WebConfig  implements WebMvcConfigurer {
  3.     @Autowired
  4.     private LoginInterceptor loginInterceptor;
  5.    
  6.     @Override
  7.     public void addInterceptors(InterceptorRegistry registry) {
  8.         //登录注册不用拦截
  9.         registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","/user/register");
  10.     }
  11. }
复制代码
  1. @RestController
  2. @RequestMapping("/dungeon")
  3. public class DungeonController {
  4.     @GetMapping("/list")
  5.     public Result<String> list() {
  6.         //这里不用再验证token,已经统一在拦截器中做验证
  7.         return Result.success("副本数据获取成功!");
  8.     }
  9. }
复制代码
登录优化——Redis




获取用户信息


ThreadLocal


  • 获取用户信息需要通过token中存储的username到数据库中查找,需要解析token。
  • 在其他业务可能也需要username的信息,又要解析token,为了避免代码重复,在之前拦截器中解析出的token同一放到线程中(ThreadLocal)。
  1. public class ThreadLocalUtil {
  2.     //提供ThreadLocal对象
  3.     private static final ThreadLocal THREAD_LOCAL= new ThreadLocal();
  4.     public static <T> T get() {
  5.         return (T) THREAD_LOCAL.get();
  6.     }
  7.     public static void set(Object value) {
  8.         THREAD_LOCAL.set(value);
  9.     }
  10.     public static void remove() {
  11.         THREAD_LOCAL.remove();
  12.     }
  13. }
复制代码
拦截器中将数据存入ThreadLocal中,请求完成后清除ThreadLocal,防止内存泄漏
  1. @Component
  2. public class LoginInterceptor implements HandlerInterceptor {
  3.     @Override
  4.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  5.         //令牌验证
  6.         String token = request.getHeader("Authorization");
  7.         //若能正常解析(不报错),则验证通过
  8.         try {
  9.             Map<String, Object> claims = JWTUtil.parseToken(token);
  10.             //将数据存储到ThreadLocal中
  11.             ThreadLocalUtil.set(claims);
  12.             //放行
  13.             return true;
  14.         }catch (Exception e) {
  15.             response.setStatus(401);
  16.             return false;
  17.         }
  18.     }
  19.     @Override
  20.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  21.         //清空ThreadLocal中的数据,防止内存泄露
  22.         ThreadLocalUtil.remove();
  23.     }
  24. }
复制代码
接口中从ThreadLocal中获取数据
  1. @GetMapping("/userInfo")
  2.     public Result<User> userInfo(@RequestHeader("Authorization") String token) {
  3. //        Map<String, Object> claims = JWTUtil.parseToken(token);
  4. //        String username = (String) claims.get("username");
  5.         Map<String, Object> map = ThreadLocalUtil.get();
  6.         String username = (String) map.get("username");
  7.         User loginUser = userService.findByUsername(username);
  8.         return Result.success(loginUser);
  9.     }
复制代码
@JsonIgnore



更新用户信息


实体类中参数验证



更新用户密码

参数用一个map接收,因为继续的参数名与数据库中不一致
更新用户信息时,参数名与字段名一致,所以用user实体类接收


文章模块


新增文章分类


文章分类列表


@JsonFormat



文章分类详情


更新文章分类



新增文章


自定义校验



文章分页查询






文件上传







免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

杀鸡焉用牛刀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表