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

SpringSecurity集成第三方登錄過程詳解(最新推薦)

 更新時(shí)間:2024年05月13日 11:41:14   作者:小???王八  
在ThirdAuthenticationFilter 類的attemptAuthentication()方法中,我們通過authType類型,然后創(chuàng)建對(duì)應(yīng)的Authentication實(shí)現(xiàn)來實(shí)現(xiàn)不同方式的登錄,下面給大家分享SpringSecurity集成第三方登錄過程,感興趣的朋友一起看看吧

SpringSecurity 集成第三方登錄

認(rèn)證及自定義流程

首先我們提供一個(gè)實(shí)現(xiàn)了AbstractAuthenticationProcessingFilter抽象類的過濾器,用來代替UsernamePasswordAuthenticationFilter邏輯,然后提供一個(gè)AuthenticationProvider實(shí)現(xiàn)類代替AbstractUserDetailsAuthenticationProvider或DaoAuthenticationProvider,最后再提供一個(gè)UserDetailsService實(shí)現(xiàn)類。

1.驗(yàn)證碼登錄

1.通用過濾器實(shí)現(xiàn)–ThirdAuthenticationFilter

這個(gè)ThirdAuthenticationFilter過濾器我們可以仿照UsernamePasswordAuthenticationFilter來實(shí)現(xiàn)(也實(shí)現(xiàn)了AbstractAuthenticationProcessingFilter抽象類),主要是重新定義了attemptAuthentication()方法,這里需要根據(jù)“authType”參數(shù)值的類別構(gòu)建不同的AbstractAuthenticationToken,具體實(shí)現(xiàn)如下:

    //驗(yàn)證類型,比如Sms,uernamepassword等
    private String authTypeParameter = "authType";
    //對(duì)應(yīng)用戶名或手機(jī)號(hào)等
    private String principalParameter = "principal";
    //對(duì)應(yīng)密碼或驗(yàn)證碼等
    private String credentialsParameter = "credentials";
    private boolean postOnly = true;
    public ThirdAuthenticationFilter() {
        super(new AntPathRequestMatcher("/login/doLogin", "POST"));
    }
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }
        String authType = request.getParameter(authTypeParameter);
        if(StringUtils.isEmpty(authType)){
            authType = AuthTypeEnum.AUTH_TYPE_DEFAULT.getAuthType();
        }
        String principal = request.getParameter(principalParameter);
        String credentials = request.getParameter(credentialsParameter);
        AbstractAuthenticationToken authRequest = null;
        switch (authType){
            case "sms":
                authRequest = new SmsAuthenticationToken(principal, credentials);
                ((SmsAuthenticationToken)authRequest).setCode((String)request.getSession().getAttribute("code"));
                break;
            case "github":
                authRequest = new GithubAuthenticationToken(principal, credentials);
                break;
            case "default":
                authRequest = new UsernamePasswordAuthenticationToken(principal, credentials);
        }
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(authRequest);
    }
}

定義了ThirdAuthenticationSecurityConfig 配置類,我們還需要在SpringSecurity配置類中應(yīng)用才能生效,具體實(shí)現(xiàn)如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/error","/login/**","/login/goLogin","/login/doLogin","/login/code","/login/authorization_code").anonymous()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login/goLogin")
            .loginProcessingUrl("/login/doLogin")
            .failureUrl("/login/error")
            .permitAll()
            .successHandler(new QriverAuthenticationSuccessHandler("/index/toIndex"));
	//這里我們省略了一些配置 ……
	//應(yīng)用前面定義的配置
    http.apply(thirdAuthenticationSecurityConfig);
}

至此,我們定義的通用第三方過濾器就完成了,并且也完成了在SpringSecurity中生效的配置。下面我們就開始分別實(shí)現(xiàn)不同類型登錄的具體過程。

在ThirdAuthenticationFilter 類的attemptAuthentication()方法中,我們通過authType類型,然后創(chuàng)建對(duì)應(yīng)的Authentication實(shí)現(xiàn)來實(shí)現(xiàn)不同方式的登錄,這里我們主要實(shí)現(xiàn)了如下三種方式,我們分別梳理一下。

3、默認(rèn)的登錄過程

  默認(rèn)的登錄過程,即根據(jù)用戶名密碼進(jìn)行登錄,需要使用到UsernamePasswordAuthenticationToken,當(dāng)“authType”參數(shù)為"default"時(shí),這里就會(huì)創(chuàng)建UsernamePasswordAuthenticationToken對(duì)象,然后后續(xù)通過ProviderManager的authenticate()方法,最后就會(huì)調(diào)用AbstractUserDetailsAuthenticationProvider(DaoAuthenticationProvider)的 authenticate()方法,最終又會(huì)調(diào)用定義的UserDetailsService實(shí)現(xiàn)類。這是默認(rèn)的過程,這里就不再重復(fù)其中的邏輯,除了UserDetailsService實(shí)現(xiàn)類需要自己定義,其他都是SpringSecurity提供的實(shí)現(xiàn)類。

4、短信驗(yàn)證碼登錄實(shí)現(xiàn)

  短信驗(yàn)證碼登錄,是最貼近用戶名密碼登錄的一種方式,所以我們完全可以仿照用戶名密碼這種方式實(shí)現(xiàn)。我們這里先梳理一下短信驗(yàn)證碼登錄的業(yè)務(wù)邏輯:首先,登錄界面輸入手機(jī)號(hào)碼,然后再點(diǎn)擊“獲取驗(yàn)證碼”按鈕獲取短信驗(yàn)證碼,然后輸入收到的短信驗(yàn)證碼,最后點(diǎn)擊“登錄”按鈕進(jìn)行登錄認(rèn)證。和用戶名密碼登錄相比,短信驗(yàn)證碼登錄多了一個(gè)獲取驗(yàn)證碼的過程,其他其實(shí)都是一樣的,我們下面逐步實(shí)現(xiàn)短信驗(yàn)證碼登錄:

@RestController
@RequestMapping("/login")
public class SmsValidateCodeController {
	//生成驗(yàn)證碼的實(shí)例對(duì)象
    @Autowired
    private ValidateCodeGenerator smsCodeGenerator;
    //調(diào)用服務(wù)商接口,發(fā)送短信驗(yàn)證碼的實(shí)例對(duì)象
    @Autowired
    private DefaultSmsCodeSender defaultSmsCodeSender;
    @RequestMapping("/code")
    public String createSmsCode(HttpServletRequest request, HttpServletResponse response) throws ServletRequestBindingException {
        ValidateCode smsCode = smsCodeGenerator.generate(new ServletWebRequest(request));
        String mobile = (String)request.getParameter("principal");
        request.getSession().setAttribute("code",smsCode.getCode());
        defaultSmsCodeSender.send(mobile, smsCode.getCode());
        System.out.println("驗(yàn)證碼:" + smsCode.getCode());
        return "驗(yàn)證碼發(fā)送成功!";
    }
}

在上述方法中,我們注入了smsCodeGenerator和defaultSmsCodeSender兩個(gè)實(shí)例對(duì)象,分別用來生成驗(yàn)證碼和發(fā)送短信驗(yàn)證碼,這個(gè)可以根據(jù)項(xiàng)目的實(shí)際情況進(jìn)行定義和實(shí)現(xiàn),這里不再貼出其中的實(shí)現(xiàn)。同時(shí)在createSmsCode()方法中,還有一點(diǎn)需要注意的就是,我們發(fā)出去的短信驗(yàn)證碼需要進(jìn)行保存,方便后續(xù)登錄時(shí)進(jìn)行驗(yàn)證,這個(gè)也可以選擇很多方法,比如說會(huì)話、數(shù)據(jù)庫(kù)、緩存等,我這里為了簡(jiǎn)單,直接存到了session會(huì)話中了。

然后,我們前面定義ThirdAuthenticationFilter過濾器時(shí),根據(jù)登錄方式不同,需要對(duì)應(yīng)的Authentication對(duì)象,這里我們還需要?jiǎng)?chuàng)建短信驗(yàn)證登錄需要的Authentication類,這里我們可以仿照UsernamePasswordAuthenticationToken類進(jìn)行編寫,實(shí)現(xiàn)如下

public class SmsAuthenticationToken  extends AbstractAuthenticationToken {
    //對(duì)應(yīng)手機(jī)號(hào)碼
    private final Object principal;
    //對(duì)應(yīng)手機(jī)驗(yàn)證碼
    private Object credentials;
    //后臺(tái)存儲(chǔ)的短信驗(yàn)證碼,用于驗(yàn)證前端傳過來的是否正確
    private String code;
    public SmsAuthenticationToken(String mobile, Object credentials){
        super(null);
        this.principal = mobile;
        this.credentials = credentials;
        this.code = code;
        setAuthenticated(false);
    }
    public SmsAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities, Object credentials){
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }
    @Override
    public Object getCredentials() {
        return this.credentials;
    }
    @Override
    public Object getPrincipal() {
        return this.principal;
    }
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        if (isAuthenticated) {
            throw new IllegalArgumentException(
                    "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        }
        super.setAuthenticated(false);
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    @Override
    public void eraseCredentials() {
        super.eraseCredentials();
        credentials = null;
    }
}

在SmsAuthenticationToken 類中,我們?cè)黾恿艘粋€(gè)code屬性,其實(shí)該屬性不是必須的,我這里是為了方便傳遞存儲(chǔ)在session會(huì)話中的驗(yàn)證碼而添加的,如果使用緩存或數(shù)據(jù)庫(kù)進(jìn)行存儲(chǔ)驗(yàn)證碼,該屬性就可以省略。

在AuthenticationManager的authenticate()方法中,會(huì)根據(jù)Authentication類型選擇AuthenticationProvider對(duì)象,所以我們這里自定義短信驗(yàn)證碼需要的AuthenticationProvider對(duì)象,實(shí)現(xiàn)如下:

@Component
public class SmsAuthenticationProvider implements AuthenticationProvider{
    @Autowired
    @Qualifier("smsUserDetailsService")
    private UserDetailsService userDetailsService;
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        SmsAuthenticationToken token = (SmsAuthenticationToken) authentication;
        String mobile = (String)token.getPrincipal();
        //首先,驗(yàn)證驗(yàn)證碼是否正確
        String code = (String)token.getCredentials();
        String sCode = token.getCode();
        if(StringUtils.isEmpty(code) || !code.equalsIgnoreCase(sCode)){
            throw new BadCredentialsException("手機(jī)驗(yàn)證碼錯(cuò)誤(Bad credentials),請(qǐng)重試!");
        }
        //然后,查詢對(duì)應(yīng)用戶
        UserDetails user = userDetailsService.loadUserByUsername(mobile);
        if (Objects.isNull(user)) {
            throw new InternalAuthenticationServiceException("根據(jù)手機(jī)號(hào):" + mobile + ",無(wú)法獲取對(duì)應(yīng)的用戶信息!");
        }
        SmsAuthenticationToken authenticationResult = new SmsAuthenticationToken(user.getUsername(), user.getAuthorities(), token.getCredentials());
        authenticationResult.setDetails(token.getDetails());
        return authenticationResult;
    }
    @Override
    public boolean supports(Class<?> authentication) {
        return SmsAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

在SmsAuthenticationProvider 中,supports()方法決定了該實(shí)例對(duì)象僅支持SmsAuthenticationToken對(duì)象的驗(yàn)證。同時(shí),根據(jù)authenticate()方法傳遞參數(shù)authentication對(duì)象(包括了登錄信息:手機(jī)號(hào)和驗(yàn)證碼,session存儲(chǔ)的驗(yàn)證碼),我們這里session存儲(chǔ)的驗(yàn)證碼,是因?yàn)槲覀儾捎昧藭?huì)話存儲(chǔ)的方式,如果使用數(shù)據(jù)庫(kù),我們這里就可以通過手機(jī)號(hào),去數(shù)據(jù)庫(kù)或緩存查詢對(duì)應(yīng)的驗(yàn)證碼,然后和authentication對(duì)象傳遞過來的驗(yàn)證碼進(jìn)行比對(duì),驗(yàn)證成功,說明登錄認(rèn)證成功,否則登錄認(rèn)證失敗。登錄成功后,我們就可以調(diào)用userDetailsService對(duì)象的loadUserByUsername()方法獲取登錄用戶的其他相關(guān)信息(權(quán)限等),具體實(shí)現(xiàn)在自定義的SmsUserDetailsService類中實(shí)現(xiàn),具體如下:

@Component("smsUserDetailsService")
public class SmsUserDetailsService implements UserDetailsService {
    private Logger logger = LoggerFactory.getLogger(SmsUserDetailsService.class);
    @Autowired
    private SysUserService sysUserService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //1、查詢用戶信息
        SysUser user = new SysUser();
        user.setMobile(username);
        SysUser qUser = sysUserService.getOne(new QueryWrapper<>(user),true);
        if(qUser == null) {
            logger.info("手機(jī)號(hào)為”" + username + "“的用戶不存在!?。?);
            throw new UsernameNotFoundException("手機(jī)號(hào)為”" + username + "“的用戶不存在?。?!");
        }
        //2、封裝用戶角色
        UserRole userRole = sysUserService.getRoleByUserId(qUser.getId());
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(String.valueOf(userRole.getRoleId())));
        return new LoginUser(qUser.getUsername(), qUser.getPassword(),authorities);
    } 
}

2.GitHub登錄

和短信驗(yàn)證碼登錄認(rèn)證相比,Github登錄又會(huì)有自己的特殊性,我們這里先梳理一下基于Github進(jìn)行登錄驗(yàn)證的大致邏輯:首先,點(diǎn)擊Github登錄認(rèn)證按鈕,然后會(huì)跳轉(zhuǎn)到github登錄界面,輸入github系統(tǒng)的用戶名密碼,登錄成功,就會(huì)跳轉(zhuǎn)到我們自己的系統(tǒng)中的首頁(yè)。和基于用戶名密碼的登錄方式相比,Github登錄不需要類似用戶名和密碼這樣的輸入(在自己的系統(tǒng)中),同時(shí)又需要根據(jù)獲取到的github用戶信息,換取在自己系統(tǒng)對(duì)應(yīng)的用戶信息。具體實(shí)現(xiàn)步驟如下:

在github的配置省略

@Controller
@RequestMapping("/login")
public class GithubValidateController {
    @Autowired
    private GithubClientService githubClientService;
    @RequestMapping("/authorization_code")
    public void authorization_code(HttpServletRequest request, HttpServletResponse response, String code) throws ServletRequestBindingException, IOException {
        //github登錄驗(yàn)證,并獲取access_token
        Map<String,String> resp = githubClientService.queryAccessToken(code);
        //跳轉(zhuǎn)本系統(tǒng)的登錄流程,獲取用戶信息,實(shí)現(xiàn)兩個(gè)系統(tǒng)用戶的對(duì)接
        String url = "http://localhost:8888/qriver-admin/login/doLogin";
        this.sendByPost(response, url,resp.get("access_token"),"github");
        //this.sendByPost(response, url,"access_token","github");
    }
    public void sendByPost(HttpServletResponse response,String url, String principal, String authType) throws IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println(" <HEAD><TITLE>Post 方法</TITLE></HEAD>");
        out.println(" <BODY>");
        out.println("<form name=\"submitForm\" action=\"" + url + "\" method=\"post\">");
        out.println("<input type=\"hidden\" name=\"principal\" value=\"" + principal + "\"/>");
        out.println("<input type=\"hidden\" name=\"authType\" value=\"" + authType + "\"/>");
        out.println("</from>");
        out.println("<script>window.document.submitForm.submit();</script> ");
        out.println(" </BODY>");
        out.println("</HTML>");
        out.flush();
        out.close();
    }
}

“/login/authorization_code”接口對(duì)應(yīng)了我們?cè)贕ithub中配置的回調(diào)函數(shù),即在Github登錄驗(yàn)證成功后,就會(huì)回調(diào)該接口,我們就是就在回調(diào)方法中,模擬了用戶名密碼登錄的方式,調(diào)用了SpringSecurity登錄認(rèn)證需要的“/login/doLogin”接口。這里,我們通過queryAccessToken()方法根據(jù)回調(diào)傳遞的code獲取對(duì)應(yīng)的accessToken,然后把a(bǔ)ccessToken作為登錄使用的principal 參數(shù)值,之而立不需要傳遞密碼,因?yàn)槲覀兘?jīng)過Github授權(quán),就可以認(rèn)為完成了登錄認(rèn)證的判斷過程了。

其中GithubClientService類,提供了獲取accessToken和用戶信息的兩個(gè)方法,具體實(shí)現(xiàn)方式如下:

@Service
public class GithubClientService {
	//前面在github中配置時(shí)產(chǎn)生的
    private String clientId = "######";
    private String clientSecret = "######";
    private String state = "123";
    private String redirectUri = "http://localhost:8888/qriver-admin/login/authorization_code";
    @Autowired
    private RestTemplate restTemplate;
    @Nullable
    private WebApplicationContext webApplicationContext;
	//獲取accessToken
    public Map<String, String> queryAccessToken(String code ){
        Map<String, String> map = new HashMap<>();
        map.put("client_id", clientId);
        map.put("client_secret", clientSecret);
        map.put("state", state);
        map.put("code", code);
        map.put("redirect_uri", redirectUri);
        Map<String,String> resp = restTemplate.postForObject("https://github.com/login/oauth/access_token", map, Map.class);
        return resp;
    }
	//獲取用戶信息
    public Map<String, Object> queryUser(String accessToken){
        HttpHeaders httpheaders = new HttpHeaders();
        httpheaders.add("Authorization", "token " + accessToken);
        HttpEntity<?> httpEntity = new HttpEntity<>(httpheaders);
        ResponseEntity<Map> exchange = restTemplate.exchange("https://api.github.com/user", HttpMethod.GET, httpEntity, Map.class);
        System.out.println("exchange.getBody() = " + exchange.getBody());
        return exchange == null ? null : exchange.getBody();
    }
}

其實(shí),完成了上述的配置和方式后,后續(xù)的方式就和短信驗(yàn)證碼的邏輯一樣了,這里我們簡(jiǎn)要的再梳理一下。

首先,我們也需要定義一個(gè)基于Github登錄需要的Authentication實(shí)現(xiàn)類,具體實(shí)現(xiàn)和前面的SmsAuthenticationToken類似,這里不再重復(fù)貼代碼了。

然后,我們?cè)俣x一個(gè)AuthenticationProvider實(shí)現(xiàn)類GithubAuthenticationProvider,具體實(shí)現(xiàn)如下:

@Component
public class GithubAuthenticationProvider implements AuthenticationProvider{
    @Autowired
    @Qualifier("githubUserDetailsService")
    private UserDetailsService userDetailsService;
    @Autowired
    private GithubClientService githubClientService;
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        GithubAuthenticationToken token = (GithubAuthenticationToken) authentication;
        String accessToken = (String)token.getPrincipal();
        //根據(jù)accessToken 獲取github用戶信息
        Map<String, Object> userInfo = githubClientService.queryUser(accessToken);
        //然后,根據(jù)github用戶,查詢對(duì)應(yīng)系統(tǒng)用戶信息
        UserDetails user = userDetailsService.loadUserByUsername((String)userInfo.get("login"));
        if (Objects.isNull(user)) {
            throw new InternalAuthenticationServiceException("根據(jù)accessToken:" + accessToken + ",無(wú)法獲取對(duì)應(yīng)的用戶信息!");
        }
        GithubAuthenticationToken authenticationResult = new GithubAuthenticationToken(user.getUsername(), user.getAuthorities(), token.getCredentials());
        authenticationResult.setDetails(token.getDetails());
        return authenticationResult;
    }
    @Override
    public boolean supports(Class<?> authentication) {
        return GithubAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

在GithubAuthenticationProvider 類的authenticate()方法中,參數(shù)authentication中對(duì)應(yīng)的是Github授權(quán)后傳遞的accessToken值,我們這里需要根據(jù)accessToken值換取Github用戶信息,這里通過queryUser()方法實(shí)現(xiàn),然后根據(jù)github用戶名去獲取對(duì)應(yīng)的系統(tǒng)用戶信息。如果根據(jù)github用戶名用戶獲取的系統(tǒng)用戶為空,我們可以根據(jù)自己的需求,自動(dòng)生成一個(gè)用戶或者跳轉(zhuǎn)到注冊(cè)頁(yè)面,讓用戶注冊(cè)一個(gè)頁(yè)面,這里為了簡(jiǎn)單,我們直接拋出了一個(gè)異常。

關(guān)于自定義UserDetailsService實(shí)現(xiàn)類,主要需要實(shí)現(xiàn)根據(jù)github用戶名查詢對(duì)應(yīng)系統(tǒng)用戶的功能

當(dāng)認(rèn)證完成后要返回token可以實(shí)現(xiàn)AuthenticationSuccessHandler

import org.springframework.security.core.Authentication;  
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import java.io.IOException;  
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {  
    private final JwtTokenProvider jwtTokenProvider; // 假設(shè)你有一個(gè)JwtTokenProvider類來生成JWT  
    public CustomAuthenticationSuccessHandler(JwtTokenProvider jwtTokenProvider) {  
        this.jwtTokenProvider = jwtTokenProvider;  
    }  
    @Override  
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {  
        // 生成JWT  
        String token = jwtTokenProvider.generateToken(authentication);  
        // 將JWT添加到響應(yīng)頭中  
        response.setHeader("Authorization", "Bearer " + token);  
        // 或者將JWT添加到響應(yīng)體中(取決于你的API設(shè)計(jì))  
        // response.getWriter().write(token);  
        response.setStatus(HttpServletResponse.SC_OK);  
    }  
}

并在securityconfig中設(shè)置

到此這篇關(guān)于SpringSecurity集成第三方登錄的文章就介紹到這了,更多相關(guān)SpringSecurity登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用JMeter從JSON響應(yīng)的URL參數(shù)中提取特定值

    使用JMeter從JSON響應(yīng)的URL參數(shù)中提取特定值

    在使用Apache JMeter進(jìn)行API測(cè)試時(shí),我們經(jīng)常需要從JSON格式的響應(yīng)中提取特定字段的值,這可以通過使用JMeter內(nèi)置的JSON提取器和正則表達(dá)式提取器來完成,本文介紹JMeter JSON提取特定值的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Netty結(jié)合Protobuf進(jìn)行編解碼的方法

    Netty結(jié)合Protobuf進(jìn)行編解碼的方法

    這篇文章主要介紹了Netty結(jié)合Protobuf進(jìn)行編解碼,通過文檔表述和代碼實(shí)例充分說明了如何進(jìn)行使用和操作,需要的朋友可以參考下
    2021-06-06
  • Java 操作Properties配置文件詳解

    Java 操作Properties配置文件詳解

    這篇文章主要介紹了Java 操作Properties配置文件詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • SpringCloud Eureka實(shí)現(xiàn)服務(wù)注冊(cè)與發(fā)現(xiàn)

    SpringCloud Eureka實(shí)現(xiàn)服務(wù)注冊(cè)與發(fā)現(xiàn)

    Eureka是一種基于REST(具像狀態(tài)傳輸)的服務(wù),主要用于AWS云中定位服務(wù),以實(shí)現(xiàn)中間層服務(wù)器的負(fù)載平衡和故障轉(zhuǎn)移。本文記錄一個(gè)簡(jiǎn)單的服務(wù)注冊(cè)與發(fā)現(xiàn)實(shí)例。感興趣的小伙伴們可以參考一下
    2019-01-01
  • SpringBoot搭建Dubbo項(xiàng)目實(shí)現(xiàn)斐波那契第n項(xiàng)詳解

    SpringBoot搭建Dubbo項(xiàng)目實(shí)現(xiàn)斐波那契第n項(xiàng)詳解

    這篇文章主要講解了“SpringBoot+Dubbo怎么實(shí)現(xiàn)斐波那契第N項(xiàng)”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)吧
    2022-06-06
  • java語(yǔ)言與平臺(tái)基礎(chǔ)知識(shí)點(diǎn)

    java語(yǔ)言與平臺(tái)基礎(chǔ)知識(shí)點(diǎn)

    在本篇文章里小編給大家整理的是一篇關(guān)于java語(yǔ)言與平臺(tái)基礎(chǔ)知識(shí)點(diǎn)內(nèi)容,有需要的朋友們跟著學(xué)習(xí)下。
    2019-11-11
  • java發(fā)送HttpClient請(qǐng)求及接收請(qǐng)求結(jié)果過程的簡(jiǎn)單實(shí)例

    java發(fā)送HttpClient請(qǐng)求及接收請(qǐng)求結(jié)果過程的簡(jiǎn)單實(shí)例

    下面小編就為大家?guī)硪黄猨ava發(fā)送HttpClient請(qǐng)求及接收請(qǐng)求結(jié)果過程的簡(jiǎn)單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-11-11
  • Java中對(duì)象的克隆詳解

    Java中對(duì)象的克隆詳解

    這篇文章主要介紹了Java中對(duì)象的克隆詳解,Java中對(duì)象的復(fù)制分為淺復(fù)制與深復(fù)制的不同之處就在于深復(fù)制還會(huì)復(fù)制對(duì)象的引用對(duì)象,需要的朋友可以參考下
    2023-08-08
  • Java使用JDK與Cglib動(dòng)態(tài)代理技術(shù)統(tǒng)一管理日志記錄

    Java使用JDK與Cglib動(dòng)態(tài)代理技術(shù)統(tǒng)一管理日志記錄

    這篇文章主要介紹了Java使用JDK與Cglib動(dòng)態(tài)代理技術(shù)統(tǒng)一管理日志記錄,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • java編程是做什么的

    java編程是做什么的

    在本篇文章里小編給大家整理的是一篇關(guān)于java編程是什么相關(guān)的基礎(chǔ)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友們可以閱讀下。
    2021-01-01

最新評(píng)論