springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)

简介: 该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。

前言

本文将深入探讨 JWT(JSON Web Token)的组成与使用,以及 Redis 的依赖配置和文件操作功能。此外,我们还将列举一些常见的 HTTP 请求错误代码,并详细解释 @RequestParam 与 @PathVariable 等参数注解的区别与用法。

jwt

组成

一个token 有 3 部分
头部 (header)
载荷 (plyload)
签证 (signature)
三部分 之间 用 . 号 分隔

依赖

<!--jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.10.3</version>
        </dependency>

创建工具类

@Component
public class TokenUtils {
    /**
     * 返回的 则为生成的token
     */
    public static String genToken(String userId, String sign) {
        return JWT.create().withAudience(userId) // 将 user id 保存到 token 里面,作为载荷
                .withExpiresAt(DateUtil.offsetHour(new Date(), 2)) // 2小时后token过期
                .sign(Algorithm.HMAC256(sign)); // 以 password 作为 token 的密钥
    }
}
String token = TokenUtils.genToken(one.getId().toString(), one.getPassword());
            userDTO.setToken(token);

拦截器

package com.example.springboot.utils.intercepter;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.example.springboot.common.Constants;
import com.example.springboot.exception.ServiceException;
import com.example.springboot.pojo.User;
import com.example.springboot.server.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class JwtInterceptor implements HandlerInterceptor {
    @Autowired
    UserService userService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 前端的 token
        String token = request.getHeader("token");
//         如果 不是 映射方法  则 直接 通过
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
//         执行 认证
        if(StrUtil.isBlank(token)){
            throw new ServiceException(Constants.CODE_401,"无token,请重新登录");
        }
//         获取 token 的 user id
         String userId;
        try{
            userId= JWT.decode(token).getAudience().get(0);
        } catch (JWTDecodeException j) {
            throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
        }
        User user = userService.getById(userId);
        if(user == null){
            throw new ServiceException(Constants.CODE_401,"用户不存在,请重新登录");
        }
//      用户密码 加 签   验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
        try{
            jwtVerifier.verify(token);
        } catch (JWTVerificationException e) {
            throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
        }
        return true;
    }
}

配置类

package com.example.springboot.config;
import com.example.springboot.utils.intercepter.JwtInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//          需要通过 注入  的 方式
        registry.addInterceptor(jwtInterceptor2())
                .addPathPatterns("/**")  // 拦截所有请求,通过判断token是否合法来决定是否需要登录
                .excludePathPatterns("/user/login", "/user/register", "/**/export", "/**/import","/echarts/example");
    }
//     创建一个bean
    @Bean
    public JwtInterceptor jwtInterceptor2(){
        return new JwtInterceptor();
    }
}

redis

依赖

<!--        redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

在yaml 里面 使用

spring: 
redis:
    host: 127.0.0.1
    password: 123456
    port: 6379
    database: 1


文件操作


fileMapper


package com.example.springboot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springboot.pojo.Files;
public interface FileMapper extends BaseMapper<Files> {
}

upload

yaml

编辑 储存 文件 的 路径

files:
  upload:
    path: E:/springBootLearn/sys_file/

导入路径

@Value("${files.upload.path}")
    private  String fileUploadPath;

使用

@PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) throws IOException {
//          文件  名字
        String originFileName = file.getOriginalFilename();
//          类型
        String type = FileUtil.extName(originFileName);
//        大小
        long size = file.getSize();
//         判断 配置的文件 路径 是否 存在  不存在则 新建
        File uploadParentFile = new File(fileUploadPath);
        if(!uploadParentFile.exists()){
            uploadParentFile.mkdirs();
        }
//         定义 一个 文件  唯一 的 标识码
        String uuid = IdUtil.fastSimpleUUID();
        File uploadFile = new File(fileUploadPath + uuid + StrUtil.DOT + type);
//          把 获取  到 的文件 存到 磁盘
        file.transferTo(uploadFile);
        return "成功";
    }

hutool

<!--        hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.5.11</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>

优化 使用上 MD5 来 判断 文件 唯一性

//          通过文件的MD5 查询文件
     private  Files getFileByMd5(String md5){
//         查询数据库中 的 md5
         QueryWrapper<Files> queryWrapper =  new QueryWrapper<>();
         queryWrapper.eq("md5", md5);
         List<Files> filesList = fileMapper.selectList(queryWrapper);
         return filesList.size() == 0 ? null : filesList.get(0);
     }


down

//     文件下载 路径 和 对应的接口是一样 的
//    String url = "http://localhost:8081/file/"+fileUUID;
//     uuid  id
        @GetMapping("/{fileUUID}")
    public  void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
//         设置 文件 唯一 标识码  获取文件
            File uploadFile = new File(fileUploadPath + fileUUID);
            //             设置文件 输出 流 格式
            ServletOutputStream out=response.getOutputStream();
            response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileUUID, StandardCharsets.UTF_8));
            response.setContentType("application/octet-stream");
//             读取文件 字节 流
            out.write(FileUtil.readBytes(uploadFile));
            out.flush();
            out.close();
        }
}

删除和批量删除

//  删除
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id){
       // 在 类中找到 唯一的 id
        Files files= fileMapper.selectById(id);
        // 将文件删除 设置为 true
        files.setIsDelete(true);
      //  更新 数据  
        fileMapper.updateById(files);
        return Result.success();
    }


//   批量删除
    @PostMapping("/del/batch")
//    select * from  sys_file  where id in (id,id,id)
    public Result deleteBatch(@RequestBody List<Integer>ids){ //[1,2,3]
//          实例化一个 查函数的方法
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
//         id in id   查 找 选择的 id
        queryWrapper.in("id",ids);
//          查找函数   一个 列表
        List<Files> files = fileMapper.selectList(queryWrapper);
        for (Files file : files)
        {
//             选中 的 都 设置 为 true
            file.setIsDelete(true);
//              将 选中 的 id  都 更新
            fileMapper.updateById(file);
        }
            return Result.success();
    }

取用或 不取用

//  更新enable 字段
    @PostMapping("/update")
    public Result update(@RequestBody Files files){
//         新增或则 更新 都在里面
        return Result.success(fileMapper.updateById(files));
    }

常见请求错误代码

400  请求无效,服务器无法处理 
401  未经  授权,无身份验证
403  服务器 拒绝请求,没有权限
404  请求资源 不存在 
405  请求 方法不允许,使用了错误的请求方式
408  请求超时
500  服务器错误
503  服务器暂时无法处理 请求
也可以自定义

参数注解

@RequestParam@PathVariable 注解是用于从request中接收请求的,两个都可以接收参数,关键点不同的是@RequestParam 是从request里面拿取值,而 @PathVariable 是从一个URI模板里面来填充

@RequestParam
看下面一段代码:
http://localhost:8080/springmvc/hello/101?param1=10&param2=20
根据上面的这个URL,你可以用这样的方式来进行获取
public String getDetails(
    @RequestParam(value="param1", required=true) String param1,
        @RequestParam(value="param2", required=false) String param2){}
@RequestParam 支持下面四种参数
defaultValue 如果本次请求没有携带这个参数,或者参数为空,那么就会启用默认值
name 绑定本次参数的名称,要跟URL上面的一样
required 这个参数是不是必须的
value 跟name一样的作用,是name属性的一个别名
@PathVariable
这个注解能够识别URL里面的一个模板,我们看下面的一个URL
http://localhost:8080/springmvc/hello/101?param1=10&param2=20
1
上面的一个url你可以这样写:
@RequestMapping("/hello/{id}")
    public String getDetails(@PathVariable(value="id") String id,
    @RequestParam(value="param1", required=true) String param1,
    @RequestParam(value="param2", required=false) String param2){}
@PathParam
这个注解是和spring的pathVariable是一样的,也是基于模板的,但是这个是jboss包下面的一个实现,上面的是spring的一个实现,都要导包
@QueryParam
@QueryParam 是 JAX-RS 本来就提供的,和Spring的RequestParam作用一致
@ResponseBody
responseBody表示服务器返回的时候以一种什么样的方式进行返回, 将内容或对象作为 HTTP 响应正文返回,值有很多,一般设定为json
@RequestBody
一般是post请求的时候才会使用这个请求,把参数丢在requestbody里面

相关文章
|
4月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
810 128
|
4月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
576 0
|
4月前
|
Java 测试技术 API
将 Spring 的 @Embedded 和 @Embeddable 注解与 JPA 结合使用的指南
Spring的@Embedded和@Embeddable注解简化了JPA中复杂对象的管理,允许将对象直接嵌入实体,减少冗余表与连接操作,提升数据库设计效率。本文详解其用法、优势及适用场景。
357 126
|
5月前
|
XML JSON Java
Spring框架中常见注解的使用规则与最佳实践
本文介绍了Spring框架中常见注解的使用规则与最佳实践,重点对比了URL参数与表单参数的区别,并详细说明了@RequestParam、@PathVariable、@RequestBody等注解的应用场景。同时通过表格和案例分析,帮助开发者正确选择参数绑定方式,避免常见误区,提升代码的可读性与安全性。
|
3月前
|
NoSQL Java 网络安全
SpringBoot启动时连接Redis报错:ERR This instance has cluster support disabled - 如何解决?
通过以上步骤一般可以解决由于配置不匹配造成的连接错误。在调试问题时,一定要确保服务端和客户端的Redis配置保持同步一致。这能够确保SpringBoot应用顺利连接到正确配置的Redis服务,无论是单机模式还是集群模式。
391 5
|
3月前
|
XML JSON Java
【SpringBoot(三)】从请求到响应再到视图解析与模板引擎,本文带你领悟SpringBoot请求接收全流程!
Springboot专栏第三章,从请求的接收到视图解析,再到thymeleaf模板引擎的使用! 本文带你领悟SpringBoot请求接收到渲染的使用全流程!
332 3
|
3月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
521 2
|
4月前
|
Java 测试技术 数据库
使用Spring的@Retryable注解进行自动重试
在现代软件开发中,容错性和弹性至关重要。Spring框架提供的`@Retryable`注解为处理瞬时故障提供了一种声明式、可配置的重试机制,使开发者能够以简洁的方式增强应用的自我恢复能力。本文深入解析了`@Retryable`的使用方法及其参数配置,并结合`@Recover`实现失败回退策略,帮助构建更健壮、可靠的应用程序。
628 1
使用Spring的@Retryable注解进行自动重试
|
4月前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
400 12