欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Spring Security的Web應(yīng)用和指紋登錄實踐

 更新時間:2019年03月04日 14:22:36   作者:劉少飛  
這篇文章主要介紹了詳解Spring Security的Web應(yīng)用和指紋登錄實踐,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前言

Java 開發(fā)人員在解決 Web 應(yīng)用安全相關(guān)的問題時,通常會采用兩個非常流行的安全框架,Shiro 和 Spring Security。Shiro 配置簡單,上手快,滿足一般應(yīng)用的安全需求,但是功能相對單一。Spring Security 安全粒度細(xì),與 Spring Framework 無縫集成,滿足絕大多數(shù)企業(yè)級應(yīng)用的安全需求,但是配置復(fù)雜,學(xué)習(xí)曲線陡峭。

Spring Security 相對 Shiro 功能強(qiáng)大,并且 Spring Framework,Spring Boot,Spring Cloud 對 Spring Security 的支持更加友好 (畢竟是 "親兒子")。本文將介紹 Spring Security 的架構(gòu)設(shè)計、核心組件,在 Web 應(yīng)用中的開發(fā)方式,最后以一個指紋登錄的實例收尾。

Spring Security 核心設(shè)計

Spring Security 有五個核心組件:SecurityContext、SecurityContextHolder、Authentication、Userdetails 和 AuthenticationManager。下面分別介紹一下各個組件。

SecurityContext

SecurityContext 即安全上下文,關(guān)聯(lián)當(dāng)前用戶的安全信息。用戶通過 Spring Security 的校驗之后,SecurityContext 會存儲驗證信息,下文提到的 Authentication 對象包含當(dāng)前用戶的身份信息。SecurityContext 的接口簽名如清單 1 所示:

清單 1. SecurityContext 的接口簽名

public interface SecurityContext extends Serializable {
    Authentication getAuthentication();
    void setAuthentication(Authentication authentication);
}

SecurityContext 存儲在 SecurityContextHolder 中。

SecurityContextHolder
SecurityContextHolder 存儲 SecurityContext 對象。SecurityContextHolder 是一個存儲代理,有三種存儲模式分別是:

  • MODE_THREADLOCAL:SecurityContext 存儲在線程中。
  • MODE_INHERITABLETHREADLOCAL:SecurityContext 存儲在線程中,但子線程可以獲取到父線程中的 SecurityContext。
  • MODE_GLOBAL:SecurityContext 在所有線程中都相同。

SecurityContextHolder 默認(rèn)使用 MODE_THREADLOCAL 模式,SecurityContext 存儲在當(dāng)前線程中。調(diào)用 SecurityContextHolder 時不需要顯示的參數(shù)傳遞,在當(dāng)前線程中可以直接獲取到 SecurityContextHolder 對象。但是對于很多 C 端的應(yīng)用(音樂播放器,游戲等等),用戶登錄完畢,在軟件的整個生命周期中只有當(dāng)前登錄用戶,面對這種情況 SecurityContextHolder 更適合采用 MODE_GLOBAL 模式,SecurityContext 相當(dāng)于存儲在應(yīng)用的進(jìn)程中,SecurityContext 在所有線程中都相同。

Authentication

Authentication 即驗證,表明當(dāng)前用戶是誰。什么是驗證,比如一組用戶名和密碼就是驗證,當(dāng)然錯誤的用戶名和密碼也是驗證,只不過 Spring Security 會校驗失敗。Authentication 接口簽名如清單 2 所示:

清單 2. Authentication 的接口簽名

public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    Object getCredentials();
    Object getDetails();
    Object getPrincipal();
    boolean isAuthenticated();
    void setAuthenticated(boolean isAuthenticated);
}

Authentication 是一個接口,實現(xiàn)類都會定義 authorities,credentials,details,principal,authenticated 等字段,具體含義如下:

  • getAuthorities: 獲取用戶權(quán)限,一般情況下獲取到的是用戶的角色信息。
  • getCredentials: 獲取證明用戶認(rèn)證的信息,通常情況下獲取到的是密碼等信息。
  • getDetails: 獲取用戶的額外信息,比如 IP 地址、經(jīng)緯度等。
  • getPrincipal: 獲取用戶身份信息,在未認(rèn)證的情況下獲取到的是用戶名,在已認(rèn)證的情況下獲取到的是 UserDetails (暫時理解為,當(dāng)前應(yīng)用用戶對象的擴(kuò)展)。
  • isAuthenticated: 獲取當(dāng)前 Authentication 是否已認(rèn)證。
  • setAuthenticated: 設(shè)置當(dāng)前 Authentication 是否已認(rèn)證。

在驗證前,principal 填充的是用戶名,credentials 填充的是密碼,detail 填充的是用戶的 IP 或者經(jīng)緯度之類的信息。通過驗證后,Spring Security 對 Authentication 重新注入,principal 填充用戶信息(包含用戶名、年齡等), authorities 會填充用戶的角色信息,authenticated 會被設(shè)置為 true。重新注入的 Authentication 會被填充到 SecurityContext 中。

UserDetails

UserDetails 提供 Spring Security 需要的用戶核心信息。UserDetails 的接口簽名如清單 3 所示:

清單 3. UserDetails 的接口簽名

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    String getPassword();
    String getUsername();
    boolean isAccountNonExpired();
    boolean isAccountNonLocked();
    boolean isCredentialsNonExpired();
    boolean isEnabled();
}

UserDetails 用 isAccountNonExpired, isAccountNonLocked,isCredentialsNonExpired,isEnabled 表示用戶的狀態(tài)(與下文中提到的 DisabledException,LockedException,BadCredentialsException 相對應(yīng)),具體含義如下:

  • getAuthorites:獲取用戶權(quán)限,本質(zhì)上是用戶的角色信息。
  • getPassword: 獲取密碼。
  • getUserName: 獲取用戶名。
  • isAccountNonExpired: 賬戶是否過期。
  • isAccountNonLocked: 賬戶是否被鎖定。
  • isCredentialsNonExpired: 密碼是否過期。
  • isEnabled: 賬戶是否可用。

UserDetails 也是一個接口,實現(xiàn)類都會繼承當(dāng)前應(yīng)用的用戶信息類,并實現(xiàn) UserDetails 的接口。假設(shè)應(yīng)用的用戶信息類是 User,自定義的 CustomUserdetails 繼承 User 類并實現(xiàn) UserDetails 接口。

AuthenticationManager

AuthenticationManager 負(fù)責(zé)校驗 Authentication 對象。在 AuthenticationManager 的 authenticate 函數(shù)中,開發(fā)人員實現(xiàn)對 Authentication 的校驗邏輯。如果 authenticate 函數(shù)校驗通過,正常返回一個重新注入的 Authentication 對象;校驗失敗,則拋出 AuthenticationException 異常。authenticate 函數(shù)簽名如清單 4 所示:

清單 4. authenticate 函數(shù)簽名

Authentication authenticate(Authentication authentication)throws AuthenticationException;

AuthenticationManager 可以將異常拋出的更加明確:

  • 當(dāng)用戶不可用時拋出 DisabledException。
  • 當(dāng)用戶被鎖定時拋出 LockedException。
  • 當(dāng)用戶密碼錯誤時拋出 BadCredentialsException。

重新注入的 Authentication 會包含當(dāng)前用戶的詳細(xì)信息,并且被填充到 SecurityContext 中,這樣 Spring Security 的驗證流程就完成了,Spring Security 可以識別到 "你是誰"。

基本校驗流程示例

下面采用 Spring Security 的核心組件寫一個最基本的用戶名密碼校驗示例,如清單 5 所示:

清單 5. Spring Security 核心組件偽代碼

AuthenticationManager amanager = new CustomAuthenticationManager();
Authentication namePwd = new CustomAuthentication(“name”, “password”);
try {
    Authentication result = amanager.authenticate(namePwd);
    SecurityContextHolder.getContext.setAuthentication(result);
} catch(AuthenticationException e) {
    // TODO 驗證失敗
}

Spring Security 的核心組件易于理解,其基本校驗流程是: 驗證信息傳遞過來,驗證通過,將驗證信息存儲到 SecurityContext 中;驗證失敗,做出相應(yīng)的處理。

Spring Security 在 Web 中的設(shè)計

Spring Security 的一個常見應(yīng)用場景就是 Web。下面討論 Spring Security 在 Web 中的使用方式。

Spring Security 最簡登錄實例

Spring Security 在 Web 中的使用相對要復(fù)雜一點,會涉及到很多組件?,F(xiàn)在給出自定義登錄的偽代碼,如清單 6 所示。您可以點擊這里,查看完整的代碼。

清單 6. Web 登錄偽代碼

@Controller
public class UserController { 
 
    @PostMapping(“/login”)
    public void login(String name, String password){
       matchNameAndPassword(name, password);
       User user = getUser(name);
       Authentication auth = new CustomAuthentication(user, password);
       auth.setAuthenticated(true);
       SecurityContextHolder.getContext.setAuthentication(auth);
    }
}

觀察代碼會發(fā)現(xiàn),如果用 Spring Security 來集成已存在的登錄邏輯,真正和 Spring Security 關(guān)聯(lián)的代碼只有短短 3 行。驗證邏輯可以不經(jīng)過 AuthenticationManager,真正需要做的就是把經(jīng)過驗證的用戶信息注入到 Authentication 中,并將 Authentication 填充到 SecurityContext 中。在實際情況中,登錄邏輯的確可以這樣寫,尤其是已經(jīng)存在登錄邏輯的時候,通常會這樣寫。這樣寫雖然方便,但是不符合 Spring Security 在 Web 中的架構(gòu)設(shè)計。

下面視頻中會介紹已存在的項目如何與 Spring Security 進(jìn)行集成,要求對已存在的登錄驗證邏輯不變,但可以使用 Spring Security 的優(yōu)秀特性和功能。

視頻地址:https://mediacenter.ibm.com/media/0_qvbohipj

項目地址:https://github.com/springAppl/yuchigong

Spring Security 在 Web 中的核心組件

下面介紹在 Web 環(huán)境中 Spring Security 的核心組件。

FilterChainProxy

FilterChaniProxy 是 FilterChain 代理。FilterChain 維護(hù)了一個 Filter 隊列,這些 Filter 為 Spring Security 提供了強(qiáng)大的功能。一個很常見的問題是:Spring Security 在 Web 中的入口是哪里?答案是 Filter。Spring Security 在 Filter 中創(chuàng)建 Authentication 對象,并調(diào)用 AuthenticationManager 進(jìn)行校驗。Spring Security 選擇 Filter,而沒有采用上文中 Controller 的方式有以下優(yōu)點。Spring Security 依賴 J2EE 標(biāo)準(zhǔn),無需依賴特定的 MVC 框架。另一方面 Spring MVC 通過 Servlet 做請求轉(zhuǎn)發(fā),如果 Spring Security 采用 Servlet,那么 Spring Security 和 Spring MVC 的集成會存在問題。FilterChain 維護(hù)了很多 Filter,每個 Filter 都有自己的功能,因此在 Spring Security 中添加新功能時,推薦通過 Filter 的方式來實現(xiàn)。

ProviderManager

ProviderManager 是 AuthenticationManager 的實現(xiàn)類。ProviderManager 并沒有實現(xiàn)對 Authentication 的校驗功能,而是采用代理模式將校驗功能交給 AuthenticationProvider 去實現(xiàn)。這樣設(shè)計是因為在 Web 環(huán)境中可能會支持多種不同的驗證方式,比如用戶名密碼登錄、短信登錄、指紋登錄等等,如果每種驗證方式的代碼都寫在 ProviderManager 中,想想都是災(zāi)難。因此為每種驗證方式提供對應(yīng)的 AuthenticationProvider,ProviderManager 將驗證任務(wù)代理給對應(yīng)的 AuthenticationProvider,這是一種不錯的解決方案。在 ProviderManager 中可以找到以下代碼,如清單 7 所示:

清單 7. ProviderManager 代碼片段

private List<AuthenticationProvider> providers;
public Authentication authenticate(Authentication authentication)
           throws AuthenticationException {
    ......
    for (AuthenticationProvider provider : getProviders()) {
       if (!provider.supports(toTest)) {
           continue;
       }
       try {
           result = provider.authenticate(authentication);
           if (result != null) {
               copyDetails(authentication, result);
               break;
           }
       }
    }
}

ProviderManager 維護(hù)了一個 AuthenticationProvider 隊列。當(dāng) Authentication 傳遞進(jìn)來時,ProviderManager 通過 supports 函數(shù)查找支持校驗的 AuthenticationProvider。如果沒有找到支持的 AuthenticationProvider 將拋出 ProviderNotFoundException 異常。

AuthenticationProvider

AuthenticationProvider 是在 Web 環(huán)境中真正對 Authentication 進(jìn)行校驗的組件。其接口簽名如清單 8 所示:

清單 8. AuthenticationProvider 的接口簽名

public interface AuthenticationProvider {
    Authentication authenticate(Authentication authentication)
           throws AuthenticationException;
    boolean supports(Class<?> authentication);
}

其中,authenticate 函數(shù)用于校驗 Authentication 對象;supports 函數(shù)用于判斷 provider 是否支持校驗 Authentication 對象。

當(dāng)應(yīng)用添加新的驗證方式時,驗證邏輯需要寫在對應(yīng) AuthenticationProvider 中的 authenticate 函數(shù)中。驗證通過返回一個重新注入的 Authentication,驗證失敗拋出 AuthenticationException 異常。

Spring Security 在 Web 中的認(rèn)證示例

下面的視頻中會介紹采用 Spring Security 提供的 UsernamePasswordAuthenticationFilter 實現(xiàn)登錄驗證。

視頻地址:https://mediacenter.ibm.com/media/0_7vq75cue

項目地址:https://github.com/springAppl/rachel

下面以用戶名密碼登錄為例來梳理 Spring Security 在 Web 中的認(rèn)證流程。上文提到 Spring Security 是以 Filter 來作為校驗的入口點。在用戶名密碼登錄中對應(yīng)的 Filter 是 UsernamePasswordAuthenticationFilter。attemptAuthentication 函數(shù)會執(zhí)行調(diào)用校驗的邏輯。在 attemptAuthentication 函數(shù)中,可以找到以下代碼,如清單 9 所示:

清單 9. attemptAuthentication 函數(shù)代碼片段

public Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse 
response) throws AuthenticationException {
    ......
    UsernamePasswordAuthenticationToken authRequest = new 
UsernamePasswordAuthenticationToken(username, password);
    setDetails(request, authRequest);
    return this.getAuthenticationManager().authenticate(authRequest);
}

attemptAuthentication 函數(shù)會調(diào)用 AuthenticationManager 執(zhí)行校驗邏輯,并獲取到重新注入后的 Authentication。在 UsernamePasswordAuthenticationFilter 父類 AbstractAuthenticationProcessingFilter 的 successfulAuthentication 函數(shù)中發(fā)現(xiàn)以下代碼,如清單 10 所示:

清單 10. successAuthentication 函數(shù)

protected void successfulAuthentication(HttpServletRequest request,
           HttpServletResponse response, FilterChain chain, Authentication 
authResult)throws IOException, ServletException {
    ......     SecurityContextHolder.getContext().setAuthentication(authResult);
    ......
}

successfulAuthentication 函數(shù)會把重新注入的 Authentication 填充到 SecurityContext 中,完成驗證。

在 Web 中,AuthenticationManager 的實現(xiàn)類 ProviderManager 并沒有實現(xiàn)校驗邏輯,而是代理給 AuthenticationProvider, 在用戶名密碼登錄中就是 DaoAuthenticationProvider。DaoAuthenticationProvider 主要完成 3 個功能:獲取 UserDetails、校驗密碼、重新注入 Authentication。在 authenticate 函數(shù)中發(fā)現(xiàn)以下代碼,如清單 11 所示:

清單 11. DaoAuthenticationProvider.authenticate 函數(shù)簽名

public Authentication authenticate(Authentication authentication)
           throws AuthenticationException {
    ......
    // 獲取 UserDetails
    UserDetails user = this.userCache.getUserFromCache(username);
    if (user == null) {
       cacheWasUsed = false;
       try {
           user = retrieveUser(username,         
    (UsernamePasswordAuthenticationToken) authentication);
       }
       ......
    }
    ......
    try {
       ......
       //校驗密碼
       additionalAuthenticationChecks(
           user,
       (UsernamePasswordAuthenticationToken) authentication
       );
    }
    ......
    // 從新注入 Authentication
    return createSuccessAuthentication(
           principalToReturn, 
           authentication, 
           user
        );
}

首先從 userCache 緩存中查找 UserDetails, 如果緩存中沒有獲取到,調(diào)用 retrieveUser 函數(shù)獲取 UserDetails。retrieveUser 函數(shù)簽名如清單 12 所示:

清單 12. retrieveUser 函數(shù)簽名

protected final UserDetails retrieveUser(String username,
    UsernamePasswordAuthenticationToken authentication)
           throws AuthenticationException {
    UserDetails loadedUser;
    try {
        loadedUser = this.getUserDetailsService().loadUserByUsername(username);
    }
    ......
    return loadedUser;
}

retrieveUser 函數(shù)調(diào)用 UserDetailsService 獲取 UserDetails 對象。UserDetailsService 接口簽名如清單 13 所示:

清單 13. UserDetailsService 接口簽名

public interface UserDetailsService {
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

UserDetailsService 非常簡單,只有一個 loadUserByUserName 函數(shù),函數(shù)參數(shù)雖然名為 username,但只要是用戶的唯一標(biāo)識符即可。下面是基于數(shù)據(jù)庫存儲的簡單示例, 如清單 14 所示:

清單 14. CustomUserDetailsService 類簽名

public class CustomUserDetailsService implements UserDetailsService {
   
  @Autowired
  private UserDao userDao;
 
  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
{
    User user = userDao.findByName(username);
    if(Objects.isNull(user)) {
      throw new UsernameNotFoundException();
    }
    UserDetails details = new CustomUserDetails(user);
    return details;
  }
}

調(diào)用 UserDao 獲取 User 對象,將 User 對象包裝成 UserDetails 對象。如果沒有找到 User 對象,需要拋出 UsernameNotFoundException 異常。

DaoAuthenticationProvider 密碼校驗調(diào)用 additionalAuthenticationChecks 函數(shù),具體通過 PasswordEncoder 比對用戶輸入的密碼和存儲在應(yīng)用中的密碼是否相等,如果不相等,拋出 BadCredentialsException 異常。

DaoAuthenticationProvider 對 Authentication 對象的重新注入通過調(diào)用 createSuccessAuthentication 函數(shù), 如清單 15 所示:

清單 15. createSuccessAuthentication 函數(shù)簽名

protected Authentication createSuccessAuthentication(Object principal,
           Authentication authentication, UserDetails user) {
    UsernamePasswordAuthenticationToken result = new    
    UsernamePasswordAuthenticationToken(
        principal, 
        authentication.getCredentials(),     
        authoritiesMapper.mapAuthorities(user.getAuthorities())
    );
    result.setDetails(authentication.getDetails());
    return result;
}

以上就是 Spring Security 在 Web 環(huán)境中對于用戶名密碼校驗的整個流程,簡言之:

  1. UsernamePasswordAuthenticationFilter 接受用戶名密碼登錄請求,將 Authentication 傳遞給 ProviderManager 進(jìn)行校驗。
  2. ProviderManager 將校驗任務(wù)代理給 DaoAuthenticationProvider。
  3. DaoAuthenticationProvider 對 Authentication 的用戶名和密碼進(jìn)行校驗,校驗通過后返回重新注入的 Authentication 對象。
  4. UsernamePasswordAuthenticationFilter 將重新注入的 Authentication 對象填充到 SecurityContext 中。

指紋登錄實踐

指紋登錄和用戶名密碼登錄區(qū)別很小,只是將密碼換成了指紋特征值。下面采用 Spring Security 推薦寫法 Filter-AuthenticationProvider 的形式來定義相關(guān)組件以實現(xiàn)指紋登錄。完整的項目地址:https://github.com/springAppl/rachel。

FingerPrintToken

FingerPrintToken 增加 name 和 fingerPrint 字段,分別代表用戶名和指紋特征值,如清單 16 所示:

清單 16. FingerPrintToken 函數(shù)簽名

public class FingerPrintToken implements Authentication {
    private String name;  
    private String fingerPrint;
    ......
}

FingerPrintFilter

FingerPrintFilter 處理指紋登錄請求,調(diào)用 AuthenticationManager 進(jìn)行驗證,驗證通過后調(diào)用 SecurityContextHolder 將重新注入的 Authentication 填充到 SecurityContext 中,如清單 17 所示:

清單 17. doFilter 函數(shù)簽名

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 
FilterChain filterChain) throws IOException, ServletException {
    if (Objects.equals(httpServletRequest.getRequestURI(), "/api/finger-print")) {
        // 調(diào)用 AuthenticationManager, 并填充 SecurityContext
    }
}

FingerPrintProvider

FingerPrintProvider 負(fù)責(zé)處理 FingerPrintToken,需要在 supports 函數(shù)中支持處理 FingerPrintToken。authenticate 函數(shù)負(fù)責(zé) UserDetails 獲取,指紋校驗,F(xiàn)ingerPrintToken 的重新注入。

FingerPrintUserDetails

FingerPrintUserDetails 繼承 User 并實現(xiàn) UserDetails 的方法,應(yīng)用的用戶信息可以加載到 Spring Security 中使用。

FingerPrintUserDetailsService

FingerPrintUserDetailsService 獲取 FingerUserDetails。通過 UserDao 查找到 User,并將 User 轉(zhuǎn)換為 Spring Security 可識別 UserDetails。

SecurityConfig

SecurityConfig 繼承 WebSecurityConfigurerAdapter,需要定義 Spring Security 配置類。Spring Security 的配置不是本文的重點,配置時只需要注意以下幾點:

  1. 將 FingerPrintFilter、FingerPrintProvider 添加進(jìn)去。
  2. 將 FingerPrintFilter 的執(zhí)行順序放置在 SecurityContextPersistenceFilter 之后即可。Spring Security 維護(hù)了一個 Filter 的 list,因此每個 Filter 是有順序的。
  3. 將 "/api/test" 請求設(shè)置為用戶驗證成功后才允許方問。

配置代碼在 configure 函數(shù)中,如清單 18 所示:

清單 18. configure 函數(shù)

protected void configure(HttpSecurity http) throws Exception {
    http
       .userDetailsService(userDetailsService())
       .addFilterAfter(fingerPrintFilter(), SecurityContextPersistenceFilter.class)
       .authenticationProvider(fingerPrintProvider())
       .authorizeRequests()
       .mvcMatchers(HttpMethod.GET, "/api/test").authenticated()
}

總結(jié)

在 Web 時代,用戶和應(yīng)用的耦合度越來越高,應(yīng)用中存儲了大量用戶的私密信息。隨著各種用戶信息泄露事件的爆發(fā),安全成為了 Web 應(yīng)用重要的一個環(huán)。Spring Security 由于其強(qiáng)大的功能和 Spring Framework 的高度集成,贏得了開發(fā)人員的青睞。本文對 Spring Security 的架構(gòu)設(shè)計與核心組件進(jìn)行了深入淺出的介紹,分析了 Spring Security 在 Web 應(yīng)用的集成方式,并展示了一個指紋登錄的實例。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java使用MyBatis框架分頁的5種方式

    Java使用MyBatis框架分頁的5種方式

    這篇文章主要為大家詳細(xì)介紹了Java使用MyBatis框架分頁的5種方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • 基于kafka實現(xiàn)Spring Cloud Bus消息總線

    基于kafka實現(xiàn)Spring Cloud Bus消息總線

    消息總線是一種通信工具,可以在機(jī)器之間互相傳輸消息、文件等,這篇文章主要介紹了如何利用kafka實現(xiàn)SpringCloud Bus消息總線,感興趣的可以學(xué)習(xí)一下
    2022-04-04
  • 快速入手IntelliJ IDEA基本配置

    快速入手IntelliJ IDEA基本配置

    IntelliJ IDEA是java編程語言開發(fā)的集成環(huán)境,本篇主要介紹了對它的安裝、配置maven倉庫、調(diào)試方法、常用的插件推薦、快捷鍵大全與常用快捷鍵說明,感興趣的朋友一起看看吧
    2021-10-10
  • 重寫Java中的equals方法介紹

    重寫Java中的equals方法介紹

    這篇文章主要介紹了重寫Java中的equals方法介紹,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • Java多線程事務(wù)回滾@Transactional失效處理方案

    Java多線程事務(wù)回滾@Transactional失效處理方案

    這篇文章主要介紹了Java多線程事務(wù)回滾@Transactional失效處理方案,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-08-08
  • 解析SpringSecurity自定義登錄驗證成功與失敗的結(jié)果處理問題

    解析SpringSecurity自定義登錄驗證成功與失敗的結(jié)果處理問題

    這篇文章主要介紹了SpringSecurity系列之自定義登錄驗證成功與失敗的結(jié)果處理問題,本文通過實例給大家講解的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-11-11
  • @PropertySource 無法讀取配置文件的屬性值解決方案

    @PropertySource 無法讀取配置文件的屬性值解決方案

    這篇文章主要介紹了@PropertySource 無法讀取配置文件的屬性值解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java實現(xiàn)簡單圖形界面計算器

    Java實現(xiàn)簡單圖形界面計算器

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)簡單圖形界面計算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Java 讀取excel 文件流代碼實例

    Java 讀取excel 文件流代碼實例

    這篇文章主要介紹了Java 讀取excel 文件流代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • netty中的ByteBuf源碼詳解

    netty中的ByteBuf源碼詳解

    這篇文章主要介紹了netty中的ByteBuf源碼詳解,ByteBuf,顧名思義,就是字節(jié)緩沖區(qū),是Netty中非常重要的一個組件,某些場景下性能不是太好,netty開發(fā)團(tuán)隊重新設(shè)計了ByteBuf用以替代原生ByteBuffer,需要的朋友可以參考下
    2023-11-11

最新評論