SpringBoot登錄認(rèn)證前后端實(shí)現(xiàn)方案:SpringBoot + Mybatis + JWT(圖文實(shí)例)
本文簡(jiǎn)介
目的:
Spring生態(tài)為Java后端開(kāi)發(fā)提供了強(qiáng)大支持,但將分散的技術(shù)點(diǎn)整合成完整解決方案往往令人困惑。本文將以登錄接口為切入點(diǎn),系統(tǒng)演示如何將IOC/DI、MyBatis數(shù)據(jù)持久化、MD5加密、Session/Cookie管理、JWT令牌和攔截器機(jī)制融合運(yùn)用,打造企業(yè)級(jí)認(rèn)證方案
技術(shù)棧:
- 前端:HTML + CSS + JavaScript + Jquery
- 后端:SpringBoot + Mybatis + JWT
搭建環(huán)境:
- 數(shù)據(jù)庫(kù):MySQL8.4.0
- 項(xiàng)目結(jié)構(gòu):maven
- 前端框架:Jquery
- 后端框架:SpringBoot
- JDK:17
- 編譯器:IDEA
目錄結(jié)構(gòu):

項(xiàng)目搭建及配置
1.創(chuàng)建SpringBoot3.0.0+項(xiàng)目并添加依賴(lài):Spring Web、MyBatis Framework、MySQL Driver、Lombok
2.初始化數(shù)據(jù)庫(kù):
create database spring_blog_login charset utf8mb4;
use spring_blog_login;
create table user_info (id int primary key auto_increment,user_name varchar(128) unique ,
password varchar(128) not null,delete_flag int default 0,
create_time datetime default now(),update_time datetime default now()
);
insert into user_info (user_name,password) values
('張三','123456'),
('李四','123456'),
('王五','123456');
3.將application.properties修改為application.yml并添加如下配置:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/spring_blog_login?characterEncoding=utf8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
configuration:
map-underscore-to-camel-case: true #自動(dòng)駝峰轉(zhuǎn)換
server:
port: 8080 #不顯式設(shè)置默認(rèn)為8080
按住Ctrl + F5,如果程序能運(yùn)行成功則說(shuō)明搭建及配置都沒(méi)問(wèn)題(MySQL服務(wù)器必須要處于運(yùn)行狀態(tài))
1.登錄認(rèn)證全棧實(shí)現(xiàn) ->基礎(chǔ)版
1.1 后端實(shí)現(xiàn)
1.1.1 架構(gòu)設(shè)計(jì)
本次登錄功能采用Controller、Service、Mapper三層架構(gòu):Controller層依賴(lài)于Service層來(lái)執(zhí)行業(yè)務(wù)邏輯并獲取處理結(jié)果,而Service層又依賴(lài)于Mapper層來(lái)進(jìn)行數(shù)據(jù)持久化操作

1.1.2 實(shí)體類(lèi)
實(shí)體類(lèi)用于封裝業(yè)務(wù)數(shù)據(jù),需要與數(shù)據(jù)庫(kù)表結(jié)構(gòu)一一對(duì)應(yīng)
import lombok.Data;
import java.util.Date;
@Data
public class UserInfo {
private Integer id;
private String userName;
private String password;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}
1.1.3 Controller
處理HTTP請(qǐng)求、參數(shù)校驗(yàn)、返回響應(yīng)
import org.example.springlogin.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@RequestMapping("/login")
public String login(String userName,String password) {
if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
return "用戶(hù)或密碼為空";
}
return userService.getUserInfoByUserName(userName,password);
}
}
1.1.4 Service
業(yè)務(wù)邏輯處理
import org.example.springlogin.mapper.UserMapper;
import org.example.springlogin.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserMapper userMapper;
@Autowired
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
public String getUserInfoByUserName(String userName,String password) {
UserInfo userInfo = userMapper.getUserInfoByUserName(userName);
if (userInfo == null) {
return "用戶(hù)不存在";
}
if (!password.equals(userInfo.getPassword())) {
return "密碼錯(cuò)誤";
}
return "登錄成功";
}
}
1.1.5 Mapper
數(shù)據(jù)持久化操作
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.example.springlogin.model.UserInfo;
@Mapper
public interface UserMapper {
@Select("select * from user_info where user_name = #{userName}")
UserInfo getUserInfoByUserName(String userName);
}
1.2 前端實(shí)現(xiàn)
Gitee:項(xiàng)目前端代碼:https://gitee.com/lys3210728077/test.-java-ee-advanced/tree/master/spring-login/src/main/resources/static,Gitee上的前端代碼是最新提交的,如下效果圖僅作參考效果演示:
- 1.用戶(hù)或密碼為空

- 2.用戶(hù)不存在

- 3.密碼錯(cuò)誤

- 4.登錄成功

2.Cookie/Session
HTTP(超文本傳輸協(xié)議)設(shè)計(jì)為無(wú)狀態(tài)協(xié)議,指服務(wù)器默認(rèn)不保留客戶(hù)端請(qǐng)求之間的任何狀態(tài)信息。每個(gè)請(qǐng)求獨(dú)立處理,服務(wù)器不會(huì)記憶之前的交互內(nèi)容(如下圖)

優(yōu)點(diǎn):
- 請(qǐng)求獨(dú)立性:每次請(qǐng)求被視為新請(qǐng)求,服務(wù)器不依賴(lài)歷史請(qǐng)求數(shù)據(jù)
- 簡(jiǎn)單高效:無(wú)狀態(tài)設(shè)計(jì)降低服務(wù)器資源消耗,簡(jiǎn)化實(shí)現(xiàn)邏輯
缺點(diǎn):
- 身份識(shí)別困難:需通過(guò)額外機(jī)制(如Cookies、Session)跟蹤用戶(hù)狀態(tài)
- 重復(fù)傳輸數(shù)據(jù):每次請(qǐng)求需攜帶完整信息,可能增加冗余(如認(rèn)證信息)
cookie:是存儲(chǔ)在客戶(hù)端(瀏覽器)的小型文本數(shù)據(jù),由服務(wù)器通過(guò)HTTP響應(yīng)頭Set-Cookie發(fā)送給客戶(hù)端,并在后續(xù)請(qǐng)求中自動(dòng)攜帶
session:是存儲(chǔ)在服務(wù)器端的用戶(hù)狀態(tài)信息,通常通過(guò)一個(gè)唯一的Session ID標(biāo)識(shí),該ID可能通過(guò)Cookie或URL傳遞

如上圖片引用自我的博客:Java EE(13)——網(wǎng)絡(luò)原理——應(yīng)用層HTTP協(xié)議,服務(wù)器內(nèi)部實(shí)際上專(zhuān)門(mén)開(kāi)辟了一個(gè)session空間用于存儲(chǔ)用戶(hù)信息,每當(dāng)新用戶(hù)發(fā)送第一次請(qǐng)求時(shí)服務(wù)器會(huì)將用戶(hù)信息存儲(chǔ)在session中并生成一個(gè)session id通過(guò)Set-Cookie方法返回給客戶(hù)端,即cookie
session結(jié)構(gòu)如下:

修改Controller類(lèi)代碼:
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.example.springlogin.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@RequestMapping("/login")
public String login(String userName, String password, HttpSession session) {
log.info("接收到參數(shù),userName:{},password:{}",userName,password);
if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
return "用戶(hù)或密碼為空";
}
String result = userService.getUserInfoByUserName(userName, password);
if (result.equals("登錄成功")){
HashMap<String,String> map = new HashMap<>();
map.put("userName",userName);
map.put("password",password);
//將map作為用戶(hù)信息存儲(chǔ)到session/會(huì)話(huà)中
session.setAttribute("cookie", map);
log.info("登錄成功");
}
return result;
}
修改前端代碼:
function login() {
$.ajax({
url: '/user/login',
type: "post",
data:{
userName:$('#username').val(),
password:$('#password').val(),
},
success: function(result) {
alert(result);
},
})
}
Fiddler抓包結(jié)果:

前端/瀏覽器按住Ctrl + Shift + i打開(kāi)控制臺(tái)點(diǎn)擊應(yīng)用程序/application,打開(kāi)Cookie:

3.統(tǒng)一返回結(jié)果封裝
統(tǒng)一返回結(jié)果封裝是后端開(kāi)發(fā)中的重要設(shè)計(jì)模式,能夠保持API響應(yīng)格式的一致性,便于前端處理
1.創(chuàng)建枚舉類(lèi):統(tǒng)一管理接口或方法的返回狀態(tài)碼和描述信息,標(biāo)準(zhǔn)化業(yè)務(wù)邏輯中的成功或失敗狀態(tài)
import lombok.Getter;
@Getter
public enum ResultStatus {
SUCCESS(200,"成功"),
FAIL(-1,"失敗"),
;
private final Integer code;
private final String message;
ResultStatus(Integer code, String message) {
this.code = code;
this.message = message;
}
}
2.創(chuàng)建Result< T >類(lèi):主要用于規(guī)范服務(wù)端返回給客戶(hù)端的響應(yīng)數(shù)據(jù)格式。通過(guò)固定結(jié)構(gòu)(狀態(tài)碼、錯(cuò)誤信息、數(shù)據(jù))確保前后端交互的一致性
import lombok.Data;
@Data
//通過(guò)泛型<T>設(shè)計(jì),可以靈活封裝任意類(lèi)型的數(shù)據(jù)對(duì)象到data字段
public class Result<T> {
//業(yè)務(wù)碼
private ResultStatus code;
//錯(cuò)誤信息
private String errorMessage;
//數(shù)據(jù)
private T data;
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(ResultStatus.SUCCESS);
result.setErrorMessage(null);
result.setData(data);
return result;
}
public static <T> Result<T> fail(String errorMessage) {
Result<T> result = new Result<>();
result.setCode(ResultStatus.FAIL);
result.setErrorMessage(errorMessage);
result.setData(null);
return result;
}
}
3.修改Controller代碼:
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@RequestMapping("/login")
public Result<String> login(String userName, String password, HttpSession session) {
log.info("接收到參數(shù),userName:{},password:{}",userName,password);
if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
return Result.fail("用戶(hù)或密碼為空");
}
String result = userService.getUserInfoByUserName(userName, password);
if (!result.equals("登錄成功")){
return Result.fail(result);
}
HashMap<String,String> map = new HashMap<>();
map.put("userName",userName);
map.put("password",password);
//將map作為用戶(hù)信息存儲(chǔ)到session/會(huì)話(huà)中
session.setAttribute("cookie", map);
log.info("登錄成功");
return Result.success(result);
}
}
4.修改前端代碼:
function login() {
$.ajax({
url: '/user/login',
type: "post",
data:{
userName:$('#username').val(),
password:$('#password').val(),
},
success: function(result) {
if (result.code === "SUCCESS") {
alert(result.data)
}else {
alert(result.error)
}
},
})
}
4.圖形驗(yàn)證碼
圖形驗(yàn)證碼(captcha)是一種區(qū)分用戶(hù)是人類(lèi)還是自動(dòng)化程序的技術(shù),主要通過(guò)視覺(jué)或交互任務(wù)實(shí)現(xiàn)。其核心意義體現(xiàn)在以下方面:
- 防止自動(dòng)化攻擊:通過(guò)復(fù)雜圖形或扭曲文字,阻止爬蟲(chóng)、暴力破解工具等自動(dòng)化程序批量注冊(cè)或登錄,降低服務(wù)器壓力
- 提升安全性:在敏感操作(如支付、修改密碼)前增加驗(yàn)證步驟,減少數(shù)據(jù)泄露或惡意操作風(fēng)險(xiǎn)
Hutool提供了CaptchaUtil類(lèi)用于快速生成驗(yàn)證碼,支持圖形驗(yàn)證碼和GIF動(dòng)態(tài)驗(yàn)證碼。在pom.xml文件中添加圖下配置:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<!-- 版本號(hào)應(yīng)與springboot版本兼容 -->
<version>5.8.40</version>
</dependency>
1.創(chuàng)建CaptchaController類(lèi),用于生成驗(yàn)證碼并返回給前端
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
@RequestMapping("/captcha")
@Slf4j
public class CaptchaController {
//設(shè)置過(guò)期時(shí)間
public final static long delay = 60_000L;
@RequestMapping("/get")
public void getCaptcha(HttpSession session, HttpServletResponse response) {
log.info("getCaptcha");
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
//設(shè)置返回類(lèi)型
response.setContentType("image/jpeg");
//禁止緩存
response.setHeader("Pragma", "No-cache");
try {
//通過(guò)響應(yīng)輸出生成的圖形驗(yàn)證碼
lineCaptcha.write(response.getOutputStream());
//保存code
session.setAttribute("CAPTCHA_SESSION_CODE", lineCaptcha.getCode());
//保存當(dāng)前時(shí)間
session.setAttribute("CAPTCHA_SESSION_DATE", System.currentTimeMillis());
//關(guān)閉輸出流
response.getOutputStream().close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
2.修改前端代碼:最終版
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>微信登錄</title>
<link rel="stylesheet" rel="external nofollow" >
<link rel="stylesheet" href="css/login.css" rel="external nofollow" >
</head>
<body>
<div class="login-container">
<div class="logo">
<i class="fab fa-weixin"></i>
</div>
<h2>微信登錄</h2>
<form id="loginForm">
<div class="input-group">
<i class="fas fa-user"></i>
<label for="username"></label><input type="text" id="username" placeholder="請(qǐng)輸入用戶(hù)名" required>
</div>
<div class="input-group">
<i class="fas fa-lock"></i>
<label for="password"></label><input type="password" id="password" placeholder="請(qǐng)輸入密碼" required>
</div>
<div class="input-group">
<div class="captcha-container">
<label for="inputCaptcha"></label><input type="text" id="inputCaptcha" class="captcha-input" placeholder="輸入驗(yàn)證碼">
<img id="verificationCodeImg" src="/captcha/get" class="captcha-img" title="看不清?換一張" alt="驗(yàn)證碼">
</div>
</div>
<div class="agreement">
<input type="checkbox" id="agreeCheck" checked>
<label for="agreeCheck">我已閱讀并同意<a href="#" rel="external nofollow" rel="external nofollow" >《服務(wù)條款》</a>和<a href="#" rel="external nofollow" rel="external nofollow" >《隱私政策》</a></label>
</div>
<button type="submit" class="login-btn" onclick="login()">登錄</button>
</form>
<div class="footer">
<p>版權(quán)所有 ?九轉(zhuǎn)蒼翎</p>
</div>
</div>
<!-- 引入jQuery依賴(lài) -->
<script src="js/jquery.min.js"></script>
<script>
//刷新驗(yàn)證碼
$("#verificationCodeImg").click(function(){
//new Date().getTime()).fadeIn()防止前端緩存
$(this).hide().attr('src', '/captcha/get?dt=' + new Date().getTime()).fadeIn();
});
//登錄
function login() {
$.ajax({
url: '/user/login',
type: "post",
data:{
userName:$('#username').val(),
password:$('#password').val(),
captcha:$('#inputCaptcha').val(),
},
success: function(result) {
console.log(result);
if (result.code === "SUCCESS") {
alert(result.data)
}else {
alert(result.error)
}
},
})
}
</script>
</body>
</html>
3.在UserController類(lèi)新增captcha形參接收來(lái)自CaptchaController類(lèi)的請(qǐng)求,并傳遞給UserService

import jakarta.servlet.http.HttpSession;
import org.example.springlogin.controller.CaptchaController;
import org.example.springlogin.mapper.UserMapper;
import org.example.springlogin.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserMapper userMapper;
@Autowired
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
public String getUserInfoByUserName(String userName, String password, String captcha, HttpSession session) {
UserInfo userInfo = userMapper.getUserInfoByUserName(userName);
if (userInfo == null) {
return "用戶(hù)不存在";
}
if (!password.equals(userInfo.getPassword())) {
return "密碼錯(cuò)誤";
}
long saveTime = (long)session.getAttribute("CAPTCHA_SESSION_DATE");
if (System.currentTimeMillis() - saveTime > CaptchaController.delay) {
return "驗(yàn)證碼超時(shí)";
}
if (!captcha.equalsIgnoreCase((String) session.getAttribute("CAPTCHA_SESSION_CODE"))) {
return "驗(yàn)證碼錯(cuò)誤";
}
return "登錄成功";
}
}
實(shí)現(xiàn)效果:

5.MD5加密
MD5(Message-Digest Algorithm 5)是一種廣泛使用的哈希函數(shù),可將任意長(zhǎng)度數(shù)據(jù)生成固定長(zhǎng)度(128位,16字節(jié))的哈希值,通常表示為32位十六進(jìn)制字符串,常用于校驗(yàn)數(shù)據(jù)完整性或存儲(chǔ)密碼。但因其安全性不足,通常結(jié)合鹽值(Salt)配合使用
- 不可逆性:無(wú)法通過(guò)哈希值反推原始數(shù)據(jù)
- 唯一性:理論上不同輸入產(chǎn)生相同哈希值的概率極低(哈希碰撞)
- 固定長(zhǎng)度:無(wú)論輸入數(shù)據(jù)大小,輸出均為32位十六進(jìn)制字符串
1.創(chuàng)建SecurityUtil類(lèi)用于生成和驗(yàn)證密文
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import java.util.UUID;
public class SecurityUtil {
//加密
public static String encrypt(String inputPassword){
//生成隨機(jī)鹽值
String salt = UUID.randomUUID().toString().replaceAll("-", "");
//(密碼+鹽值)進(jìn)行加密
String finalPassword = DigestUtils.md5DigestAsHex((inputPassword + salt).getBytes());
return salt + finalPassword;
}
//驗(yàn)證
public static boolean verify(String inputPassword, String sqlPassword){
if (!StringUtils.hasLength(inputPassword)){
return false;
}
if (sqlPassword == null || sqlPassword.length() != 64){
return false;
}
//取出鹽值
String salt = sqlPassword.substring(0,32);
//(輸入密碼 + 鹽值)重新生成 加密密碼
String finalPassword = DigestUtils.md5DigestAsHex((inputPassword + salt).getBytes());
//判斷數(shù)據(jù)庫(kù)中儲(chǔ)存的密碼與輸入密碼是否一致
return (salt + finalPassword).equals(sqlPassword);
}
public static void main(String[] args) {
System.out.println(SecurityUtil.encrypt("123456"));
}
}
2.將數(shù)據(jù)庫(kù)中的密碼替換為加密后的值
3.修改驗(yàn)證密碼的邏輯(UserService類(lèi))
if (!SecurityUtil.verify(password,userInfo.getPassword())) {
return "密碼錯(cuò)誤";
}
6.攔截器
Spring攔截器(Interceptor)是一種基于AOP的機(jī)制,用于在請(qǐng)求處理的不同階段插入自定義邏輯。常用于權(quán)限校驗(yàn)、日志記錄、參數(shù)預(yù)處理等場(chǎng)景
1.創(chuàng)建攔截器類(lèi)并實(shí)現(xiàn)HandlerInterceptor接口,該接口提供了三種方法:
- preHandle:在Controller方法執(zhí)行前調(diào)用
- postHandle:Controller方法執(zhí)行后、視圖渲染前調(diào)用
- afterCompletion:請(qǐng)求完成、視圖渲染完畢后調(diào)用
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Slf4j
@Component
public class Interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//1.獲取token
String cookie = request.getHeader("cookie");
if (cookie == null) {
response.setStatus(401);
return false;
}
log.info("接收到cookie:{}",cookie);
//2.校驗(yàn)token
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
log.info("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
log.info("afterCompletion");
}
}
2.注冊(cè)攔截器
import org.example.springlogin.intercepter.Interceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays;
import java.util.List;
@Configuration
public class Config implements WebMvcConfigurer {
private final Interceptor Interceptor;
@Autowired
public Config(Interceptor interceptor) {
Interceptor = interceptor;
}
//排除不需要攔截的路徑
private static final List<String> excludes = Arrays.asList(
"/**/login.html",
"/user/login",
"/captcha/get"
);
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注冊(cè)攔截器
registry.addInterceptor(Interceptor)
//攔截所有路徑
.addPathPatterns("/**")
.excludePathPatterns(excludes);
}
}
3.創(chuàng)建home.html文件,并且在登錄成功后跳轉(zhuǎn)到該頁(yè)面(在login.html中添加location.href="/home.html")
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>home</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
實(shí)現(xiàn)效果:
- 成功登陸時(shí)


- 未登錄直接訪(fǎng)問(wèn)home.html頁(yè)面時(shí)

到此這篇關(guān)于SpringBoot登錄企業(yè)級(jí)認(rèn)證系統(tǒng)實(shí)現(xiàn)方案:Session、統(tǒng)一封裝、MD5加密與攔截器的文章就介紹到這了,更多相關(guān)SpringBoot登錄認(rèn)證方案內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot整合Sa-Token實(shí)現(xiàn)登錄認(rèn)證和權(quán)限校驗(yàn)的詳細(xì)流程
- JWT登錄認(rèn)證Springboot詳解
- springboot+vue前后端分離項(xiàng)目中使用jwt實(shí)現(xiàn)登錄認(rèn)證
- Springboot 如何使用 SaToken 進(jìn)行登錄認(rèn)證、權(quán)限管理及路由規(guī)則接口攔截
- SpringBoot?實(shí)現(xiàn)CAS?Server統(tǒng)一登錄認(rèn)證的詳細(xì)步驟
- SpringBoot+Vue+JWT的前后端分離登錄認(rèn)證詳細(xì)步驟
相關(guān)文章
Java實(shí)現(xiàn)讀取Word模板文檔并替換內(nèi)容生成新文檔
在實(shí)際開(kāi)發(fā)中,經(jīng)常會(huì)遇到需要根據(jù) Word 模板生成特定文檔的需求,下面小編就來(lái)為大家介紹一下如何使用 Apache POI 庫(kù)來(lái)讀取 Word 模板文檔,然后替換其中的指定內(nèi)容最后生成新的文檔吧2025-02-02
Java中zip的壓縮和解壓縮的實(shí)現(xiàn)代碼
這篇文章主要介紹了Java中zip的壓縮和解壓縮的實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02
JDK常用命令jps jinfo jstat的具體說(shuō)明與示例
JDK本身提供了很多方便的JVM性能調(diào)優(yōu)監(jiān)控工具,除了集成式的VisualVM和jConsole外,還有jps、jinfo、jstat等小巧的工具,本文章希望能起拋磚引玉之用,讓大家能開(kāi)始對(duì)JVM性能調(diào)優(yōu)的常用工具有所了解2021-09-09
springboot整合spring-retry的實(shí)現(xiàn)示例
本文將結(jié)合實(shí)例代碼,介紹springboot整合spring-retry的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
詳解基于Mybatis-plus多租戶(hù)實(shí)現(xiàn)方案
這篇文章主要介紹了詳解基于Mybatis-plus多租戶(hù)實(shí)現(xiàn)方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
自己動(dòng)手編寫(xiě)一個(gè)Mybatis插件之Mybatis脫敏插件
這篇文章主要介紹了自己動(dòng)手編寫(xiě)一個(gè)Mybatis插件之Mybatis脫敏插件,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
java實(shí)現(xiàn)pdf文件截圖的方法【附PDFRenderer.jar下載】
這篇文章主要介紹了java實(shí)現(xiàn)pdf文件截圖的方法,結(jié)合實(shí)例形式分析了java基于PDFRenderer.jar進(jìn)行pdf文件截圖的相關(guān)操作技巧,并附帶PDFRenderer.jar文件供讀者下載使用,需要的朋友可以參考下2018-01-01
IDEA中項(xiàng)目集成git提交代碼的詳細(xì)步驟
這篇文章主要介紹了IDEA中項(xiàng)目集成git提交代碼的詳細(xì)步驟,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10

