公司网站建设技术的发展,家居网站建设 百度文库,工业设计公司排行,黄冈建设工程信息网序言
随着技术的快速发展和数字化转型的深入推进#xff0c;软件开发领域迎来了前所未有的变革。在众多开发框架中#xff0c;Spring Boot凭借其“约定大于配置”的核心理念和快速开发的能力#xff0c;迅速崭露头角#xff0c;成为当今企业级应用开发的首选框架之一。
《…序言
随着技术的快速发展和数字化转型的深入推进软件开发领域迎来了前所未有的变革。在众多开发框架中Spring Boot凭借其“约定大于配置”的核心理念和快速开发的能力迅速崭露头角成为当今企业级应用开发的首选框架之一。
《Spring Boot实战教程》旨在为广大开发者提供一本系统、全面且实用的学习指南。本教程不仅深入解析了Spring Boot的核心特性和最佳实践还通过大量的实战案例帮助读者快速掌握Spring Boot的应用开发技巧从而能够高效、稳定地构建出符合业务需求的Web应用。
1、为何选择Spring Boot
在众多的开发框架中Spring Boot以其独特的优势赢得了开发者的青睐。首先Spring Boot简化了Spring应用的初始搭建和开发过程通过提供大量的默认配置和自动化配置使开发者能够快速地启动和运行应用。其次Spring Boot支持各种主流的开发工具和平台如Maven、Gradle、IntelliJ IDEA等方便开发者根据自己的习惯和需求选择最适合的开发环境。最后Spring Boot拥有庞大的社区支持和丰富的生态系统开发者可以轻松找到所需的库和插件实现各种复杂的功能需求。
2、本教程的特点
系统全面本教程从Spring Boot的基础知识讲起逐步深入到高级特性和实战应用涵盖了Spring Boot的各个方面。 实战导向通过大量的实战案例和示例代码帮助读者更好地理解和掌握Spring Boot的应用开发技巧。 图文并茂教程中穿插了大量的图表和示意图使内容更加生动直观易于理解。 深入浅出对于复杂的概念和技术本教程采用深入浅出、循序渐进的讲解方式使读者能够轻松掌握。
3、本教程的内容结构
本教程共分为以下几个部分
基础篇介绍Spring Boot的基本概念、发展历程和核心特性以及如何搭建一个基础的Spring Boot项目。 进阶篇深入解析Spring Boot的高级特性和最佳实践包括数据访问、Web开发、安全控制、性能优化等方面。 实战篇通过多个实战案例展示如何使用Spring Boot构建符合业务需求的Web应用包括电商网站、企业门户、社交应用等。 高级篇介绍Spring Boot与微服务架构、云计算、容器化等技术的结合应用以及如何进行Spring Boot应用的测试和部署。
4、结语
《Spring Boot实战教程》不仅是一本学习指南更是一本实战手册。通过本教程的学习你将能够全面掌握Spring Boot的应用开发技巧并能够在实际项目中灵活运用这些技巧构建出高效、稳定且符合业务需求的Web应用。让我们一起踏上Spring Boot的实战之旅吧
一、创建Springboot项目
创建Maven工程导入spring-boot-stater-web起步依赖编写Controller提供启动类
二、手动创建SpringBoot工程 三、编写配置文件application.properties
删除application.properties配置文件新建application.yml或application.yaml配置文件【两者区别请自行查询】
四、编写Controller 启动项目后在控制台会显示配置的端口 可以根据需要将pom文件中的jdk17改为jdk8【注意mybatis等三方依赖库的版本也需要降低】 五、提供启动类 六、启动服务在浏览器调用http://localhost:8080/hello
页面返回Hello World~表示调用成功项目搭建正常
------------接下来就可以进行业务相关接口开发了------------
七、执行sql语句【在navicat、idea或者dos窗口执行sql语句】
-- 创建数据库
create database big_event;-- 使用数据库
use big_event;-- 用户表
create table user (id int unsigned primary key auto_increment comment ID,username varchar(20) not null unique comment 用户名,password varchar(32) comment 密码,nickname varchar(10) default comment 昵称,email varchar(128) default comment 邮箱,user_pic varchar(128) default comment 头像,create_time datetime not null comment 创建时间,update_time datetime not null comment 修改时间
) comment 用户表;-- 分类表
create table category(id int unsigned primary key auto_increment comment ID,category_name varchar(32) not null comment 分类名称,category_alias varchar(32) not null comment 分类别名,create_user int unsigned not null comment 创建人ID,create_time datetime not null comment 创建时间,update_time datetime not null comment 修改时间,constraint fk_category_user foreign key (create_user) references user(id) -- 外键约束
);-- 文章表
create table article(id int unsigned primary key auto_increment comment ID,title varchar(30) not null comment 文章标题,content varchar(10000) not null comment 文章内容,cover_img varchar(128) not null comment 文章封面,state varchar(3) default 草稿 comment 文章状态: 只能是[已发布] 或者 [草稿],category_id int unsigned comment 文章分类ID,create_user int unsigned not null comment 创建人ID,create_time datetime not null comment 创建时间,update_time datetime not null comment 修改时间,constraint fk_article_category foreign key (category_id) references category(id),-- 外键约束constraint fk_article_user foreign key (create_user) references user(id) -- 外键约束
)
八、整合mysql 九、整合mybatis 十、配置application.yml文件 十一、在包名下新建业务分类包 十二、通用实体类
返回结果实体类
package com.source.bigevent2.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;Data
NoArgsConstructor
AllArgsConstructor
public class ResultT {private Integer code;//状态码0成功1失败private String msg;//提示信息private T data;//响应数据public static Result success() {return new Result(0, 操作成功, null);}public static E ResultE success(E data) {return new Result(0, 操作成功, data);}public static ResultString error(String msg) {return new Result(1, msg, null);}
}
分页返回结果实体类
package com.source.bigevent2.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;//分页返回结果对象
Data
NoArgsConstructor
AllArgsConstructor
public class PageBeanT{private Long total;//总条数private ListT items;//当前页数据集合
}
十三、注册用户 如果只添加正则校验参数不合格时会被校验并抛出异常如下 这时候可以添加全局异常捕获 【参考https://huaweicloud.csdn.net/638754d5dacf622b8df8b03d.html】如下 十四、登录认证
令牌就是一段字符串 承载业务数据, 减少后续请求查询数据库的次数 防篡改, 保证信息的合法性和有效性 JWT JWT依赖 JWT详细步骤 JWT工具类
package com.source.bigevent.utils;import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;import java.util.Date;
import java.util.Map;public class JwtUtil {private static final String KEY itheima;//接收业务数据,生成token并返回public static String genToken(MapString, Object claims) {return JWT.create().withClaim(claims, claims).withExpiresAt(new Date(System.currentTimeMillis() 1000 * 60 * 60 * 12)).sign(Algorithm.HMAC256(KEY));}//接收token,验证token,并返回业务数据public static MapString, Object parseToken(String token) {return JWT.require(Algorithm.HMAC256(KEY)).build().verify(token).getClaim(claims).asMap();}}
登录返回token PostMapping(/login)public Result login(Pattern(regexp ^\\S{5,16}$) String username, Pattern(regexp ^\\S{5,16}$) String password) {User user userService.findByUserName(username);if (user null) {return Result.error(用户名错误);}if (Md5Util.checkPassword(password, user.getPassword())) {MapString, Object claims new HashMap();claims.put(userId, user.getId());claims.put(userName, username);String token JwtUtil.genToken(claims);//使用redis对token进行进一步校验登录成功存一份token到redis中redisTemplate.opsForValue().set(Token, token, 12, TimeUnit.HOURS);return Result.success(token);}return Result.error(密码错误);}十五、拦截器认证Token
步骤一、使用拦截器统一验证令牌
步骤二、登录和注册接口需要放行
主要实现逻辑为WebConfig类【注意路径中有两个”/”】 十六、使用ThreadLocal进行局部变量存储
可以存储userId等ThreadLocalUtil见附录一 十七、获取用户信息 通过ThreadLocal可以获取到userName、userId 十八、更新用户信息 注意如果方法的参数是实体类那么不能存在与之并列的其他参数也就是说参数只能有实体类一个参数。如果是入参形式为json则必须添加RequestBody注解否则无法解析传参数据。 实体类参数校验实体类成员变量上添加注解【NotNull、NotEmpty、Email】、接口参数的实体参数上添加Validated注解 十九、更新用户头像 参数校验必须是url地址 二十、修改密码 二十一、新增文章分类 二十二、文章分类列表 二十三、更新文章分类 二十四、新增文章【自定义校验】 参数校验 自定义校验【State】 package com.source.bigevent.pojo;import com.fasterxml.jackson.annotation.JsonFormat;
import com.source.bigevent.annotation.State;
import lombok.Data;
import org.hibernate.validator.constraints.URL;import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.groups.Default;
import java.time.LocalDateTime;/*** 文章*/
Data
public class Article {NotNull(groups Edit.class)private Integer id;NotEmptyprivate String title;NotEmptyprivate String content;URLprivate String coverImg;Stateprivate String state;NotNullprivate Integer categoryId;NotNull(groups Add.class)private Integer createUser;JsonFormat(pattern yyyy-MM-dd HH:mm:ss)private LocalDateTime createTime;JsonFormat(pattern yyyy-MM-dd HH:mm:ss)private LocalDateTime updateTime;public interface Add extends Default {}public interface Edit extends Default {}
}
二十五、文章列表【条件分页】
引入依赖pagehelper dependencygroupIdcom.github.pagehelper/groupIdartifactIdpagehelper-spring-boot-starter/artifactIdversion1.4.6/version/dependency在resources文件夹下新建包名和mapper相同的目录并新建ArticelMapper.xml同名文件 二十六、文件上传
文件上传分两种一种是存在服务器磁盘另一种是存在三方云服务器上。 A、将文件存在本地磁盘 B、三方文件存储服务器阿里云OSS https://blog.csdn.net/m0_72853403/article/details/134611445 https://gitcode.csdn.net/65ec53451a836825ed7988ad.html 二十七、登录优化【Redis】
Springboot集成redis
令牌主动失效机制 A、 登录成功后给浏览器响应令牌的同时把该令牌存储到redis中【这里使用token的值做为key存入redis避免所有用户使用同一个key来存取值】
B、 LoginInterceptor拦截器中需要验证浏览器携带的令牌并同时需要获取到redis中存储的与之相同的令牌
C、 当用户修改密码成功后删除redis中存储的旧令牌
代码编辑完成后启动redis安装包中的redis-server.exe即可使用redis
二十八、SpringBoot项目部署 A、如何生成jar包 执行package命令即可 B、如何运行jar包? Java –jar jar包位置 C、如何停止正在运行的服务 Dos窗口中CtrlC D、Jar包部署对服务器有什么要求 必须有jre环境 E、启动redis 启动redis安装包中的redis-server.exe才可以使用redis
二十九、属性配置方式【优先级从低到高依次为ABCD】
A、 项目中resources目录下的application.yml B、 Jar包所在目录下的application.yml【Window环境下测试不生效】 C、 操作系统环境变量
D、 命令行参数
三十、application配置文件相关知识
application.yml / application.yaml格式如下
yml配置信息书写与获取 三方依赖库技术参数信息书写【以redis为例】 自定义配置参数及获取 方式一、通过Value(“${键名}”) 方式二、通过ConfigurationProperties(prefix“前缀”)Value(“${键名}”) 三十一、驼峰命名格式导致实体类和数据库不一致
修改application.yml配置文件 参考 https://www.cnblogs.com/ubiquitousShare/p/12507070.html https://blog.csdn.net/weixin_45935633/article/details/104704042
附录一
一、JWT工具类
package com.source.bigevent.utils;import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;import java.util.Date;
import java.util.Map;public class JwtUtil {private static final String KEY itheima;//接收业务数据,生成token并返回public static String genToken(MapString, Object claims) {return JWT.create().withClaim(claims, claims).withExpiresAt(new Date(System.currentTimeMillis() 1000 * 60 * 60 * 12)).sign(Algorithm.HMAC256(KEY));}//接收token,验证token,并返回业务数据public static MapString, Object parseToken(String token) {return JWT.require(Algorithm.HMAC256(KEY)).build().verify(token).getClaim(claims).asMap();}}
二、ThreadLocal工具类
package com.source.bigevent.utils;/*** ThreadLocal 工具类*/
SuppressWarnings(all)
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);}//清除ThreadLocal 防止内存泄漏public static void remove() {THREAD_LOCAL.remove();}
}
三、Md5工具类
package com.source.bigevent.utils;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class Md5Util {/*** 默认的密码字符串组合用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合*/protected static char hexDigits[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f};protected static MessageDigest messagedigest null;static {try {messagedigest MessageDigest.getInstance(MD5);} catch (NoSuchAlgorithmException nsaex) {System.err.println(Md5Util.class.getName() 初始化失败MessageDigest不支持MD5Util。);nsaex.printStackTrace();}}/*** 生成字符串的md5校验值** param s* return*/public static String getMD5String(String s) {return getMD5String(s.getBytes());}/*** 判断字符串的md5校验码是否与一个已知的md5码相匹配** param password 要校验的字符串* param md5PwdStr 已知的md5校验码* return*/public static boolean checkPassword(String password, String md5PwdStr) {String s getMD5String(password);return s.equals(md5PwdStr);}public static String getMD5String(byte[] bytes) {messagedigest.update(bytes);return bufferToHex(messagedigest.digest());}private static String bufferToHex(byte bytes[]) {return bufferToHex(bytes, 0, bytes.length);}private static String bufferToHex(byte bytes[], int m, int n) {StringBuffer stringbuffer new StringBuffer(2 * n);int k m n;for (int l m; l k; l) {appendHexPair(bytes[l], stringbuffer);}return stringbuffer.toString();}private static void appendHexPair(byte bt, StringBuffer stringbuffer) {char c0 hexDigits[(bt 0xf0) 4];// 取字节中高 4 位的数字转换, // 为逻辑右移将符号位一起右移,此处未发现两种符号有何不同char c1 hexDigits[bt 0xf];// 取字节中低 4 位的数字转换stringbuffer.append(c0);stringbuffer.append(c1);}}