SpringBoot实战1

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.Driverurl: jdbc:mysql://localhost:3306/big_event?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTCusername: rootpassword: ****

(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 {@Autowiredprivate 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 {@Autowiredprivate UserMapper userMapper;@Overridepublic void register(String username, String password) {// TODO: 对于用于的密码进行MD5加密处理String md5Password = Md5Util.getMD5String(password);userMapper.add(username,md5Password);}@Overridepublic 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 {@Testpublic 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(){//定义一个字符串模拟用户传递过来的TokenString token ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" +".eyJ1c2VyIjp7ImlkIjoxLCJ1c2VybmFtZSI6ImFkbWluIn0sImV4cCI6MTc0NDMyMTkyNX0" +".wfaRNJPOvVz6sU7rsyxnyzSKdezmhyhwslp4eUW2O4g";//调用API验证TokenJWTVerifier 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) {//验证Tokentry {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 {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//在这个拦截器中验证Token---》通过请求头中携带的的tokenString token = request.getHeader("Authorization");//解析Tokentry {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 {@Autowiredprivate 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.mzph.cn/diannao/77448.shtml

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

相关文章

【软考-高级】【信息系统项目管理师】【论文基础】进度管理过程输入输出及工具技术的使用方法

定义 项目进度管理是为了保证项目按时完成&#xff0c;对项目中所需的各个过程进行管理的过程&#xff0c;包括规划进度、定义活动、活动优先级排序、活动持续时间、制定进度计划和控制进度。 管理基础 制定进度计划的一般步骤 选择进度计划方法&#xff08;如关键路径法&a…

【Linux】之【Get】 chroot 环境下安装deb包时 .postinst:行 9: 201 段错误 (核心已转储)ldconfig

背景 如题&#xff0c;在postinst文件中直接执行了ldconfig命令&#xff0c; chroot 环境下出错&#xff0c;安装失败 分析 chroot 环境下不能用 ldconfig 和 systemctl 但是&#xff1a;如果环境是 chroot&#xff0c;系统有可能没完整挂载 /proc、/dev、系统路径&#xff…

【论文精读与实现】EDC²-RAG:基于动态聚类的文档压缩方法提升检索增强生成RAG性能

🧠 向所有学习者致敬! “学习不是装满一桶水,而是点燃一把火。” —— 叶芝 我的博客主页: https://lizheng.blog.csdn.net 🌐 欢迎点击加入AI人工智能社区! 🚀 让我们一起努力,共创AI未来! 🚀 1. 论文核心思想 这篇由清华大学团队提出的EDC-RAG框架,针对当前…

OSPF接口的网络类型和不规则区域

网络类型(数据链路层所使用的协议所构建的二层网络类型) 1、MA --- 多点接入网络 BMA --- 支持广播的多点接入网络 NBMA --- 不支持广播的多点接入网络 2、P2P --- 点到点网络 以太网 --- 以太网最主要的特点是需要基于MAC地址进行物理寻址&#xff0c;主要是因为以太网接口所连…

HTTP代理:内容分发战场上的「隐形指挥官」

目录 一、技术本质&#xff1a;流量博弈中的「规则改写者」 二、战略价值&#xff1a;内容分发的「四维升级」 三、实战案例&#xff1a;代理技术的「降维打击」 四、未来进化&#xff1a;代理技术的「认知升级」 五、结语&#xff1a;代理技术的「战略觉醒」 在数字内容爆…

(2)网络学习之堡垒机

堡垒机和防火墙的区别&#xff1a; 1.功能定位 防火墙主要负责抵御外部攻击&#xff0c;就像一道坚固的城墙&#xff0c;防止黑客进入内部网络。堡垒机则专注于内部管理&#xff0c;监控和记录运维人员的操作行为&#xff0c;确保内部网络的安全。 2.部署位置与作用范围 防…

minio命令行客户端mc常见用法

安装minio命令行客户端mc https://min-io.cn/docs/minio/linux/reference/minio-mc-admin.html # Windows安装minio命令行客户端 choco install minio-client -y# Linux安装mc客户端 wget -c -P /usr/local/bin/ https://dl.min.io/client/mc/release/linux-amd64/mc # 赋予可…

idea调整控制台日志显示长度

概述 在调试时&#xff0c;idea控制台显示的日志有长度显示&#xff0c;当显示的日志太长时&#xff0c;后生成的日志会覆盖掉之前生成的日志内容。想要调整长度就可以按以下方式进行设置。 设置方法 Settings -> Editor -> General -> Console -> Override con…

oracle em修复之路

很早以前写的文章&#xff0c;再草稿中存放太久了&#xff0c;今天开始整理20年来工作体会&#xff0c;以后陆续发出&#xff0c;希望给大家提供小小的帮助。 去年做的项目使用的oracle数据库&#xff0c;最近要看一下&#xff0c;启动机器进入系统&#xff0c;出现无法加载数…

QT中怎么隐藏或显示最大化、最小化、关闭按钮

文章目录 方法一&#xff1a;通过代码动态设置1、隐藏最大化按钮2、隐藏最小化按钮3、隐藏关闭按钮方法 1&#xff1a;移除 WindowCloseButtonHint方法 2&#xff1a;使用 Qt::CustomizeWindowHint 并手动控制按钮 4、同时隐藏最大化和最小化按钮5、同时隐藏最大化和关闭按钮6、…

性能比拼: Redis vs Memcached

本内容是对知名性能评测博主 Anton Putra Redis vs Memcached Performance Benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 在本视频中&#xff0c;我们将对比 Redis 和 Memcached。我会介绍一些功能上的不同&#xff0c;但主要关注 性能。 首先&#xf…

P1331 洛谷 海战

题目描述 思路 这个题需要读懂题意&#xff0c;即“什么样的形式表示两只船相撞&#xff1f;” ----> 上下相邻或左右相邻 如果图是不和法的&#xff0c;一定存在如下结构&#xff1a; # # . # 或 # # # . 或 # . # # 或 . # # #即四个格子里有三个#&#xff0c;一个"…

传统项目纯前端实现导出excel之xlsx.bundle.js

传统项目纯前端实现导出excel之xlsx.js 自从vue问世后&#xff0c;使得前端开发更加简洁从容&#xff0c;极大的丰富组件样式和页面渲染效果&#xff0c;使得前端功能的可扩展性得到极大地加强。虽然vue的使用对于前后端分离的项目对于功能实现与扩展有了质的飞跃&#xff0c;但…

2025.04.10-拼多多春招笔试第四题

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 04. 优惠券最优分配问题 问题描述 LYA是一家电商平台的运营经理,负责促销活动的策划。现在平台上有 n n n

基于 Spring Boot 瑞吉外卖系统开发(三)

基于 Spring Boot 瑞吉外卖系统开发&#xff08;三&#xff09; 分类列表 静态页面 实现功能所需要的接口 定义Mapper接口 Mapper public interface CategoryMapper extends BaseMapper<Category> {}定义Service接口 public interface CategoryService extends ISe…

FlinkSQL的常用语言

FlinkSQL 常用语言指南 FlinkSQL 是 Apache Flink 提供的 SQL 接口&#xff0c;允许用户使用标准 SQL 或扩展的 SQL 语法来处理流式和批式数据。以下是 FlinkSQL 的常用语言元素和操作&#xff1a; 基本查询 -- 选择查询 SELECT * FROM table_name;-- 带条件的查询 SELECT c…

spring mvc异步请求 sse 大文件下载 断点续传下载Range

学习连接 异步Servlet3.0 Spring Boot 处理异步请求&#xff08;DeferredResult 基础案例、DeferredResult 超时案例、DeferredResult 扩展案例、DeferredResult 方法汇总&#xff09; spring.io mvc Asynchronous Requests 官网文档 spring.io webflux&webclient官网文…

一问看懂——支持向量机SVM(Support Vector Machine)

目录 芜湖~~~支持向量机&#xff08;SVM&#xff09; 1. 引言 2. 基本思想 3. 数学模型 3.1 超平面定义 3.2 分类间隔与目标函数 3.3 软间隔与松弛变量 4. 核函数方法&#xff08;Kernel Trick&#xff09; 4.1 核函数定义 4.2 常用核函数 5. SVM 的几种类型 6. SV…

蓝桥杯 拼数(字符串大小比较)

题目描述 设有 n 个正整数 a1​…an​&#xff0c;将它们联接成一排&#xff0c;相邻数字首尾相接&#xff0c;组成一个最大的整数。 输入格式 第一行有一个整数&#xff0c;表示数字个数 n。 第二行有 n 个整数&#xff0c;表示给出的 n 个整数 ai​。 输出格式 一个正整…

Elasticsearch 系列专题 - 第三篇:搜索与查询

搜索是 Elasticsearch 的核心功能之一。本篇将介绍如何构建高效的查询、优化搜索结果,以及调整相关性评分,帮助你充分发挥 Elasticsearch 的搜索能力。 1. 基础查询 1.1 Match Query 与 Term Query 的区别 Match Query:用于全文搜索,会对查询词进行分词。 GET /my_index/_…