SpringBoot实战1

news2025/4/18 22:09:56

SpringBoot实战1


一、开发环境,环境搭建-----创建项目

通过传统的Maven工程进行创建SpringBoot项目
在这里插入图片描述

(1)导入SpringBoot项目开发所需要的依赖

一个父依赖:(工件ID为:spring-boot-starter-parent

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.4.4</version>
</parent>

开发相关依赖

Web依赖:spring-boot-starter-web

<!--引入Web的依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

Mybatis依赖:mybatis-spring-boot-starter

<!--引入Mybatis的依赖-->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>3.0.4</version>
    </dependency>

MySQL的驱动依赖:mysql-connector-j

<!--引入MySQL的驱动依赖-->
    <dependency>
      <groupId>com.mysql</groupId>
      <artifactId>mysql-connector-j</artifactId>
    </dependency>

lombok工具依赖:

<!--lombok依赖-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>

(2)创建基本的项目架构

Controller,Service,Mapper,POJO,utils

(3)在resources目录下加入application.yml的SpringBoot项目配置文件,在其中加入Jdbc的相关配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/big_event?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
    username: root
    password: ****

(4)完成SQL配置,连接数据库,同时创建数据库表

(5)添加SpringBoot的启动类:(项目名)XxxApplication

加上@SpringBootApplication注解确定为启动类

@SpringBootApplication
public class BigEventApplication
{
    public static void main( String[] args) {
        SpringApplication.run(BigEventApplication.class, args);
    }
}

二、注册功能实现

localhost:8080/user/register

Controller层加上@RestController—>@ResponseBody可以自动将返回值转为JSON格式

通过Post的方式提交数据

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public Result register(String username, String password){
        // TODO: 查询用户是否存在
        User user=userService.findByUserName(username);
        if (user!=null){
            return Result.error("用户已存在");
        }else {
            // TODO: 用户不存在的话就开始注册用户
           userService.register(username,password);
           return Result.success();
        }
    }
}

编写对应的业务层 ,数据层的操作

public interface UserService {
    // 注册
    void register(String username, String password) ;
    // 根据用户名查询用户
    User findByUserName(String username);
}
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public void register(String username, String password) {
        // TODO: 对于用于的密码进行MD5加密处理
        String md5Password = Md5Util.getMD5String(password);
        userMapper.add(username,md5Password);
    }

    @Override
    public User findByUserName(String username) {
        User user =userMapper.findByUserName(username);
        return user;
    }
}
@Mapper
public interface UserMapper {
    // TODO: 必须加入创建时间,更新时间通过sql自带的now()函数
    @Insert("insert into user(username,password,create_time,update_time)" +
            " values(#{username},#{password},now(),now())")
    void add(String username, String password);

    @Select("select * from user where username=#{username}")
    User findByUserName(String username);
}

参数校验框架(Spring Validation)

在注册的时候注意加上:对注册接口的参数进行合法性校验

使用步骤:

1、引入对应的依赖:spring-boot-starter-validation

<!-- 添加validation依赖用于参数的校验 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2、在参数前面加上@Pattern注解(@Pattern(regexp=“正则表达式(注意Java中单斜杠不行需转成\\)”))

public Result register(@Pattern(regexp = "^\\S{5,16}$") String username,@Pattern(regexp = "^\\S{5,16}$") String password)

3、在对应的Controller类上加上@Validated

@Validated
public class UserController

注意:如果遇到参数校验失败的情况的话

4、通过全局异常处理器中处理参数校验失败

@RestControllerAdvice//表示该类是一个全局异常处理类

@ExceptionHandler(Exception.class)//表示该方法可以处理所有异常

//  TODO: 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
    // TODO: 捕获所有异常
    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        e.printStackTrace();
        return Result.error(StringUtils.hasLength(e.getMessage())?e.getMessage():"参数校验失败");
    }
}

三、登录功能实现

1、在数据表中查询用户

2、判断查询到的用户是否存在

3、用户存在判断密码是否正确

//TODO: 登录
@PostMapping("/login")
public Result login(@Pattern(regexp = "^\\S{5,16}$") String username,
                   @Pattern(regexp = "^\\S{5,16}$") String password) {
    // TODO: 查询用户是否存在
    User loginUser = userService.findByUserName(username);
    // TODO: 判断用户是否存在
    if(loginUser==null){
        return Result.error("用户不存在");
    }
    // TODO: 判断密码是否正确
    else{
        if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){
            // 登录成功
            return Result.success("jwt token令牌");
        }
        else {
            return Result.error("密码错误");
        }
    }
}

登录认证:

通过令牌技术承载业务的数据,减少后续请求查询数据库的次数,1、防止篡改,2、保证信息的合法性和有效性

JWT令牌:JSON Web Token(通信双方通过JSON数据格式安全的传输信息)
在这里插入图片描述

JWT组成—通过Base64的编码格式进行编码

1、Header头部:记录令牌的类型,签名算法(用于加密算法)

2、Payload有效载荷:携带一些自定义的信息,默认信息–不能存放私密数据

3、Signature签名:防止Token被篡改,确保安全性


JWT-生成:

引入JWT的依赖

<!-- 添加JWT依赖 -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.4.0</version>
</dependency>

在单元测试中生成jwt令牌

public class JwtTest {

    @Test
    public void testGen(){
        Map<String, Object> claims =new HashMap<>();
        claims.put("id",1);
        claims.put("username","admin");
        //生成jwt代码
        String token = JWT.create()
                .withClaim("user", claims)//添加自定义信息(载荷)
                .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 12))//设置过期时间为12小时
                .sign(Algorithm.HMAC256("geshihua"));//指定算法,配置密钥
        System.out.println(token);
    }
}

jwt令牌的验证:

注意:

1、校验jwt的签名密钥要和生成jwt令牌的签名密钥吻合

2、jwt令牌解析验证报错的话那么说明对应的jwt令牌被篡改了,或者生成的jwt令牌过期失效了

//TODO:jwt令牌的验证
@Test
public void testParse(){
    //定义一个字符串模拟用户传递过来的Token
    String token ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" +
            ".eyJ1c2VyIjp7ImlkIjoxLCJ1c2VybmFtZSI6ImFkbWluIn0sImV4cCI6MTc0NDMyMTkyNX0" +
            ".wfaRNJPOvVz6sU7rsyxnyzSKdezmhyhwslp4eUW2O4g";
    //调用API验证Token
    JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("geshihua")).build();
    //解析Token,生成一个解析后的jwt对象
    DecodedJWT decodedJWT = jwtVerifier.verify(token);
    Map<String, Claim> claims = decodedJWT.getClaims();
    System.out.println(claims.get("user"));
}

将JWT令牌纳入登录验证中(登录成功了之后将相关的信息存储到Token中

// 登录成功
Map<String,Object> claims=new HashMap<>();
claims.put("id",loginUser.getId());
claims.put("username",loginUser.getUsername());
String token = JwtUtil.genToken(claims);
return Result.success(token);

在其他的业务接口中解析验证Token–原理

@GetMapping("/list")
public Result list(@RequestHeader(name = "Authorization") String token, HttpServletResponse response) {
    //验证Token
    try {
        Map<String, Object> claims = JwtUtil.parseToken(token);
    } catch (Exception e) {
        response.setStatus(401);
        return Result.error("请先登录");
    }
    return Result.success("获取到对应的文章信息了!!!");
}

通过拦截器Interceptor多个接口都需要同样的操作可以用拦截器进行实现
在这里插入图片描述

完成对应的验证操作,只有通过验证的才可以进行相关的业务操作

1、先创建一个登录校验的拦截器(LoginInterceptor)–》需要在拦截器这个类上面加一个注解@Component(用于Bean对象注册)

拦截器实现HanderInterceptor接口==>实现preHandle方法(意味在请求的Controller方法(请求访问服务器)之前进行调用)

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //在这个拦截器中验证Token---》通过请求头中携带的的token
        String token = request.getHeader("Authorization");
        //解析Token
        try {
            Map<String, Object> claims = JwtUtil.parseToken(token);
            //TODO:如果解析成功,则放行
            return true;
        } catch (Exception e) {
            response.setStatus(401);
            //TODO:如果解析失败,则返回错误信息,并且拦截
            return false;
        }
    }
}

2、添加Interceptor拦截器到WebMvcConfig配置类中–》配置类需要通过注解@Component将配置类注册到Spring的IOC容器中去

(1)WebMvcConfig配置类需要实现WebMvcConfigurer接口

(2)配置类中将登录拦截器的Bean自动注入进来

@Autowired
private LoginInterceptor loginInterceptor;

(3)实现对应的接口方法–》用于添加对应的登录拦截器addInterceptors

@Configuration//TODO:配置类也需要注册到spring的IOC容器中
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    //TODO:用于拦截器注册
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                //TODO: 放行登录和注册接口,不进行拦截
                .excludePathPatterns("/user/login","/user/register");
    }
}

三、获取用户的详细信息(在进行此业务请求的时候需要再请求头中携带对象的token信息—Authorization)

根据用户名查询数据表中的用户信息(用户名的信息通过请求头中的token----Authorization获取得到)

@RequestHeader(name = "Authorization")String token

通过上面的 参数得到token携带的信息–》用户名的username,id

// TODO: 获取用户详细信息
@GetMapping("/userInfo")
public Result<User> userInfo(@RequestHeader(name = "Authorization")String token){
    //根据用户名查询用户信息---》用户名是通过token解析出来的
    Map<String, Object> map = JwtUtil.parseToken(token);
    String username = (String) map.get("username");
    User user = userService.findByUserName(username);
    return Result.success(user);
}

注意:对于数据表中存在有下划线的字段的时候在进行查询的时候不会自动转化为对应的驼峰命名导致查询不到对应的信息

解决方式一:

在配置文件中开启驼峰映射

mybatis:
  configuration:
    map-underscore-to-camel-case: true # 开启下划线转驼峰命名 自动将数据表中有下划线字段的转换为驼峰明明形式的

解决方式二:

在写SQL语句的时候对于有下划线的字段采取起别名的方式:

@Select("select id, username, password, nickname, email, user_pic as userPic, create_time as createTime, update_time as updateTime from user where username=#{username}")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2332532.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿里云域名证书自动更新acme.sh

因为阿里云的免费证书只有三个月的有效期&#xff0c;每次更换都比较繁琐&#xff0c;所以找到了 acme.sh&#xff0c;还有一种 certbot 我没有去了解&#xff0c;就直接使用了 acme.sh 来更新证书&#xff0c;acme.sh 的主要特点就是&#xff1a; 支持多种 DNS 服务商自动化续…

大数据Hadoop(MapReduce)

MapReduce概述 MapReduce定义 MapReduce是一个分布式运算程序的编程框架&#xff0c;是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff0c;并发运行在一个Hadoop集群上…

图灵逆向——题十七-字体加密

十七题是一个很经典的字体加密案例&#xff0c;很适合新手入门~ 目录列表 过程分析代码实现 过程分析 打开开发者工具直接看请求&#xff0c;发现它请求的没有加密参数&#xff0c;以为万事大吉的你迫不及待的点击了响应&#xff0c;然后就会发现依托。。。 返回的数据中字体…

系统与网络安全------网络通信原理(5)

资料整理于网络资料、书本资料、AI&#xff0c;仅供个人学习参考。 传输层解析 传输层 传输层的作用 IP层提供点到点的连接传输层提供端到端的连接 端口到端口的连接&#xff08;不同端口号&#xff0c;代表不同的应用程序&#xff09; TCP协议概述 TCP&#xff08;Transm…

minio提供nfs服务

minio提供nfs服务 挂载minio为本地目录配置开机自动挂载方法1: 使用supervisor实现开机自动挂载方法2: 服务单元实现开机自动挂载minio为本地目录---失败调试 配置NFS服务端 挂载minio为本地目录 使用 Minio 作为后端存储&#xff0c;并通过 NFS 为客户端提供访问&#xff0c;…

嵌入式---加速度计

一、基本概念与定义 定义 加速度计&#xff08;Accelerometer&#xff09;是一种测量物体加速度&#xff08;线性加速度或振动加速度&#xff09;的传感器&#xff0c;可检测物体运动状态、振动幅度、倾斜角度等&#xff0c;输出与加速度成比例的电信号&#xff08;模拟或数字信…

swagger + Document

swagger 虽然有了api接口&#xff0c;对于复杂接口返回值说明&#xff0c;文档还是不能少。如果是一个人做的还简单一点&#xff0c;现在都搞前后端分离&#xff0c;谁知道你要取那个值呢

【Git】--- 多人协作实战场景

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; Git 前面我们学习了Git的所有本地仓库的相关操作:git基本操作,分支理解,版本回退,冲突解决等等。同时我们还理解了远端仓库在开发的作用以及相关操作push…

Higress: 阿里巴巴高性能云原生API网关详解

一、Higress概述 Higress是阿里巴巴开源的一款基于云原生技术构建的高性能API网关&#xff0c;专为Kubernetes和微服务架构设计。它集成了Ingress控制器、微服务网关和API网关功能于一体&#xff0c;支持多种协议和丰富的流量管理能力。 发展历程 Higress 从最初社区的 Isti…

VM——相机拍照失败

1、问题&#xff1a;相机频闪触发&#xff0c;在MVS中正常出图&#xff0c;在VM中出现拍照失败 2、解决&#xff1a; 1、首先排查网络设置&#xff08;巨帧是否设置&#xff09; 2、电脑的所有防火墙是否关闭 3、在MVS中恢复相机的设置参数为默认参数&#xff0c;删除VM中的全…

初识Redis · 简单理解Redis

目录 前言&#xff1a; 分布式系统 开源节流 认识Redis 负载均衡 缓存 微服务 前言&#xff1a; 本文只是作为Redis的一篇杂谈&#xff0c;简单理解一下Redis为什么要存在&#xff0c;以及它能做到和它不能做到的事儿&#xff0c;简单提及一下它对应的优势有什么&#…

自动驾驶时间同步

主要包含两个大的概念&#xff1a;时间系统间的时间同步与传感器数据间的时间同步 1. 时间系统间的时间同步 概念&#xff1a; 自动驾驶域控一般由多个芯片与多种类型的传感器组成&#xff0c;如&#xff1a;MCU SoC Camera Lidar Radar USS GNSS&#xff0c;其中 MCU…

项目进度延误的十大原因及应对方案

项目进度延误主要源于以下十大原因&#xff1a;目标不明确、需求频繁变更、资源配置不足或不合理、沟通不畅、风险管理不足、缺乏有效的项目监控、技术难题未及时解决、团队协作效率低下、决策链过长、外部因素影响。其中&#xff0c;需求频繁变更是导致延误的关键因素之一&…

消息队列(IPC技术)

目录 一、Linux 中主要的进程间通信方式如下&#xff1a; 二、消息队列函数 &#xff08;1&#xff09;msgget函数 功能概述 函数原型 参数解释 返回值 示例 结果 问题 (2) msgsnd函数 功能概述 函数原型 参数说明 返回值 示例 结果 &#xff08;3&#xff0…

突破焊丝虚影干扰,端子焊点缺陷检测如何实现自动化?

端子焊点作为 3C 产品中连接电路的关键环节&#xff0c;其质量优劣对产品性能有着决定性影响。然而&#xff0c;传统人工检测端子焊点不仅效率低下&#xff0c;难以满足大规模生产需求&#xff0c;而且误判率高&#xff0c;无法精准把控产品质量&#xff0c;成为企业提质增效智…

电能质量在线监测分析装置支持实时监测、数据存储及远程传输,适用于电网、工业等场景

电能质量在线监测分析装置主要技术指标 2.1工作电源 交流&#xff1a;220V10% &#xff1b;50Hz0.5Hz&#xff1b;谐波畸变率不大于15&#xff05; 直流&#xff1a;220V10%&#xff0c;纹波系数不大于5% 2.2电流信号输入 输入方式&#xff1a;电流互感器输入&#xff1b; …

01分数规划

好久没发博客了……浅浅复活一下&#xff0c;讲个冷门些的算法。 算法目的&#xff1a;选出k组ai,bi使得 最大。 算法过程&#xff1a; 不妨考虑二分答案&#xff0c;那么答案的形式便是 的形式&#xff0c;则可通过移项转化为&#xff0c;进一步的&#xff0c;我们可以将…

网络安全防护技术

边界安全防护——防火墙 控制&#xff1a;在网络连接点上建立一个安全控制点&#xff0c;对进出数据进行限制隔离&#xff1a;将需要保护的网络与不可信任网络进行隔离&#xff0c;隐藏信息并进行安全防护记录&#xff1a;对进出数据进行检查&#xff0c;记录相关信息 防火墙…

课程分享 | 安全设计原则

讲师介绍 前言 在数字化时代&#xff0c;软件安全已从技术问题升级为关乎企业存亡的战略要务。从SolarWinds供应链攻击到Log4j漏洞风暴&#xff0c;一次次安全事件不断警示我们&#xff1a;传统的边界防护思维已无法应对日益复杂的威胁环境。面对不断演进的攻击手段&#xff0…

【数据结构 · 初阶】- 单链表

目录 一.相关指针知识点 二.链表 1.为什么学了顺序表还要学链表 2.优点 三.实现 1.链表的打印 —— 理解链表结构 (2) 物理结构图 2.链表的尾插 —— 入门 错误写法&#xff1a;tail ! NULL 总结&#xff1a; 正确代码物理图解&#xff1a; (2) 尾插整体代码 (思考…