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

新版SpringSecurity5.x使用與配置詳解

 更新時間:2024年08月16日 10:37:36   作者:Alphamilk  
Spring Security是一個強大且高度可定制的身份驗證和訪問控制框架,本文主要介紹了新版SpringSecurity5.x使用與配置詳解,具有一定的參考價值,感興趣的可以了解一下

一、了解SpringSecurity

1.1 什么是Spring Security?

Spring Security 是一個強大且高度可定制的身份驗證和訪問控制框架。它是 Spring 生態(tài)系統(tǒng)的一部分,為基于 Spring 的應(yīng)用提供了全面的安全服務(wù)。Spring Security 的設(shè)計目標是為應(yīng)用的安全需求提供一個完整的解決方案,同時保持高度的靈活性和可擴展性。

1.2 Spring Security功能

Spring Security 提供的功能包括但不限于:

  • 認證(Authentication):驗證用戶身份,通常需要用戶名和密碼。
  • 授權(quán)(Authorization):確定已認證的用戶可以訪問哪些資源或執(zhí)行哪些操作。
  • CSRF 保護:防止跨站請求偽造攻擊。
  • 會話管理:處理用戶的會話,包括會話的創(chuàng)建、維護和銷毀。
  • 加密和編碼:提供加密和散列算法的支持。
  • OAuth2 和 OpenID Connect 支持:集成 OAuth2 和 OpenID Connect 協(xié)議,實現(xiàn)第三方認證。
  • CORS 支持:處理跨域資源共享(Cross-Origin Resource Sharing)請求。
  • 安全配置:允許通過 XML 或 Java 配置來定制安全策略。

1.3 Spring Security原理

Spring Security 的工作原理涉及幾個關(guān)鍵組件:

  • SecurityContext:存儲認證信息,如當(dāng)前登錄用戶和他們的權(quán)限。
  • AuthenticationManager:負責(zé)用戶認證,通常使用 UserDetailsService 來加載用戶信息。
  • AccessDecisionManager:決定用戶是否有權(quán)訪問特定資源。
  • Filter Chain:一系列的過濾器處理請求和響應(yīng),例如 UsernamePasswordAuthenticationFilter 用于處理用戶名和密碼的提交。

1.4 RABC (Role-Based Access Control)

RABC,即基于角色的訪問控制,是一種常見的訪問控制機制,用于管理用戶對資源的訪問權(quán)限。在 RABC 中,權(quán)限不是直接授予用戶,而是授予用戶所屬的角色。每個用戶可以擁有一個或多個角色,而每個角色則有一組相應(yīng)的權(quán)限。這種機制簡化了權(quán)限管理,因為只需更改用戶的角色就可以改變他們的權(quán)限集。

二、SpringSecurity簡單案例

2.1 引入SpringSecurity依賴

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
     <groupId>org.springframework.security</groupId>
     <artifactId>spring-security-test</artifactId>
     <scope>test</scope>
</dependency>

 2.2 創(chuàng)建一個簡單的Controller

@RestController
public class HelloController {
    @GetMapping("Hello")
    public String Hello(){
        return "Hello SpringSecurity";
    }
}

2.3 運行后訪問localhost:8080/Hello會自動跳轉(zhuǎn)到localhost:8080/login

這里的用戶密碼都在啟動時候的控制臺上  (注意:每一次啟動密碼都不一樣)

用戶名:user

密碼:    b82aa5e5-0a3a-466b-90a8-e94098877823(控制臺上的一串密碼)

登陸后成功訪問

三、SpringSecurity配置

后面的配置都是基于小案例的基礎(chǔ)上實現(xiàn),請先完成上述的小案例

3.1 自定義用戶與密碼

由于每一次生成密碼都是不固定的,對調(diào)試并不友好,springSecurity可以通過在application.yml中進行自定義設(shè)置用戶和密碼

spring:
  security:
    user:
      name: alphaMilk
      password: 123456

輸入用戶名和密碼即可正常登陸并訪問資源

3.2 允許匿名訪問路徑

在Spring Security框架中,允許某些路徑或資源在未經(jīng)過身份驗證的情況下被訪問,通常稱為“允許匿名訪問”。這種配置對于公共頁面、登錄頁面、注冊頁面、API文檔等是非常必要的,因為這些頁面或資源需要對所有用戶開放,無論他們是否已經(jīng)登錄。

以下通過配置類實現(xiàn),用戶能夠匿名訪問login頁面

// 使用@Configuration標記此類為Spring的配置類
@Configuration
// 啟用WebSecurity的自動配置,以便Spring Security可以管理Web安全
@EnableWebSecurity
public class SecurityConfiguration {

    // 定義一個名為securityFilterChain的bean,該bean將負責(zé)構(gòu)建和應(yīng)用安全過濾器鏈
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 配置HttpSecurity對象,定義安全規(guī)則
        http
                // 授權(quán)HTTP請求,定義哪些URL需要什么類型的訪問控制
                .authorizeHttpRequests((authz) -> authz
                        // 允許"/user/login" URL匿名訪問
                        .requestMatchers("/user/login").anonymous()
                        
                        // 所有其他請求都需要認證才能訪問
                        .anyRequest().authenticated())
                
                // 啟用HTTP Basic認證,默認情況下提供簡單的用戶名/密碼認證
                .httpBasic(Customizer.withDefaults());

        // 構(gòu)建并返回SecurityFilterChain
        return http.build();
    }
}

創(chuàng)建一個LoginController類

@RestController
@RequestMapping("user")
public class LoginController {
    
    @GetMapping("/login")
    public String Login(){
        return "這是登陸資源頁面";
    }
}

重啟系統(tǒng)后直接訪問,不需要登陸即可獲取資源.

3.3 數(shù)據(jù)庫實現(xiàn)登陸校驗

通過自己數(shù)據(jù)庫的用戶和密碼,實現(xiàn)登陸。將之前的自定義用戶密碼(application.yml中)都刪除掉,并執(zhí)行以下操作:

用戶表單:

-- 創(chuàng)建一個包含用戶信息和角色的簡化表
CREATE TABLE IF NOT EXISTS `users` (
    `id` INT AUTO_INCREMENT PRIMARY KEY,          -- 用戶ID,自增主鍵
    `username` VARCHAR(255) NOT NULL UNIQUE,      -- 用戶名,唯一且不能為空
    `password` VARCHAR(255) NOT NULL,             -- 密碼,存儲加密后的密碼
    `role` ENUM('ROLE_USER', 'ROLE_ADMIN') NOT NULL, -- 角色,預(yù)定義為'ROLE_USER'或'ROLE_ADMIN'
    `enabled` TINYINT(1) NOT NULL DEFAULT 1       -- 用戶狀態(tài),1表示啟用,0表示禁用
);

注意:這里的role需要按照ROLE_身份 的方式進行存儲以便springsecurity進行權(quán)限訪問控制

插入案例數(shù)據(jù) :

-- 插入示例用戶數(shù)據(jù)
INSERT INTO `users` (`username`, `password`, `role`, `enabled`)
VALUES
    ('user1', '123456', 'ROLE_USER', 1),
    ('admin1', '123456', 'ROLE_ADMIN', 1),
    ('disabledUser', '123456', 'ROLE_USER', 0);

引入依賴:

<!--        數(shù)據(jù)庫依賴-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.5</version>
            <exclusions>
                <exclusion>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis-spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>3.0.3</version>
        </dependency>
        
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

配置數(shù)據(jù)源:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ap_security?characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

 創(chuàng)建User實體與mapper并加上啟動注釋

User實體

@TableName(value ="users")
@Data
public class Users implements Serializable {
    /**
     * 
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    /**
     * 
     */
    private String username;

    /**
     * 
     */
    private String password;

    /**
     * 
     */
    private Object role;

    /**
     * 
     */
    private Integer enabled;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;

    @Override
    public boolean equals(Object that) {
        if (this == that) {
            return true;
        }
        if (that == null) {
            return false;
        }
        if (getClass() != that.getClass()) {
            return false;
        }
        Users other = (Users) that;
        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
            && (this.getUsername() == null ? other.getUsername() == null : this.getUsername().equals(other.getUsername()))
            && (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword()))
            && (this.getRole() == null ? other.getRole() == null : this.getRole().equals(other.getRole()))
            && (this.getEnabled() == null ? other.getEnabled() == null : this.getEnabled().equals(other.getEnabled()));
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
        result = prime * result + ((getUsername() == null) ? 0 : getUsername().hashCode());
        result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode());
        result = prime * result + ((getRole() == null) ? 0 : getRole().hashCode());
        result = prime * result + ((getEnabled() == null) ? 0 : getEnabled().hashCode());
        return result;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", username=").append(username);
        sb.append(", password=").append(password);
        sb.append(", role=").append(role);
        sb.append(", enabled=").append(enabled);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}

UserMapper

public interface UsersMapper extends BaseMapper<Users> {

}

@MapperScan

@SpringBootApplication
@MapperScan("com.example.mysecurity.mapper")
public class MySecurityApplication {

    public static void main(String[] args) {
        SpringApplication.run(MySecurityApplication.class, args);
    }

}

測試mybatisPlus是否配置正確

@SpringBootTest
class MySecurityApplicationTests {

    @Autowired
    private UsersMapper usersMapper;

    @Test
    void contextLoads() {
        List<Users> users = usersMapper.selectList(null);
        System.out.println(users);
    }

}

通過后,即可開始實現(xiàn)通過自己數(shù)據(jù)庫進行登陸功能:

先創(chuàng)建返回的驗證類

 LoginUser 實現(xiàn) UserDetails

@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginUser implements UserDetails {

    private Users user;


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

登陸實現(xiàn)類

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UsersMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根據(jù)用戶名查詢用戶信息
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(Users::getUsername,username);
        Users user = userMapper.selectOne(wrapper);

        //如果查詢不到數(shù)據(jù)就通過拋出異常來給出提示
        if(Objects.isNull(user)){
            throw new RuntimeException("用戶名或密碼錯誤");
        }


        Collection<? extends GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority(user.getRole()));

        //封裝成UserDetails對象返回 
        return new LoginUser(user,authorities);
    }
}

由于在Spring Boot 2.3及更高版本中,Spring Security默認不再提供任何內(nèi)置的PasswordEncoder。這意味著如果在配置中直接使用明文密碼或沒有正確配置PasswordEncoder,你將看到這個異常。這里暫時先使用明文加密。后面將一步步完善加密功能.

在SecurityConfig中加入配置

@Configuration
// 啟用WebSecurity的自動配置,以便Spring Security可以管理Web安全
@EnableWebSecurity
public class SecurityConfiguration {

//    設(shè)置密碼加密為明文加密
    @Bean
    public org.springframework.security.crypto.password.PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
    
    // 定義一個名為securityFilterChain的bean,該bean將負責(zé)構(gòu)建和應(yīng)用安全過濾器鏈
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 配置HttpSecurity對象,定義安全規(guī)則
        http
                // 授權(quán)HTTP請求,定義哪些URL需要什么類型的訪問控制
                .authorizeHttpRequests((authz) -> authz
                        // 允許"/user/login" URL匿名訪問
                        .requestMatchers("/user/login").anonymous()
                        
                        // 所有其他請求都需要認證才能訪問
                        .anyRequest().authenticated())
                
                // 啟用HTTP Basic認證,默認情況下提供簡單的用戶名/密碼認證
                .httpBasic(Customizer.withDefaults());

        // 構(gòu)建并返回SecurityFilterChain
        return http.build();
    }
}

再次訪問localhost:8080/Hello后彈出登陸框:

輸入任意的用戶與密碼即可正常訪問

3.4 實現(xiàn)角色權(quán)限訪問

在Controller中定義一個Admin資源類,只有admin用戶才能進行訪問

@RequestMapping("admin")
@RestController
@Slf4j
public class AdminController {

    @GetMapping("resourse")
    public String AdminRole(){
        return "這是只有管理員用戶才能訪問的資源";
    }

}

在設(shè)置中進行配置

@Configuration
// 啟用WebSecurity的自動配置,以便Spring Security可以管理Web安全
@EnableWebSecurity
public class SecurityConfiguration {

//    設(shè)置密碼加密為明文加密
    @Bean
    public org.springframework.security.crypto.password.PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    // 定義一個名為securityFilterChain的bean,該bean將負責(zé)構(gòu)建和應(yīng)用安全過濾器鏈
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 配置HttpSecurity對象,定義安全規(guī)則
        http
                // 授權(quán)HTTP請求,定義哪些URL需要什么類型的訪問控制
                .authorizeHttpRequests((authz) -> authz
                        .requestMatchers("/user/login").anonymous()
//                        需要有Admin身份的用戶才能進行訪問
                        .requestMatchers("/admin/**").hasRole("ADMIN")
                        // 所有其他請求都需要認證才能訪問
                        .anyRequest().authenticated())
                
                // 啟用HTTP Basic認證,默認情況下提供簡單的用戶名/密碼認證
                .httpBasic(Customizer.withDefaults());

        // 構(gòu)建并返回SecurityFilterChain
        return http.build();
    }
}

重啟服務(wù)器后分別用兩種身份進行訪問

用戶訪問:

管理員訪問:

3.5 對密碼進行B加密

config中進行配置BCrypt

@Configuration
// 啟用WebSecurity的自動配置,以便Spring Security可以管理Web安全
@EnableWebSecurity
public class SecurityConfiguration {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;


//    設(shè)置密碼加密為B加密
    @Bean
    public PasswordEncoder passwordEncoder() {
     return new BCryptPasswordEncoder();
    }


    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }



    // 定義一個名為securityFilterChain的bean,該bean將負責(zé)構(gòu)建和應(yīng)用安全過濾器鏈
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 配置HttpSecurity對象,定義安全規(guī)則
        http
                // 授權(quán)HTTP請求,定義哪些URL需要什么類型的訪問控制
                .authorizeHttpRequests((authz) -> authz
                        .requestMatchers("/user/login").anonymous()
//                        需要有Admin身份的用戶才能進行訪問
                        .requestMatchers("/admin/**").hasRole("ADMIN")
                        // 所有其他請求都需要認證才能訪問
                        .anyRequest().authenticated())
                
                // 啟用HTTP Basic認證,默認情況下提供簡單的用戶名/密碼認證
                .httpBasic(Customizer.withDefaults());

        // 構(gòu)建并返回SecurityFilterChain
        return http.build();
    }
}

由于數(shù)據(jù)庫中都是明文的密碼,所以這里可以通過創(chuàng)建一個SpringbootTest類,將所有用戶的密碼改為B加密后的數(shù)據(jù).

    @Test
    public void testUpdateAllPasswords() {
        // 創(chuàng)建一個BCryptPasswordEncoder實例
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

        // 更新所有用戶的密碼為加密后的"123456"
        String encodedPassword = encoder.encode("123456");

        // 構(gòu)造更新條件
        LambdaUpdateWrapper<Users> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Users::getPassword, encodedPassword);

        // 執(zhí)行更新操作
        boolean result = usersMapper.update(null, updateWrapper) > 0;

        if (result) {
            System.out.println("所有用戶的密碼更新成功!");
        } else {
            System.out.println("密碼更新失?。?);
        }
        
    }

配置好后,重新進行登陸查看輸入對應(yīng)的admin1和123456

3.6 結(jié)合Jwt實現(xiàn)多重校驗

 Spring Security 和 JSON Web Tokens (JWT) 可以協(xié)同工作來提供更靈活和安全的身份驗證和授權(quán)機制。盡管 Spring Security 提供了一套全面的安全框架,但它默認使用基于會話的認證機制,這意味著服務(wù)器維護著與客戶端的活動會話狀態(tài)。而JWT提供了一種無狀態(tài)的認證方式,這意味著每個請求都包含完整的認證信息,無需服務(wù)器保存會話狀態(tài)。

pom文件中引入jwt所需要的依賴

<!--        JWT依賴-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

Jwt資源類:

@Component
@ConfigurationProperties(prefix = "jwt")
@Data
public class JwtProperties {

    private String SecretKey;
    private long Ttl;
    private String TokenName;


}

Jwt yml配置:

jwt:
  secret-key: Alphamilk
  token-name: Authorization
  ttl: 10800000

實現(xiàn)Jwt的工具類

@Component
public class JwtUtil {

    @Autowired
    private JwtProperties jwtProperties;

    public String createJWT(Map<String, Object> claims, long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);

        return Jwts.builder()
                .setClaims(claims)
                .signWith(signatureAlgorithm, jwtProperties.getSecretKey().getBytes(StandardCharsets.UTF_8))
                .setExpiration(exp)
                .compact();
    }

    public Claims parseJWT(String token) {
        return Jwts.parser()
                .setSigningKey(jwtProperties.getSecretKey().getBytes(StandardCharsets.UTF_8))
                .parseClaimsJws(token)
                .getBody();
    }

    public boolean isTokenValid(String token, UserDetails userDetails) {
        final String username = getUsernameFromToken(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }

    private String getUsernameFromToken(String token) {
        Claims claims = parseJWT(token);
        return (String) claims.getSubject();
    }

    private boolean isTokenExpired(String token) {
        try {
            final Date expiration = parseJWT(token).getExpiration();
            return expiration.before(new Date());
        } catch (ExpiredJwtException e) {
            return true;
        }
    }
}

Jwt的校驗Filter

@Component
public class JwtFilter extends OncePerRequestFilter {

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(jwtProperties.getTokenName());

        if (token != null) {
            try {
                Claims claims = jwtUtil.parseJWT(token);
                String username = (String) claims.get("userName");

                if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                    UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
                    if (jwtUtil.isTokenValid(token, userDetails)) {
                        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                                userDetails, null, userDetails.getAuthorities());
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    }
                }
            } catch (ExpiredJwtException ex) {

                response.sendError(HttpServletResponse.SC_FORBIDDEN, "Token has expired.");
            } catch (JwtException ex) {

                response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid token.");
            }
        }else {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "No token provided.");
        }
        filterChain.doFilter(request, response);
    }
}

將jwt校驗規(guī)則加入到Spring的Filter中進行校驗

@Configuration
// 啟用WebSecurity的自動配置,以便Spring Security可以管理Web安全
@EnableWebSecurity
public class SecurityConfiguration {

    @Autowired

    private JwtFilter jwtFilter;


    @Autowired
    private UserDetailsServiceImpl userDetailsService;


//    設(shè)置密碼加密為B加密
    @Bean
    public PasswordEncoder passwordEncoder() {
     return new BCryptPasswordEncoder();
    }


    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }



    // 定義一個名為securityFilterChain的bean,該bean將負責(zé)構(gòu)建和應(yīng)用安全過濾器鏈
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 配置HttpSecurity對象,定義安全規(guī)則
        http
                // 授權(quán)HTTP請求,定義哪些URL需要什么類型的訪問控制
                .authorizeHttpRequests((authz) -> authz
                        .requestMatchers("/user/login").anonymous()
//                        需要有Admin身份的用戶才能進行訪問
                        .requestMatchers("/admin/**").hasRole("ADMIN")
                        // 所有其他請求都需要認證才能訪問
                        .anyRequest().authenticated())

                // 啟用HTTP Basic認證,默認情況下提供簡單的用戶名/密碼認證
                .httpBasic(Customizer.withDefaults());
//        加入jwtFIlter
        http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        // 構(gòu)建并返回SecurityFilterChain
        return http.build();
    }
}

到此這篇關(guān)于新版SpringSecurity5.x使用與配置詳解的文章就介紹到這了,更多相關(guān)SpringSecurity5.x使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • IDEA 去除 mybatis.xml 文件黃色警告的圖文教程

    IDEA 去除 mybatis.xml 文件黃色警告的圖文教程

    這篇文章主要介紹了IDEA 去除 mybatis.xml 文件黃色警告的方法,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Java使用Apache compress實現(xiàn)文件夾壓縮成Zip包

    Java使用Apache compress實現(xiàn)文件夾壓縮成Zip包

    Apache common提供了很多實用的工具包,這篇文章主要來和大家介紹一下Java如何使用Apache compress包實現(xiàn)文件夾壓縮成Zip包,希望對大家有所幫助
    2024-01-01
  • idea啟動與jar包啟動中使用resource資源文件路徑的問題

    idea啟動與jar包啟動中使用resource資源文件路徑的問題

    這篇文章主要介紹了idea啟動與jar包啟動中使用resource資源文件路徑的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • java中如何實現(xiàn) zip rar 7z 壓縮包解壓

    java中如何實現(xiàn) zip rar 7z 壓縮包解壓

    這篇文章主要介紹了java中如何實現(xiàn) zip rar 7z 壓縮包解壓問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Mybatis3中方法返回生成的主鍵:XML,@SelectKey,@Options詳解

    Mybatis3中方法返回生成的主鍵:XML,@SelectKey,@Options詳解

    這篇文章主要介紹了Mybatis3中方法返回生成的主鍵:XML,@SelectKey,@Options,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • SpringBoot下實現(xiàn)session保持方式

    SpringBoot下實現(xiàn)session保持方式

    這篇文章主要介紹了SpringBoot下實現(xiàn)session保持方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot+mail 輕松實現(xiàn)各類郵件自動推送

    SpringBoot+mail 輕松實現(xiàn)各類郵件自動推送

    在實際的項目開發(fā)過程中,經(jīng)常需要用到郵件通知功能,例如,通過郵箱注冊,郵箱找回密碼,郵箱推送報表等等,實際的應(yīng)用場景非常的多,今天通過這篇文章,我們一起來學(xué)習(xí)如何在 Spring Boot 中快速實現(xiàn)一個自動發(fā)送郵件的功能
    2024-07-07
  • Java Swing GridBagLayout網(wǎng)格袋布局的實現(xiàn)

    Java Swing GridBagLayout網(wǎng)格袋布局的實現(xiàn)

    這篇文章主要介紹了Java Swing GridBagLayout網(wǎng)格袋布局的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • JavaWeb項目音頻資源播放實現(xiàn)方法詳解

    JavaWeb項目音頻資源播放實現(xiàn)方法詳解

    這篇文章主要介紹了JavaWeb項目音頻資源播放實現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • Java實現(xiàn) 基于密度的局部離群點檢測------lof算法

    Java實現(xiàn) 基于密度的局部離群點檢測------lof算法

    這篇文章主要介紹了Java實現(xiàn) 基于密度的局部離群點檢測------lof算法,本文通過算法概述,算法Java源碼,測試結(jié)果等方面一一進行說明,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07

最新評論