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

SpringSecurity多表多端賬戶登錄的實(shí)現(xiàn)

 更新時(shí)間:2024年05月14日 09:48:43   作者:石添的編程哲學(xué)  
本文主要介紹了SpringSecurity多表多端賬戶登錄的實(shí)現(xiàn)

需求:針對公司員工,普通用戶等各類型用戶,將其分別存儲(chǔ)在不同的用戶表中,基于SpeingSecurity實(shí)現(xiàn)用戶認(rèn)證,也就是登錄功能

流程

  • 首先做數(shù)據(jù)庫設(shè)計(jì)
  • 基于SpringBoot創(chuàng)建一個(gè)項(xiàng)目
  • 項(xiàng)目中做相關(guān)的實(shí)現(xiàn)
  • 通過apifox接口測試工具進(jìn)行測試
  • 分別測試不同用戶的登錄方法,是否調(diào)用了對應(yīng)的登錄邏輯【登錄也稱為認(rèn)證】

注意:權(quán)限這塊并沒有涉及,僅僅是用戶數(shù)據(jù)這塊

數(shù)據(jù)表設(shè)計(jì)

本文先不涉及權(quán)限,表設(shè)計(jì)就是兩張用戶表

員工表

CREATE TABLE `ums_sys_user` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用戶ID',
  `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用戶賬號(hào)',
  `nickname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用戶昵稱',
  `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '用戶郵箱',
  `mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '手機(jī)號(hào)碼',
  `sex` int DEFAULT '0' COMMENT '用戶性別(0男 1女 2未知)',
  `avatar` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '頭像地址',
  `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '密碼',
  `status` int DEFAULT '0' COMMENT '帳號(hào)狀態(tài)(0正常 1停用)',
  `creator` bigint DEFAULT '1' COMMENT '創(chuàng)建者',
  `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',
  `updater` bigint DEFAULT '1' COMMENT '更新者',
  `update_time` datetime DEFAULT NULL COMMENT '更新時(shí)間',
  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '備注',
  `deleted` tinyint DEFAULT '0',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='后臺(tái)用戶表';

客戶表

CREATE TABLE `ums_site_user` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用戶ID',
  `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用戶賬號(hào)',
  `nickname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用戶昵稱',
  `openid` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '微信openid',
  `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '用戶郵箱',
  `mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '手機(jī)號(hào)碼',
  `sex` int DEFAULT '0' COMMENT '用戶性別(0男 1女 2未知)',
  `avatar` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '頭像地址',
  `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '密碼',
  `status` int DEFAULT '0' COMMENT '帳號(hào)狀態(tài)(0正常 1停用)',
  `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',
  `updater` bigint DEFAULT '1' COMMENT '更新者',
  `update_time` datetime DEFAULT NULL COMMENT '更新時(shí)間',
  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '備注',
  `deleted` tinyint DEFAULT '0',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='外部用戶表';

創(chuàng)建項(xiàng)目

登錄功能,使用非常簡單的三層架構(gòu),技術(shù)選型有:

  • SpringBoot 3.1.X
  • SpringSecurity 6.1.X
  • Mybatis Plus
  • lombok【簡化實(shí)體類】,可以通過注解生成getter、setter方法,構(gòu)造方法,toString方法等
  • maven

pom文件

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.2</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

application.yml文件配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/spring-security?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
    username: root
    password: stt123456

創(chuàng)建三層架構(gòu)

Controller

@RestController
@RequestMapping("/auth")
public class AuthController {

    private final ISysUserService sysUserService;
    private final ISiteUserService siteUserService;

    public AuthController(ISysUserService sysUserService, ISiteUserService siteUserService) {
        this.sysUserService = sysUserService;
        this.siteUserService = siteUserService;
    }

    /**
     * 后端管理系統(tǒng)登錄
     * 返回值:token
     */
    @PostMapping("sys_login")
    public String sysLogin(@RequestBody LoginParam loginParam) {

        return "后臺(tái)用戶登錄======》" +sysUserService.sysLogin(loginParam);
    }

    @PostMapping("site_login")
    public String siteLogin(@RequestBody LoginParam loginParam) {

        return "APP用戶登錄======》" + siteUserService.siteLogin(loginParam);
    }

}

SysUserServiceImpl

@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    @Qualifier("sysUserAuthenticationManager")
    private AuthenticationManager authenticationManager;

    /**
     * 登錄是SpringSecurity實(shí)現(xiàn)的,我們就是去告訴SpringSecurity現(xiàn)在要登錄
     * SpringSecirity登錄是通過 AuthticationManager 實(shí)現(xiàn)的
     * 將AuthticationManager引入到service中,調(diào)用他的認(rèn)證方法就可以了
     * @param loginParam
     * @return
     */
    @Override
    public String sysLogin(LoginParam loginParam) {
        // 通過authenticationManager 的認(rèn)證方法實(shí)現(xiàn)登錄,該方法需要傳入 Authentication 對象 就是一個(gè)認(rèn)證對象
        // Authenticationl里邊存儲(chǔ)的就是用戶的認(rèn)證信息,權(quán)限,用戶名,密碼的等信息,其實(shí)就是loadUserByUsername方法返回的UserDetails
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginParam.getUsername(), loginParam.getPassword());

        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        // 獲取用戶信息
        SysUser sysUser = (SysUser) authenticate.getPrincipal();
        log.info("sysUser==========》{}",sysUser);
        // 返回的是token
        return sysUser.getUsername();
    }
}

SiteUserServiceImpl

@Service
@Slf4j
public class SiteUserServiceImpl extends ServiceImpl<SiteUserMapper, SiteUser> implements ISiteUserService {

    /**
     * 將AuthenticationManager注入
     */
    @Autowired
    @Qualifier("siteUserAuthenticationManager")
    private AuthenticationManager authenticationManager;

    @Override
    public String siteLogin(LoginParam loginParam) {
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginParam.getMobile(), loginParam.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        // 強(qiáng)轉(zhuǎn)為用戶類型
        SiteUser siteUser = (SiteUser) authenticate.getPrincipal();
        log.info("siteUser===========>{}",siteUser);
        return siteUser.getUsername();
    }
}

實(shí)現(xiàn)login功能

項(xiàng)目中引入SpringSecurity,SpringSecurity在實(shí)現(xiàn)用戶登錄【認(rèn)證】時(shí)需要使用到兩個(gè)接口

  • UserDetailsService:是一個(gè)接口 ,提供了一個(gè)方法loadUserByUsername();
  • UserDetails:是一個(gè)接口,用來存儲(chǔ)用戶權(quán)限,狀態(tài)【是否禁用,超時(shí)等】

通過UserDetailsService查詢用戶,將用戶信息放到UserDetails中,剩下的就交給SpringSecurity的AuthenticationManager做判斷,判斷用戶是否允許登錄

分兩步走

創(chuàng)建UserDetailsService接口實(shí)現(xiàn)類

查詢用戶,分別為客戶和用后臺(tái)系統(tǒng)用戶創(chuàng)建對應(yīng)的查詢用戶的實(shí)現(xiàn)類

// 系統(tǒng)用戶的DetailsService
@Service
public class SysUserDetailsService implements UserDetailsService {

    private final SysUserMapper sysUserMapper;

    public SysUserDetailsService(SysUserMapper sysUserMapper) {
        this.sysUserMapper = sysUserMapper;
    }

    /**
     * 此方法從數(shù)據(jù)庫中查詢用戶
     * 返回一個(gè) UserDetails
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info("后臺(tái)系統(tǒng)用戶登錄=============》");
        // 根據(jù)用戶名查詢用戶
        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
        // 有權(quán)限的話,需要查詢該用戶對應(yīng)的權(quán)限
        if(sysUser == null) {
            throw new UsernameNotFoundException("用戶或密碼不正確");
        }
        return sysUser;
    }
}
// APP用戶的DetailsService
@Slf4j
public class SiteUserDetailsService implements UserDetailsService {

    private final SiteUserMapper siteUserMapper;

    public SiteUserDetailsService(SiteUserMapper siteUserMapper) {
        this.siteUserMapper = siteUserMapper;
    }

    @Override
    public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
        log.info("APP用戶登錄===================》");
        SiteUser siteUser = siteUserMapper.selectOne(new LambdaQueryWrapper<SiteUser>().eq(SiteUser::getMobile, mobile));
        if(siteUser == null) {
            throw new UsernameNotFoundException("用戶名或密碼錯(cuò)誤!");
        }
        return siteUser;
    }
}

創(chuàng)建UserDetails接口實(shí)現(xiàn)類

存儲(chǔ)用戶信息,同樣的創(chuàng)建兩個(gè)實(shí)現(xiàn)類,存儲(chǔ)不同的用戶信息,再實(shí)體類上直接修改

// 后臺(tái)管理系統(tǒng)用戶類
@TableName("ums_sys_user")
@Data
public class SysUser implements Serializable, UserDetails {

    private Long id;
    private String username;
    private String nickname;
    private String email;
    private String mobile;
    private Integer sex;
    private String avatar;
    @JsonIgnore
    private String password;
    private Integer status;
    private Long creator;
    private Long updater;
    private String remark;
    @TableLogic
    private Integer deleted;

    private LocalDateTime createTime;
    private LocalDateTime updateTime;

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

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

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

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

    @Override
    public boolean isEnabled() {
        return true;
    }
}
// APP用戶實(shí)體類
@Data
@TableName("ums_site_user")
public class SiteUser implements Serializable, UserDetails {

    private Long id;
    private String username;
    private String nickname;
    private String openid;
    private String email;
    private String mobile;
    private Integer sex;
    private String avatar;
    @JsonIgnore
    private String password;
    private Integer status;
    private Long updater;
    private String remark;
    @TableLogic
    private Integer deleted;

    private LocalDateTime createTime;
    private LocalDateTime updateTime;

    /**
     * 權(quán)限。現(xiàn)在并沒有查詢權(quán)限
     * @return
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

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

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

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

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

關(guān)聯(lián)

將SpringSecurity的AuthenticationManager 【認(rèn)證管理器,管登錄的組件】,與我們寫的登錄邏輯關(guān)聯(lián)起來【loadUserByUsername方法】,實(shí)現(xiàn)方式就是在SpringSecurity的配置類中實(shí)現(xiàn)

/**
 * 現(xiàn)在使用的是SpringSecurity 6.1.5版本,開啟SpringSecurity的自定義配置,
 * 需要使用 @EnableWebSecurity注解,而不再是繼承Adpater
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private SysUserDetailsService sysUserDetailsService;

    @Autowired
    private SiteUserDetailsService siteUserDetailsService;

    // 配置SpringSecurity的過濾器鏈
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        // 設(shè)置登錄接口放行
        http.authorizeHttpRequests(auth -> auth.requestMatchers("/auth/sys_login","/auth/site_login").permitAll().anyRequest().authenticated());
        // 關(guān)閉csrf
        http.csrf(csrf -> csrf.disable());
        return http.build();
    }


    // 配置AuthenticationManager,配置兩個(gè)。一個(gè)管理后臺(tái)用戶
    @Primary
    @Bean("sysUserAuthenticationManager")
    public AuthenticationManager sysUserAuthenticationManager(PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        // 關(guān)聯(lián)UserDetailsService
        authenticationProvider.setUserDetailsService(sysUserDetailsService);
        // 關(guān)聯(lián)密碼管理器
        authenticationProvider.setPasswordEncoder(passwordEncoder);
        return new ProviderManager(authenticationProvider);
    }


    // 配置AuthenticationManager,管理APP用戶
    @Bean("siteUserAuthenticationManager")
    public AuthenticationManager siteUserAuthenticationManager(PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        // 關(guān)聯(lián)UserDetailsService
        authenticationProvider.setUserDetailsService(siteUserDetailsService);
        // 關(guān)聯(lián)密碼管理器
        authenticationProvider.setPasswordEncoder(passwordEncoder);
        return new ProviderManager(authenticationProvider);
    }

    /**
     * 密碼管理器,會(huì)將明文密碼轉(zhuǎn)換成密文,加密,而且不能解碼
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

密碼

需要對數(shù)據(jù)庫中存儲(chǔ)的密碼進(jìn)行編碼,因?yàn)镾pringSecurity進(jìn)行密碼匹配時(shí),會(huì)對用戶輸入的密碼先編碼,再驗(yàn)證,先通過PasswordEncoder生成加密后的密碼

@SpringBootTest
public class MyTestApplication {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Test
    public void test() {
		// 密碼加密
        String encode = passwordEncoder.encode("123456");
        System.out.println(encode);

    }
}

SpringSecurity配置

創(chuàng)建兩個(gè)AuthenticationManager,一定要設(shè)置一個(gè)主AuthenticationManager否則將會(huì)報(bào)錯(cuò),即在任意一個(gè)Bean上添加@Primary注解標(biāo)記

@Primary
@Bean("sysAuthenticationManager")
public AuthenticationManager sysAuthenticationManager(PasswordEncoder passwordEncoder) {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(sysUserDetailsService);
    authenticationProvider.setPasswordEncoder(passwordEncoder);
    ProviderManager providerManager = new ProviderManager(authenticationProvider);
    providerManager.setEraseCredentialsAfterAuthentication(false);
    return providerManager;
}

/**
 * 外部用戶驗(yàn)證管理器
 * @param passwordEncoder
 * @return
 */
@Bean("siteAuthenticationManager")
public AuthenticationManager siteAuthenticationManager(PasswordEncoder passwordEncoder) {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(siteUserDetailsService);
    authenticationProvider.setPasswordEncoder(passwordEncoder);
    ProviderManager providerManager = new ProviderManager(authenticationProvider);
    providerManager.setEraseCredentialsAfterAuthentication(false);
    return providerManager;
}

數(shù)據(jù)庫配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springsecurity?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
    username: root
    password: stt123456

AuthenticationManager

AuthenticationManager用于定義SpringSecurity如何進(jìn)行身份認(rèn)證,之后將認(rèn)證信息封裝在Authentication對象上,設(shè)置到SecurityContextHolder上,AuthenticationManager常用的實(shí)現(xiàn)是ProviderManager,你也可以對其做自定義實(shí)現(xiàn)。

到此這篇關(guān)于SpringSecurity多表多端賬戶登錄的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)SpringSecurity多表多端賬戶登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中線程中斷停止的三種實(shí)現(xiàn)方法

    Java中線程中斷停止的三種實(shí)現(xiàn)方法

    本文主要介紹了Java中線程中斷停止的三種實(shí)現(xiàn)方法,包括stop()方法但已廢棄且不安全,推薦使用volatile標(biāo)志位或interrupt中斷機(jī)制,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-06-06
  • Maven生命周期和及插件原理用法詳解

    Maven生命周期和及插件原理用法詳解

    這篇文章主要介紹了Maven生命周期和及插件原理用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值的相關(guān)資料
    2020-08-08
  • 全面解析Java中的HashMap類

    全面解析Java中的HashMap類

    HashMap類為Java提供了鍵值對應(yīng)的map類型,本文將從源碼角度全面解析Java中的HashMap類,同時(shí)包括其各種常用操作方法等,歡迎參考與借鑒
    2016-05-05
  • java中Supplier、Function、BiFunction的區(qū)別及說明

    java中Supplier、Function、BiFunction的區(qū)別及說明

    Supplier、Function、BiFunction是Java函數(shù)式編程中常用的三個(gè)接口,它們分別用于無參數(shù)返回值、單參數(shù)返回值和雙參數(shù)返回值的抽象函數(shù)定義
    2026-04-04
  • SpringBoot啟動(dòng)時(shí)執(zhí)行某些操作的8種方式

    SpringBoot啟動(dòng)時(shí)執(zhí)行某些操作的8種方式

    在真實(shí)項(xiàng)目開發(fā)過程中,我們經(jīng)常會(huì)需要在程序啟動(dòng)時(shí)執(zhí)行一些特定的業(yè)務(wù)操作,比如系統(tǒng)預(yù)熱、系統(tǒng)初始化等,小編為大家介紹 8 種實(shí)現(xiàn)方式,需要的朋友可以參考下
    2025-10-10
  • Java中實(shí)現(xiàn)時(shí)間偏移(Time?Offset)處理過程

    Java中實(shí)現(xiàn)時(shí)間偏移(Time?Offset)處理過程

    本文介紹Java中時(shí)間偏移處理,利用java.time包中的ZonedDateTime、ZoneOffset等類,支持跨時(shí)區(qū)轉(zhuǎn)換、日志統(tǒng)一標(biāo)準(zhǔn),并給出最佳實(shí)踐中注意事項(xiàng)與應(yīng)用場景示例
    2025-09-09
  • 在Java中以及Spring環(huán)境下操作Redis的過程

    在Java中以及Spring環(huán)境下操作Redis的過程

    文章介紹了在Java和Spring環(huán)境下操作Redis的基本方法,在Java環(huán)境下,使用Maven創(chuàng)建項(xiàng)目并導(dǎo)入Jedis依賴,通過配置端口轉(zhuǎn)發(fā)訪問Redis,文章總結(jié)了Redis的基本命令和類別,如String、list、hash、set和zset,感興趣的朋友跟隨小編一起看看吧
    2025-03-03
  • JAVA按字節(jié)讀取文件的簡單實(shí)例

    JAVA按字節(jié)讀取文件的簡單實(shí)例

    下面小編就為大家?guī)硪黄狫AVA按字節(jié)讀取文件的簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-08-08
  • MyBatis 中 SqlMapConfig 配置文件詳解

    MyBatis 中 SqlMapConfig 配置文件詳解

    這篇文章主要介紹了MyBatis 中 SqlMapConfig 配置文件詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • java?緩沖流的概念使用方法以及實(shí)例詳解

    java?緩沖流的概念使用方法以及實(shí)例詳解

    這篇文章主要為大家介紹了java?緩沖流的概念使用方法以及實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06

最新評(píng)論

隆林| 宝兴县| 资中县| 新巴尔虎左旗| 伊通| 砀山县| 高邮市| 高雄县| 萝北县| 泗阳县| 湘乡市| 永登县| 化州市| 兰坪| 武隆县| 江油市| 正阳县| 长顺县| 怀仁县| 襄垣县| 凌源市| 安多县| 嘉义县| 手游| 黄冈市| 荔浦县| 仁化县| 革吉县| 鄱阳县| 关岭| 黑河市| 武穴市| 阳东县| 泊头市| 宁国市| 凯里市| 历史| 迭部县| 宣武区| 松溪县| 长丰县|