最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot 創(chuàng)建及登錄、攔截器的實現(xiàn)

 更新時間:2026年01月12日 14:38:34   作者:又是忙碌的一天  
本文主要介紹了Java開發(fā)中使用JDK 1.8和Spring Boot框架進行Web應(yīng)用開發(fā)時,如何處理無狀態(tài)的HTTP協(xié)議以及如何實現(xiàn)用戶狀態(tài)的管理和維護,本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧

1.創(chuàng)建

這里jdk1.8推薦使用java21

pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.qcby</groupId>
    <artifactId>SpringBootDemoTest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringBootDemoTest</name>
    <description>SpringBootDemoTest</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--加載web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--加載Lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--加載mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope> runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

2.登錄和攔截器

HTTP協(xié)議本身是無狀態(tài)的,這意味著服務(wù)器不會保存任何與客戶端交互的狀態(tài)信息。每個HTTP請求都是獨立的,服務(wù)器在處理完當(dāng)前請求后不會記住之前的請求信息。這種設(shè)計是HTTP協(xié)議的核心特性之一。

這種無狀態(tài)特性帶來以下具體表現(xiàn):

  1. 每個請求必須包含服務(wù)器處理該請求所需的全部信息
  2. 服務(wù)器不會基于之前的請求來推斷當(dāng)前請求的上下文
  3. 默認情況下,服務(wù)器不會記錄客戶端的歷史訪問記錄

無狀態(tài)設(shè)計的優(yōu)缺點: 優(yōu)點:

  • 簡化服務(wù)器設(shè)計,降低服務(wù)器資源消耗
  • 提高可擴展性,服務(wù)器可以更容易地處理大量并發(fā)請求
  • 減少服務(wù)器故障時的數(shù)據(jù)丟失風(fēng)險

缺點:

  • 無法直接支持需要保持狀態(tài)的Web應(yīng)用(如購物車、用戶登錄等)
  • 需要額外機制(如Cookie、Session)來實現(xiàn)狀態(tài)管理

為了解決無狀態(tài)帶來的限制,Web開發(fā)中常采用以下技術(shù):

  1. Cookie:在客戶端存儲少量數(shù)據(jù)
  2. Session:在服務(wù)器端保存用戶狀態(tài)
  3. Token:通過令牌驗證用戶身份

典型應(yīng)用場景對比:

  • 靜態(tài)網(wǎng)頁:無狀態(tài)完全適用
  • 動態(tài)網(wǎng)頁:需要額外狀態(tài)管理機制
  • Web應(yīng)用:必須實現(xiàn)某種形式的狀態(tài)保持

2.1 session

Session(會話)是Web開發(fā)中用于跟蹤用戶狀態(tài)的重要機制。以下是關(guān)于session的詳細說明:

  1. 基本概念
  • 服務(wù)器端存儲的用戶狀態(tài)信息
  • 每個用戶擁有獨立的session數(shù)據(jù)
  • 通常通過cookie中的session ID來識別用戶
  1. 工作原理
  1. 客戶端首次訪問時,服務(wù)器創(chuàng)建session
  2. 服務(wù)器生成唯一session ID并返回給客戶端
  3. 客戶端后續(xù)請求攜帶session ID
  4. 服務(wù)器根據(jù)ID查找對應(yīng)的session數(shù)據(jù)
  1. 典型應(yīng)用場景
  • 用戶登錄狀態(tài)維護
  • 購物車功能實現(xiàn)
  • 個性化設(shè)置存儲
  • 表單數(shù)據(jù)跨頁面暫存

2.1.1 登錄

@GetMapping("/login")
@ResponseBody
public String login(Users users, HttpServletRequest request) {
    List<Users> list = usersDao.login(users);
   if(list.size()==1){
        request.getSession().setAttribute("users", list.get(0));//保存用戶信息
        return "login success";
    }else {
        return "login fail";
    }
}

jsessionid每次登錄都不一樣

2.1.2 session攔截器

package com.qcby.springbootdemotest.interceptor;
import com.qcby.springbootdemotest.model.Users;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
登錄攔截器
HandlerInterceptor 該接口是springmvc提供的一個接口,攔截器的主要接口*/@Componentpublic class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 Users users = (Users) request.getSession().getAttribute("users");// 從session中獲取用戶信息
 if(users != null){
     return true;// true 表示放行,false 表示不放行
 }else {
     response.getWriter().append("please login");
     return false;
 }
}
}

添加攔截器:

package com.qcby.springbootdemotest.config;
import com.qcby.springbootdemotest.interceptor.LoginInterceptor;
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;
@Configuration
public class LoginConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(loginInterceptor)//添加攔截器
            .addPathPatterns("/**")         //攔截所有請求
            .excludePathPatterns("/users/login");//放行接口
}
}

2.2 token

token 說明

token 是服務(wù)端生成的一串字符串,目的是作為客戶端進行請求的一個令牌。當(dāng)?shù)谝淮蔚卿浐?,服?wù)器生成一個 token (一串字符串),并將此 token 返回給客戶端,此后頁面接收到請求后,只需要找到 token 即可獲取信息,無需再輸入登錄名和密碼。

session 和 token 的區(qū)別

session 和 token 的區(qū)別:但 session 有一個缺陷:如果 web 服務(wù)器做了負載均衡,那么下一個操作請求到了另一臺服務(wù)器的時候 session 會丟失。而 token 最大特點就是支持跨平臺操作,不論是在 App 還是在 PC 端,token 都可以保留。

2.2.1 常建工具類用于創(chuàng)建token和解析token密鑰

package com.qcby.springbootdemotest.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
/**
JWT工具類/public class JwtUtil {//有效期為public static final long JWT_TTL = 6060*1000L;//60 * 60 *1000 一個小時//設(shè)置密鑰明文public static final String JWT_KEY = "qcby";
/**
生成jwt
@param id
@param subject
@param ttlMillis
@return*/public static String createJWT(String id, String subject, Long ttlMillis){SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);if(ttlMillis==null){ttlMillis = JwtUtil.JWT_TTL;}long expMillis = nowMillis + ttlMillis;Date expDate = new Date(expMillis);SecretKey secretKey = generalKey();
JwtBuilder builder = Jwts.builder()
.setId(id)      // jwt的唯一標(biāo)識,根據(jù)業(yè)務(wù)需要,可以設(shè)置為一個不重復(fù)的值
.setSubject(subject)// 主題 可以是JSON數(shù)據(jù)
.setIssuer("wd") // 簽發(fā)者
.setIssuedAt(now)  // 簽發(fā)時間
.signWith(signatureAlgorithm, secretKey) //使用HS256簽名算法和密鑰
.setExpiration(expDate); // 設(shè)置過期時間
return builder.compact();
}
/**
生成加密后的密鑰 secretKey
@return*/public static SecretKey generalKey(){byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}
/**
解密jwt
@param jwt
@return
@throws Exception*/public static Claims parseJWT(String jwt) throws Exception{SecretKey secretKey = generalKey();return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}
public static void main(String[] args) {
String token = JwtUtil.createJWT(UUID.randomUUID().toString(),"qd", null);
System.out.println(token);
}
}

導(dǎo)入依賴

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>

2.2.2 修改登錄

@GetMapping("/login")
@ResponseBody
public String login(Users users, HttpServletRequest request) {
    List<Users> list = usersDao.login(users);
   if(list.size()==1){
        String token = JwtUtil.createJWT(list.get(0).getId().toString(), list.get(0).getUsername(), null);
        return token;
    }else {
        return "login fail";
    }
}

token優(yōu)化:

@PostMapping("/login")
@ResponseBody
public ResponseResult login(@RequestBody Users users, HttpServletRequest request) {
    List<Users> list = usersDao.login(users);
    Map<String,Object> map;
   if(list.size()==1) {
        map = new HashMap<>();
        //生成token
        String token = JwtUtil.createJWT(list.get(0).getId().toString(), list.get(0).getUsername(), null);
        map.put("token", token);
        return new ResponseResult(200,"success",map);
    }
    return new ResponseResult(400,"fail");
}

攔截器

package com.qcby.springbootdemotest.interceptor;
import com.qcby.springbootdemotest.model.Users;
import com.qcby.springbootdemotest.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 登錄攔截器
 * HandlerInterceptor 該接口是springmvc提供的一個接口,攔截器的主要接口
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");//獲取請求頭中的token
        if(!StringUtils.hasText(token)){//token為空
            throw new RuntimeException("請登錄");
        }
        //解析 token
        try{
            Claims claims = JwtUtil.parseJWT(token);//解析token
        }catch (Exception e){
            e.printStackTrace();
            response.sendError(401);//響應(yīng)錯誤
            throw new RuntimeException("請登錄");
        }
        return true;
    }
}

指定攔截異常類

package com.qcby.springbootdemotest.expection;
import com.qcby.springbootdemotest.model.ResponseResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class MyControllerAdvice {
    @ResponseBody
    @ExceptionHandler(RuntimeException.class)//指定攔截的異常
    public ResponseResult handleException(Exception e){
        String message = e.getMessage();//獲取異常信息
        ResponseResult result = new ResponseResult(400,message);
        return result;
    }
}

3.springboot統(tǒng)一的響應(yīng)格式

springboot統(tǒng)一的響應(yīng)格式好處:

標(biāo)準(zhǔn)化接口設(shè)計

  • 統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)使前后端協(xié)作更高效,前端開發(fā)者可以預(yù)期固定的響應(yīng)格式
  • 示例:所有接口返回{"code":200,"message":"success","data":{...}}格式
  • 避免了不同開發(fā)者各自定義響應(yīng)格式導(dǎo)致的混亂

錯誤處理規(guī)范化

  • 統(tǒng)一錯誤碼和錯誤信息格式,便于客戶端識別和處理異常
  • 可預(yù)定義常見的HTTP狀態(tài)碼(200,400,401,403,404,500等)
  • 示例:{"code":401,"message":"未授權(quán)訪問","data":null}

簡化客戶端處理

  • 前端無需為不同接口編寫不同的響應(yīng)解析邏輯
  • 移動端應(yīng)用可以復(fù)用統(tǒng)一的響應(yīng)解析模塊
  • 示例:可以封裝通用的響應(yīng)攔截器處理所有API響應(yīng)

增強可維護性

  • 統(tǒng)一修改響應(yīng)格式時只需修改一處代碼
  • 方便添加全局的響應(yīng)攔截和日志記錄
  • 便于實現(xiàn)響應(yīng)數(shù)據(jù)的統(tǒng)一加密或簽名

監(jiān)控和統(tǒng)計

  • 統(tǒng)一的格式便于收集和分析接口調(diào)用情況
  • 可以基于響應(yīng)碼統(tǒng)計系統(tǒng)健康狀態(tài)
  • 示例:監(jiān)控系統(tǒng)可以統(tǒng)計不同錯誤碼的出現(xiàn)頻率

實現(xiàn)方式

  1. 使用@RestControllerAdvice創(chuàng)建全局響應(yīng)處理器
  2. 自定義ResponseEntity封裝類
  3. 統(tǒng)一處理異常轉(zhuǎn)換為標(biāo)準(zhǔn)格式
  4. 可結(jié)合AOP實現(xiàn)響應(yīng)數(shù)據(jù)的增強處理

典型應(yīng)用場景

  • 微服務(wù)架構(gòu)中需要規(guī)范化的API響應(yīng)
  • 前后端分離項目中需要明確的數(shù)據(jù)契約
  • 需要提供開放API的第三方服務(wù)
  • 需要嚴格監(jiān)控接口質(zhì)量的系統(tǒng)

具體實現(xiàn):

@RequestMapping("/findAll")
@ResponseBody
public ResponseResult findAll() {
    List<Users> list = usersDao.findAll();
    return new ResponseResult<>(200,list);
}
/**
 * 根據(jù)用戶名查詢用戶
 * @param username
 * @return
 * @PathVariable 路徑變量, 路徑參數(shù)
 */
@RequestMapping("/findByUsername")
@ResponseBody
public ResponseResult findByUsername(String username) {
    List<Users> user = usersDao.findByName(username);
    return new ResponseResult<>(200,"suc",user);
}
@PostMapping("/insert")
@ResponseBody
public ResponseResult insert(@RequestBody Users users) {
    int count = usersDao.insert(users);
    if(count>0){
        return new ResponseResult(200,"suc");
    }else {
        return new ResponseResult(400,"fail");
    }
}
@PostMapping("/update")
@ResponseBody
public ResponseResult update(@RequestBody Users users) {
    int count = usersDao.update(users);
    if (count>0){
        return new ResponseResult(200,"suc");
    }else {
        return new ResponseResult(400,"fail");
    }
}
@PostMapping("/delete/{id}")
@ResponseBody
public ResponseResult delete(@PathVariable Integer id) {
    int count = usersDao.delete(id);
    if (count>0){
        return new ResponseResult(200,"suc");
    }else {
        return new ResponseResult(400,"fail");
    }
}

ResponseResult類

package com.qcby.springbootdemotest.model;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class ResponseResult<T> {
private Integer code;//狀態(tài)碼
private String message;//提示信息
private T data;  // 數(shù)據(jù)
public ResponseResult(Integer code, String message, T data) {
    this.code = code;
    this.message = message;
    this.data = data;
}
public ResponseResult(Integer code, String message) {
    this.code = code;
    this.message = message;
}
public ResponseResult(Integer code, T data) {
    this.code = code;
    this.data = data;
}
}

到此這篇關(guān)于SpringBoot 創(chuàng)建及登錄、攔截器的實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot 創(chuàng)建登錄攔截器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis-Plus中的MetaObjectHandler組件的使用

    Mybatis-Plus中的MetaObjectHandler組件的使用

    MetaObjectHandler是Mybatis-Plus中一個實用組件,專門用于自動處理實體對象中的特定字段,如創(chuàng)建時間、更新時間、創(chuàng)建人和修改人等,該接口允許開發(fā)者在不修改業(yè)務(wù)代碼的情況下,實現(xiàn)自動填充功能,極大地簡化了代碼的復(fù)雜性,感興趣的可以了解一下
    2024-10-10
  • Java8?Optional常用方法使用場景分析

    Java8?Optional常用方法使用場景分析

    這篇文章主要介紹了Java8?Optional常用方法使用場景,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • 解決Spring Boot 多模塊注入訪問不到j(luò)ar包中的Bean問題

    解決Spring Boot 多模塊注入訪問不到j(luò)ar包中的Bean問題

    這篇文章主要介紹了解決Spring Boot 多模塊注入訪問不到j(luò)ar包中的Bean問題。具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • SpringBoot利用ThreadPoolTaskExecutor批量插入百萬級數(shù)據(jù)

    SpringBoot利用ThreadPoolTaskExecutor批量插入百萬級數(shù)據(jù)

    在處理大量數(shù)據(jù)時,為了提高效率和性能,通常需要采用批量插入的方式,本文主要介紹了SpringBoot利用ThreadPoolTaskExecutor批量插入百萬級數(shù)據(jù),具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • BigDecimal的toString()、toPlainString()和toEngineeringString()區(qū)別及用法詳解

    BigDecimal的toString()、toPlainString()和toEngineeringString()區(qū)

    使用BigDecimal進行打印的時候,經(jīng)常會對BigDecimal提供的三個toString方法感到好奇,以下整理3個toString方法的區(qū)別及用法,需要的朋友可以參考下
    2023-08-08
  • 高可用架構(gòu)etcd選主故障主備秒級切換實現(xiàn)

    高可用架構(gòu)etcd選主故障主備秒級切換實現(xiàn)

    這篇文章主要為大家介紹了高可用架構(gòu)etcd選主故障主備秒級切換的實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-02-02
  • 詳解Java中Collection集合的常用方法

    詳解Java中Collection集合的常用方法

    本篇文章給大家?guī)淼膬?nèi)容是關(guān)于Java中Collection集合的常用方法詳解,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。下面我們就來學(xué)習(xí)一下吧
    2021-11-11
  • 在Java中將Markdown轉(zhuǎn)換為Word、PDF和HTML的常見實現(xiàn)方式

    在Java中將Markdown轉(zhuǎn)換為Word、PDF和HTML的常見實現(xiàn)方式

    在軟件開發(fā)和技術(shù)寫作領(lǐng)域,Markdown?已成為一種被廣泛使用的輕量級標(biāo)記語言,但在實際應(yīng)用中,Markdown?文件往往需要被轉(zhuǎn)換為更通用的格式,本文將分享如何在?Java?環(huán)境下實現(xiàn)?Markdown?轉(zhuǎn)換為?Word、PDF?和?HTML,需要的朋友可以參考下
    2025-09-09
  • Spring中利用配置文件和@value注入屬性值代碼詳解

    Spring中利用配置文件和@value注入屬性值代碼詳解

    這篇文章主要介紹了Spring中利用配置文件和@value注入屬性值代碼詳解,代碼中注釋比較詳細,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • 詳解JAVA的封裝

    詳解JAVA的封裝

    Java面向?qū)ο蟮娜筇匦裕悍庋b、繼承、多態(tài)。下面對三大特性之一封裝進行了總結(jié),需要的朋友可以參考下
    2017-04-04

最新評論

嘉兴市| 白城市| 贞丰县| 教育| 永顺县| 清徐县| 鄱阳县| 子长县| 南康市| 益阳市| 庐江县| 泰州市| 明光市| 大安市| 海盐县| 自贡市| 亚东县| 称多县| 北京市| 静乐县| 九龙城区| 六安市| 泊头市| 时尚| 资兴市| 绥化市| 遵化市| 峨眉山市| 布拖县| 永新县| 新平| 尉犁县| 曲水县| 通城县| 新绛县| 华亭县| 雷州市| 象山县| 千阳县| 泸溪县| 兴义市|