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

SpringSecurity角色權(quán)限控制(SpringBoot+SpringSecurity+JWT)

 更新時(shí)間:2024年05月07日 11:32:38   作者:lans_g  
本文主要介紹了SpringSecurity角色權(quán)限控制(SpringBoot+SpringSecurity+JWT),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、項(xiàng)目介紹

通過springboot整合jwt和security,以用戶名/密碼的方式進(jìn)行認(rèn)證和授權(quán)。認(rèn)證通過jwt+數(shù)據(jù)庫的,授權(quán)這里使用了兩種方式,分別是SpringSecurity自帶的hasRole方法+SecurityConfig 和 我們自定義的permission+@PreAuthorize注解。

二、SpringSecurity簡介

SpringSecurity中的幾個(gè)重要組件:

1.SecurityContextHolder(class)

用來存儲(chǔ)和獲取當(dāng)前線程關(guān)聯(lián)的 SecurityContext 對象的類。

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-ku2An95n-1683728698707)(E:/Blog/lansg/source/img/1683186758072-ccd6a67a-c2c5-4ec7-aca3-b42404ce8277.png)]

其中有兩種 SecurityContext 模式:

  • MODE_THREADLOCAL:將 SecurityContext 對象存儲(chǔ)到當(dāng)前線程中,只在當(dāng)前線程中可見。多線程時(shí),每個(gè)線程的 SecurityContext 對象都是獨(dú)立的。
  • MODE_INHERITABLETHREADLOCAL:將 SecurityContext 對象存儲(chǔ)到當(dāng)前線程中,對當(dāng)前線程和子線程都可見。也就是說,在當(dāng)前線程中存儲(chǔ)的 SecurityContext 對象可以被傳遞給子線程使用。

表示用戶已通過身份驗(yàn)證的最簡單方法就是設(shè)置 SecurityContextHolder!

2.SecurityContext(Interface)

用來存儲(chǔ)當(dāng)前已經(jīng)被認(rèn)證的用戶,包含了當(dāng)前執(zhí)行操作的線程上下文信息以及用戶認(rèn)證和授權(quán)信息。包含Authentication。

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-KFfG9auG-1683728698708)(E:/Blog/lansg/source/img/1683186616655-7d1408b0-f5aa-4a06-ae7e-417d63c3fe94.png)]

3.Authentication(Interface)

存儲(chǔ)了當(dāng)前正在執(zhí)行操作的用戶的身份驗(yàn)證信息,包括用戶名、密碼、權(quán)限,可以作為AuthenticationManager的輸入,它包含principal、credentials、authorities。

  • principal:用戶的標(biāo)識(shí)。通常情況下是UserDetails接口的一個(gè)實(shí)例。
  • credentials:用戶的密碼。多數(shù)情況下,為確保密碼不被泄露,會(huì)在用戶身份驗(yàn)證之后被清除。
  • authorities:用戶擁有的權(quán)限。

Authentication 接口的常用實(shí)現(xiàn)類有以下幾種:

  • AnonymousAuthenticationToken:匿名用戶的身份驗(yàn)證信息。
  • UsernamePasswordAuthenticationToken:用戶名/密碼的身份驗(yàn)證信息。
  • RememberMeAuthenticationToken:用于“記住我”功能的身份驗(yàn)證信息。
  • PreAuthenticatedAuthenticationToken:基于預(yù)先認(rèn)證信息的身份驗(yàn)證。

通常情況下,用戶在進(jìn)行登錄時(shí)需要通過身份驗(yàn)證,當(dāng)身份驗(yàn)證成功時(shí),就會(huì)通過 Authentication 接口封裝用戶的身份信息。在后續(xù)的操作中,認(rèn)證后的用戶可以通過 SecurityContextHolder 獲取 Authentication 對象,并根據(jù)其中的信息獲得用戶的身份信息及相應(yīng)的權(quán)限等。

對比SecurityContext和Authentication

Authentication 是一個(gè)封裝了用戶身份認(rèn)證信息的對象,表示用戶已經(jīng)通過了驗(yàn)證。

SecurityContext 則是一個(gè)上下文類對象,用于保存和獲取當(dāng)前線程關(guān)聯(lián)的上下文信息,包括了 Authentication 對象。

4.AuthenticationManager(Interface)

定義了用戶身份驗(yàn)證的api接口(例如將用戶名和密碼和數(shù)據(jù)庫進(jìn)行比對)。可以接收一個(gè)Authentication對象作為入?yún)?,?yàn)證成功后會(huì)返回已被驗(yàn)證的Authentication對象。

5.GrantedAuthority(Interface)

授權(quán)信息以GrantedAuthority的形式存儲(chǔ)在Authentication對象中,GrantedAuthority接口表示一個(gè)授權(quán)(權(quán)限)對象,包含一個(gè)字符串類型的授權(quán)名字(authority name)。授權(quán)名字通常是一個(gè)表示權(quán)限的字符串,例如"ROLE_ADMIN"、"ROLE_USER"等

二、整理思路

  • 搭建springboot項(xiàng)目,導(dǎo)入相關(guān)依賴
  • 在數(shù)據(jù)庫導(dǎo)入sql創(chuàng)建用戶表
  • 創(chuàng)建幾個(gè)關(guān)于User的對象便于數(shù)據(jù)傳輸
  • dao層開發(fā)(對用戶信息增刪改查)
  • 實(shí)現(xiàn)UserDetails接口和UserDetailService接口
  • 自定義實(shí)現(xiàn)校驗(yàn)token的攔截器JwtAuthenticationTokenFilter
  • 自定義實(shí)現(xiàn)用戶登錄校驗(yàn)的攔截器JWTAuthenticationFilter
  • service層開發(fā)(包括PermissionService和UserService)
  • 創(chuàng)建測試Controller
  • 實(shí)現(xiàn)SpringSecurity的配置類SecurityConfig
  • 通過postman進(jìn)行測試

三、具體實(shí)現(xiàn)步驟

1.項(xiàng)目主要相關(guān)依賴

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.3.12.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.3.12.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
  </dependency>
  <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
  </dependency>
  <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.0</version>
  </dependency>
</dependencies>

2.用戶表

創(chuàng)建一個(gè)名為security_jwt_demo的數(shù)據(jù)庫,導(dǎo)入項(xiàng)目根目錄下/db/db.sql文件即可。

3.項(xiàng)目中用到的幾個(gè)user相關(guān)對象

(1)User實(shí)體

對應(yīng)數(shù)據(jù)庫中的user表

@Data
public class User {

    private Long id;
    private String username;
    private String password;
    private String permission;
    private String role;

    @Override
    public String toString() {
        return "User{" +
        "id=" + id +
        ", username='" + username + '\'' +
        ", password='" + password + '\'' +
        ", permission='" + permission + '\'' +
        ", role='" + role + '\'' +
        '}';
    }
}

(2)LoginUser

UserDetails的實(shí)現(xiàn)類,使用用戶名/密碼驗(yàn)證時(shí)需要用到其作為返回值。這個(gè)類中包含了用戶名、密碼和當(dāng)前登錄用戶所具備的權(quán)限。

@Data
public class LoginUser implements UserDetails {

    private Long id;
    private String username;
    private String password;
    //通過自定義方式進(jìn)行授權(quán)
    private Set<String> permissions = new HashSet<String>();

    //通過springSecurity進(jìn)行授權(quán)
    private Collection<? extends GrantedAuthority> authorities;

    public LoginUser(){}

    public LoginUser(User user,Collection<? extends GrantedAuthority> authorities) {
        id = user.getId();
        username = user.getUsername();
        password = user.getPassword();
        permissions.add(user.getPermission());
        this.authorities = authorities;

    }

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

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

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

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

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

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

(3)UserVO

主要用來登錄時(shí)從輸入流中獲取登錄用戶的信息,對應(yīng)了前端傳遞的參數(shù),包括用戶名、密碼、記住我等屬性。

@Data
public class UserVO {
    private String username;
    private String password;
    private Integer rememberMe;
}

4.dao層開發(fā)

創(chuàng)建mapper接口并配置對應(yīng)的mapper.xml

@Mapper
public interface UserMapper {

    //根據(jù)用戶名獲取用戶
    User getByName(String username);

    //根據(jù)用戶id獲取用戶權(quán)限
    List<String> getPermissionById(Long id);

    //新增一個(gè)用戶
    int insertUser(User user);
}

5.實(shí)現(xiàn)UserDetail接口和UserDetailService接口

首先說一下為什么要實(shí)現(xiàn)這兩個(gè)接口。

SpringSecurity提供了多種身份驗(yàn)證的方式,在這里我們使用的是用戶名/密碼的方式進(jìn)行驗(yàn)證,而如果要使用這種方式進(jìn)行驗(yàn)證的話,我們需要實(shí)現(xiàn)UserDetailService接口中的loadUserByUsername方法,這個(gè)方法用來從數(shù)據(jù)庫中進(jìn)行查詢用戶,然后和傳入的用戶密碼進(jìn)行比對。這個(gè)方法會(huì)返回一個(gè)UserDetails對象。

@Service
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.getByName(username);
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        return new LoginUser(user,authorities);
    }
}

對于UserDetailService接口,SpringSecurity提供了基于內(nèi)存和JDBC的兩種驗(yàn)證方式,默認(rèn)是JDBC的方式。我們也可以通過自定義實(shí)現(xiàn)UserDetailService接口,來達(dá)到自定義身份驗(yàn)證的結(jié)果。這里我們使用的是自定義身份驗(yàn)證的方式。

對于UserDetails,在Spring Security中,UserDetails接口是表示用戶信息的規(guī)范。該接口表示應(yīng)用程序中的用戶,并提供有關(guān)用戶的基本信息,如用戶名、密碼、角色、權(quán)限等,因此我們需要有一個(gè)類似用戶的對象來實(shí)現(xiàn)該接口(LoginUser)。

6.JwtAuthenticationTokenFilter

檢驗(yàn)用戶token的過濾器。對于客戶端發(fā)出的請求,首先對用戶的token進(jìn)行校驗(yàn),如果token不合法表示當(dāng)前用戶未登錄,繼續(xù)執(zhí)行其他過濾器的邏輯;如果token合法則設(shè)置SecurityContextHolder表示用戶已被認(rèn)證。

/**
 * token過濾器 驗(yàn)證token有效性
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    UserMapper userMapper;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String token = request.getHeader(JwtTokenUtil.TOKEN_HEADER);
        if (StringUtils.isBlank(token) || !token.startsWith(JwtTokenUtil.TOKEN_PREFIX)){
            chain.doFilter(request,response);
            return;
        }
        try {
            //如果能獲取到token則Authentication進(jìn)行設(shè)置,表示已認(rèn)證
            SecurityContextHolder.getContext().setAuthentication(getAuthentication(token));
        } catch (Exception e) {
            e.printStackTrace();
        }
        //繼續(xù)執(zhí)行其他過濾器的邏輯
        chain.doFilter(request,response);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader) throws Exception {
        String token = tokenHeader.replace(JwtTokenUtil.TOKEN_PREFIX,"");
        //判斷token是否過期
        boolean expiration = JwtTokenUtil.isExpiration(token);
        if (expiration){
            throw new Exception("過期了");
        }else{
            String username = JwtTokenUtil.getUsername(token);
            User user = userMapper.getByName(username);
            List<String> permissions = userMapper.getPermissionById(user.getId());
            LoginUser loginUser = new LoginUser(user, Collections.singleton(new SimpleGrantedAuthority(user.getRole())));
            loginUser.setPermissions(new HashSet<>(permissions));
            //新建一個(gè)UsernamePasswordAuthenticationToken用來設(shè)置Authentication
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
            return authenticationToken;
        }
    }
}

7.JWTAuthenticationFilter

用戶登錄時(shí)對用戶名密碼進(jìn)行校驗(yàn)的過濾器,在token校驗(yàn)過濾器之后執(zhí)行。在該過濾器中會(huì)對用戶名密碼進(jìn)行比對,校驗(yàn)成功后返回一個(gè)token給客戶端,下次客戶端訪問時(shí)在請求頭帶上此token代表該用戶已經(jīng)被認(rèn)證。

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private ThreadLocal<Integer> rememberMe = new ThreadLocal<>();
    private AuthenticationManager authenticationManager;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        super.setFilterProcessesUrl("/auth/login");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {

        // 從輸入流中獲取到登錄的信息
        try {
            UserVO vo = new ObjectMapper().readValue(request.getInputStream(), UserVO.class);
            rememberMe.set(vo.getRememberMe() == null ? 0 : vo.getRememberMe());
            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(vo.getUsername(), vo.getPassword(), new ArrayList<>())
            );
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    // 成功驗(yàn)證后調(diào)用的方法
    // 如果驗(yàn)證成功,就生成token并返回
    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {

        LoginUser loginUser = (LoginUser) authResult.getPrincipal();
        System.out.println("loginUser:" + loginUser.toString());
        boolean isRemember = rememberMe.get() == 1;

        String role = "";
        String token = JwtTokenUtil.createToken(loginUser.getUsername(), role, isRemember);
        /* 返回創(chuàng)建成功的token
         但是這里創(chuàng)建的token只是單純的token
         按照jwt的規(guī)定,最后請求的時(shí)候應(yīng)該是 `Bearer token`*/
        response.setHeader("token", JwtTokenUtil.TOKEN_PREFIX + token);
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        response.getWriter().write("authentication failed, reason: " + failed.getMessage());
    }
}

8.service層開發(fā)

由于業(yè)務(wù)邏輯比較簡單,我們在service層中主要實(shí)現(xiàn)自定義授權(quán)的邏輯,用戶相關(guān)的Service不做實(shí)現(xiàn)。

自定義授權(quán)的實(shí)現(xiàn)如下,首先在數(shù)據(jù)庫的user表中有個(gè)string類型的permission字段,代表用戶所擁有的權(quán)限。在進(jìn)行授權(quán)時(shí)檢查用戶權(quán)限屬性是否包含該權(quán)限,如果包含則表示當(dāng)前用戶具有訪問權(quán)限。

/**
 * 自定義權(quán)限實(shí)現(xiàn),ss取自SpringSecurity首字母
 */
@Service("ss")
public class PermissionService {
    public boolean hasPer(String permission) throws Exception {
        if (StringUtils.isBlank(permission)){
            return false;
        }
        LoginUser loginUser = SecurityUtil.getLoginUser();
        if (loginUser == null || CollectionUtils.isEmpty(loginUser.getPermissions())) {
            return false;
        }
        return loginUser.getPermissions().contains(StringUtils.trim(permission));
    }
}

9.Controller層開發(fā)

我們用到的Controller主要有兩個(gè),一個(gè)是用戶相關(guān)的,一個(gè)是進(jìn)行測試的接口。

對于我們進(jìn)行授權(quán)測試的接口,在使用自定義授權(quán)邏輯時(shí)(PermissionService),要配合@PreAuthorize注解實(shí)現(xiàn)(createJob方法),對應(yīng)的JobController如下:

@RestController
@RequestMapping("/jobs")
public class JobController {

    @GetMapping("/list")
    public String listJobs(){
        System.out.println("接收到請求...");
        return "展示所有任務(wù)";
    }

    //通過PermissionService自定義授權(quán)實(shí)現(xiàn)
    @PostMapping("/create")
    @PreAuthorize("@ss.hasPer('job:add')")
    public String createJob(){
        return "創(chuàng)建一個(gè)新任務(wù)";
    }

    //通過SpringSecurity配合用戶角色(role字段)實(shí)現(xiàn)權(quán)限管理
    @DeleteMapping("/delete")
    public String deleteJob(){
        return "刪除一個(gè)任務(wù)";
    }
}

對于用戶相關(guān)的Controller,我們只需要寫一個(gè)注冊方法就行了,如下所示:

@RestController
@RequestMapping("/")
public class UserController {

    @Autowired
    UserMapper userMapper;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @PostMapping("/register")
    public String register(@RequestBody Map<String,String> registerUser){
        User user = new User();
        user.setUsername(registerUser.get("username"));
        //對密碼進(jìn)行一下加密
        user.setPassword(bCryptPasswordEncoder.encode(registerUser.get("password")));
        user.setPermission(registerUser.get("permission"));
        user.setRole(registerUser.get("role"));
        userMapper.insertUser(user);
        return user.toString();
    }
}

為什么不需要注冊接口呢?是因?yàn)閁sernamePasswordAuthenticationFilter已經(jīng)幫我們實(shí)現(xiàn)了,默認(rèn)是"/login"

 public UsernamePasswordAuthenticationFilter() {
        super(new AntPathRequestMatcher("/login", "POST"));
 }

這里我們也可以對這個(gè)路徑進(jìn)行修改,如下所示:

public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        super.setFilterProcessesUrl("/auth/login");
    }

10.通過SecurityConfig類對SpringSecurity進(jìn)行配置

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    @Qualifier("userDetailServiceImpl")
    UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .authorizeRequests()
                // 測試用資源,需要驗(yàn)證了的用戶才能訪問
                .antMatchers("/jobs/create").authenticated()
                //只有角色為admin的用戶才能進(jìn)行刪除
                .antMatchers(HttpMethod.DELETE,"/jobs/delete").hasRole("ADMIN")
                // 其他請求都放行了
                .anyRequest().permitAll()
                .and()
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                // 不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        //將驗(yàn)證token的過濾器添加在驗(yàn)證用戶名/密碼的過濾器之前
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource(){
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }
}

到這里就全部完成了!讓我們測試一下是否生效。

11.postman測試

這是數(shù)據(jù)庫表中原有的角色和權(quán)限:

(1)測試注冊接口

可以看到是可以注冊成功的,但是我們這里使用原有user1和user2進(jìn)行權(quán)限測試(偷個(gè)懶)

(2)測試登錄接口

由于我們之前將原有的登錄接口從"/login"改為了"/auth/login",這里需要注意一下。

在這里插入圖片描述

登錄成功后的ResponseBody是空的,響應(yīng)頭中有token代表已經(jīng)登錄成功了。我們需要從header中獲取該token,后續(xù)請求需要用到。這里展示了user2,user1也是一樣的。

在這里插入圖片描述

(3)測試創(chuàng)建任務(wù)接口

由于創(chuàng)建任務(wù)需要"job:add"權(quán)限,查看數(shù)據(jù)庫user2是有該權(quán)限的,user1沒有。

將剛才登錄獲得的token添加到參數(shù)中:

然后發(fā)現(xiàn)就可以創(chuàng)建成功了

(4)測試刪除任務(wù)接口

刪除任務(wù)需要用戶角色是admin,故user2是無法進(jìn)行刪除的。

(5)我們按照剛才的流程對user1進(jìn)行測試,來達(dá)到對比的效果。

登錄:

創(chuàng)建任務(wù):

刪除任務(wù):

對于查詢接口不需要進(jìn)行認(rèn)證和授權(quán),也就是說不需要登錄就能訪問:

源碼地址:https://github.com/Rancho-7/SpringSecurity-JWT

到此這篇關(guān)于SpringSecurity角色權(quán)限控制(SpringBoot+SpringSecurity+JWT)的文章就介紹到這了,更多相關(guān)SpringSecurity角色權(quán)限內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Java經(jīng)典算法匯總之冒泡排序

    Java經(jīng)典算法匯總之冒泡排序

    冒泡排序基本思想:在要排序的一組數(shù)中,對當(dāng)前還未排好序的范圍內(nèi)的全部數(shù),自上而下對相鄰的兩個(gè)數(shù)依次進(jìn)行比較和調(diào)整,讓較大的數(shù)往下沉,較小的往上冒。即:每當(dāng)兩相鄰的數(shù)比較后發(fā)現(xiàn)它們的排序與排序要求相反時(shí),就將它們互換。
    2016-04-04
  • 詳解SpringBoot 處理異常的幾種常見姿勢

    詳解SpringBoot 處理異常的幾種常見姿勢

    這篇文章主要介紹了詳解SpringBoot 處理異常的幾種常見姿勢,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Spring?Security中如何獲取AuthenticationManager對象

    Spring?Security中如何獲取AuthenticationManager對象

    有時(shí)需要使用AuthenticationManager(以下簡稱Manager)對象,可是這個(gè)對象不是Bean,沒有直接保存在Spring的Bean庫中,那么如何獲取Spring Security中的這個(gè)對象呢,需要的朋友可以參考下
    2022-11-11
  • 關(guān)于Spring中Bean的創(chuàng)建進(jìn)行更多方面的控制

    關(guān)于Spring中Bean的創(chuàng)建進(jìn)行更多方面的控制

    今天小編就為大家分享一篇關(guān)于關(guān)于Spring中Bean的創(chuàng)建進(jìn)行更多方面的控制,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Jsoup解析HTML實(shí)例及文檔方法詳解

    Jsoup解析HTML實(shí)例及文檔方法詳解

    這篇文章主要介紹了Jsoup如何解析一個(gè)HTML文檔、從文件加載文檔、從URL加載Document等方法,對Jsoup常用方法做了詳細(xì)講解,最近提供了一個(gè)示例供大家參考 使用DOM方法來遍歷一個(gè)文檔 從元素抽取屬性,文本和HTML 獲取所有鏈接
    2013-11-11
  • SpringCloud分布式鏈路追蹤組件Sleuth配置詳解

    SpringCloud分布式鏈路追蹤組件Sleuth配置詳解

    這篇文章主要介紹了SpringCloud鏈路追蹤組件Sleuth配置方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-11-11
  • mybatis如何對大量數(shù)據(jù)的游標(biāo)查詢

    mybatis如何對大量數(shù)據(jù)的游標(biāo)查詢

    這篇文章主要介紹了mybatis如何對大量數(shù)據(jù)的游標(biāo)查詢問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java?對象深拷貝工具類的實(shí)現(xiàn)

    Java?對象深拷貝工具類的實(shí)現(xiàn)

    本文主要介紹了Java?對象深拷貝工具類的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Spring中的@Autowired注解深入解析與實(shí)戰(zhàn)指南

    Spring中的@Autowired注解深入解析與實(shí)戰(zhàn)指南

    本文介紹了Spring框架中的@Autowired注解,詳細(xì)講解了其基本用法、高級(jí)用法以及實(shí)際應(yīng)用場景,通過@Autowired注解,Spring容器可以自動(dòng)將依賴的Bean注入到目標(biāo)Bean中,從而簡化代碼并提高可維護(hù)性,需要的朋友可以參考下
    2024-11-11
  • mybatis配置Mapper.xml文件時(shí)遇到的問題及解決

    mybatis配置Mapper.xml文件時(shí)遇到的問題及解決

    這篇文章主要介紹了mybatis配置Mapper.xml文件時(shí)遇到的問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01

最新評(píng)論