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

SpringSecurity HttpSecurity 類處理流程分析

 更新時間:2024年09月12日 12:12:39   作者:liang8999  
SpringSecurity在SSM項目中使用基于配置文件,通過XML標(biāo)簽定義認(rèn)證信息,HttpSecurity在SpringBoot中通過代碼配置實現(xiàn)與XML相同功能,詳細(xì)介紹了HttpSecurity的類結(jié)構(gòu)、處理過程及其與SecurityBuilder的關(guān)系,感興趣的朋友一起看看吧

1、SpringSecurity 在spring boot中與SSM項目中基于配置文件的區(qū)別

      通過前邊的筆記我們可以知道,在傳統(tǒng)的SSM項目中 SpringSecurity的使用是基于配置文件的,然后spring 容器初始化的時候?qū)?nbsp;SpringSecurity 中的各種標(biāo)簽解析成對應(yīng)的Bean對象,

      SpringSecurity 配置文件如下所示:

<!-- SpringSecurity配置文件 -->
        <!--
             auto-config:表示自動加載SpringSecurity的配置文件
             use-expressions:表示使用Spring的EL表達式
         -->
        <security:http auto-config="true" use-expressions="true">
            <!--定義匿名訪問,跳轉(zhuǎn)到登錄頁面 -->
            <security:intercept-url pattern="/login.jsp" access="permitAll()"/>
            <!--
                攔截資源
                pattern="/**" 攔截所有的資源
                access="hasAnyRole('ROLE_USER')" 表示只有ROLE_USER 這個角色可以訪問資源
             -->
            <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER')" ></security:intercept-url>
            <!--
                配置認(rèn)證(用戶登錄)信息,覆蓋security 默認(rèn)的登錄頁面
                 login-page:登錄頁面地址
                 login-processing-url:登錄的請求url
                 default-target-url:登錄成功皇后的目標(biāo)地址
                 authentication-failure-url:登錄校驗失敗后的地址
             -->
            <security:form-login login-page="/login.jsp" login-processing-url="/login" default-target-url="/home.jsp" authentication-failure-url="/error.jsp"/>
            <!--開啟csrf校驗 -->
            <security:csrf disabled="true"/>
            <!--
                開啟“記住我” 登錄用戶緩存功能,該功能默認(rèn)是關(guān)閉的,需要手動開啟
                remember-me-parameter 是登錄頁面配置的 “記住我” 功能的屬性名稱,如login.jsp 中的 "remember-me"
                token-validity-seconds 設(shè)置 “記住我” 登錄的數(shù)據(jù)保存的超時時間,
                注意:當(dāng)前 這種配置只是把“登錄數(shù)據(jù)” 臨時保存在頁面的Cookie(token) 中,保存在頁面中的數(shù)據(jù)安全性很差,很容故意被盜??;
                     為了解決這個問題 spring security提供了把“記住我” 功能的數(shù)據(jù)保存到數(shù)據(jù)庫中,需要在 <security:remember-me>
                     中添加配置屬性 data-source-ref,并 指定數(shù)據(jù)源,如:data-source-ref="dataSource"
            -->
            <security:remember-me
                    token-validity-seconds="1200"
                    data-source-ref="dataSource"
                    remember-me-parameter="remember-me"/>
            <!--自定義錯誤頁面 -->
            <security:access-denied-handler error-page="error.jsp"/>
        </security:http>
        <!--向IOC容器注入一個bean-->
        <bean class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" id="bCryptPasswordEncoder"/>
        <!-- 認(rèn)證用戶信息 -->
        <security:authentication-manager>
           <security:authentication-provider user-service-ref="userServiceImpl"><!--指向自己定義的認(rèn)證service,在service 中根據(jù)登錄用戶與數(shù)據(jù)庫的數(shù)據(jù)進行用戶認(rèn)證處理,這樣保密性比較好 -->
               <!--
               <security:user-service >
                  設(shè)置一個賬號 zhangsan 密碼123 {noop} 表示不加密 具有的角色是  ROLE_USER
                 <security:user name="zhangsan" authorities="ROLE_USER" password="{noop}123" ></security:user>
                 <security:user name="lisi" authorities="ROLE_USER" password="{noop}123456" ></security:user>
               </security:user-service>
            -->
               <!--引入用戶認(rèn)證密碼加密方式 -->
               <security:password-encoder ref="bCryptPasswordEncoder"></security:password-encoder>
           </security:authentication-provider>
        </security:authentication-manager>

      也就是在配置文件中通過 security:http 等標(biāo)簽來定義了認(rèn)證需要的相關(guān)信息,但是在

      SpringBoot項目中,我們慢慢脫離了xml配置文件的方式,通過配置類的方式來配置

      SpringSecurity。SpringSecurity配置類需要繼承類 WebSecurityConfigurerAdapter,并重寫

      configure(AuthenticationManagerBuilder auth) 和 configure(HttpSecurity http) 方法;

       SpringSecurity 配置類如下所示:     

/**
 * SpringSecurity的配置文件
 * WebSecurityCofniguration中 @Bean注解 把 FilterChainProxy 注入到了容器中 而且名稱為springSecurityFilterChain
 * 而 FilterChainProxy 對象是通過 WebSecurity 構(gòu)建的
 *
 * @EnableWebSecurity
 */
@Configuration
@EnableWebSecurity
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @Autowired
    private PersistentTokenRepository persistentTokenRepository;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService)// 數(shù)據(jù)庫認(rèn)證,綁定需要執(zhí)行用戶認(rèn)證操作的service
            .passwordEncoder(bCryptPasswordEncoder); // 設(shè)置加密處理的方式
        //auth.inMemoryAuthentication().withUser("root").password("123")
    }
    /**
     * 容器中注入 BCryptPasswordEncoder
     * @return
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
    /**
     * HttpSecurity 相當(dāng)于 SpringSecurity配置文件中 http 標(biāo)簽
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //匿名訪問資源
                .antMatchers("/login.html","/css/**","/img/**")
                // 配置需要放過的資源,表示前邊 antMatchers 配置的資源都需要放過
                .permitAll()
                .antMatchers("/**")
                //認(rèn)證的資源及所具備的權(quán)限
                .hasAnyRole("USER")
                .anyRequest()//表示所有請求都需要認(rèn)證
                .authenticated()//需要認(rèn)證
                //and() 返回一個HttpSecurity
                .and()
                // 配置登錄表單相關(guān)的信息
                .formLogin()
                // 指定自定義的登錄頁面
                //todo 注意:
                //      對于前后端分離的項目,不需要指定跳轉(zhuǎn)的頁面,只需要 loginProcessingUrl
                //      設(shè)置請求資源url就行了
                .loginPage("/login.html") //認(rèn)證表單相關(guān)信息
                .loginProcessingUrl("/login") // 表單提交的登錄地址
                .defaultSuccessUrl("/home.html")
                //表示上邊與form表單提交得資源都要放過
                .permitAll()
                .and()
                .rememberMe() // 放開 記住我 的功能
                .tokenRepository(persistentTokenRepository) // 持久化
                .and()
                //csrf設(shè)置
                .csrf()
                .disable();
        HttpSecurity http1 = http.authorizeRequests()
                // 配置需要放過的資源
                .antMatchers("/login.html", "/css/**", "/img/**")
                .permitAll()//表示放過前邊 antMatchers 配置得資源
                .antMatchers("/**")
                .hasAnyRole("USER")
                .anyRequest()
                .authenticated()
                .and();
    }
    /**
     * 向Spring容器中注入 PersistentTokenRepository 對象
     * @param dataSource
     * @return
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository(DataSource dataSource){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        //綁定數(shù)據(jù)源
        tokenRepository.setDataSource(dataSource);
        return tokenRepository;
    }
    public static void main(String[] args) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String password = "admin";
        // 每次都會生成一個隨機的salt,同一個明文加密多次編碼得到的密文其實都不一樣
        System.out.println(encoder.encode(password));
        System.out.println(encoder.encode(password));
        System.out.println(encoder.encode(password));
    }
}

       在SpringSecurity中提供了HttpSecurity等工具類,這里HttpSecurity就等同于我們在配置

      文件中定義的<security:http>標(biāo)簽,而。

      通過代碼結(jié)果來看和配置文件的效果是一樣的?;谂渲梦募姆绞轿覀冎胺治鲞^,是通過

     標(biāo)簽對應(yīng)的handler來解析處理的,那么HttpSecurity這塊是如何處理的呢?

2、HttpSecurity 類的處理過程

2.1、HttpSecurity 類圖:

         

         由該類圖可以清晰得發(fā)現(xiàn),HttpSecurity 繼承了父類 AbstractConfiguredSecurityBuilder

         并實現(xiàn)了接口 SecurityBuilder 和 HttpSecurityBuilder

         HttpSecurity 類的定義如下:               

2.2、SecurityBuilder 接口

         SecurityBuilder 定義如下:

public interface SecurityBuilder<O> {
    //構(gòu)建 SecurityBuilder 指定泛型類型的對象
    O build() throws Exception;
}

         由接口 SecurityBuilder 的定義可以發(fā)現(xiàn),SecurityBuilder 接口只提供了一個 build() 方法,用

         來構(gòu)建 SecurityBuilder 泛型指定類型的bean對象。

         結(jié)合 HttpSecurity 類中實現(xiàn) SecurityBuilder 接口時的泛型是什么,就知道在 HttpSecurity 類

         中 SecurityBuilder 是用來創(chuàng)建什么對象,HttpSecurity 定義如下:                 

          由 HttpSecurity 的定義可以發(fā)現(xiàn),在 HttpSecurity 類中 SecurityBuilder 指定的泛型是

          DefaultSecurityFilterChain,DefaultSecurityFilterChain 是攔截器鏈SecurityFilterChain

          一個默認(rèn)實現(xiàn),所以 DefaultSecurityFilterChain 是一個攔截器鏈,所以在 HttpSecurity

          中,SecurityBuilder 是用來創(chuàng)建攔截器鏈的。

2.2.1、SecurityBuilder.build() 方法的實現(xiàn)

            下面看下 SecurityBuilder.build() 的實現(xiàn)過程,及連接器鏈的創(chuàng)建過程

             SecurityBuilder 的默認(rèn)實現(xiàn)是類 AbstractSecurityBuilder

             SecurityBuilder.build() 方法的實現(xiàn)如下:

public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
    //CAS類型
    private AtomicBoolean building = new AtomicBoolean();
    //返回創(chuàng)建的O的對象
    private O object;
    public AbstractSecurityBuilder() {
    }
    //創(chuàng)建泛型O的對象
    public final O build() throws Exception {
        //基于CAS,保證在整個環(huán)境中O只被創(chuàng)建一次
        if (this.building.compareAndSet(false, true)) {
            //真正創(chuàng)建泛型O的對象
            this.object = this.doBuild();
            return this.object;
        } else {
            throw new AlreadyBuiltException("This object has already been built");
        }
    }
    //返回O的對象
    public final O getObject() {
        if (!this.building.get()) {
            throw new IllegalStateException("This object has not been built");
        } else {
            return this.object;
        }
    }
    //抽象方法,由子類實現(xiàn)
    protected abstract O doBuild() throws Exception;
}

             由 AbstractSecurityBuilder 的定義可以發(fā)現(xiàn),真正創(chuàng)建泛型O(在 HttpSecurity 中O是

             攔截器鏈 DefaultSecurityFilterChain )的對象是在doBuild 發(fā)給發(fā)中完成,而doBuild是

             一個抽象方法,由子類 AbstractConfiguredSecurityBuilder 實現(xiàn),

             doBuild 方法實現(xiàn)如下:

protected final O doBuild() throws Exception {
        synchronized(this.configurers) {
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.INITIALIZING;
            this.beforeInit();
            //執(zhí)行當(dāng)前類的init方法進行初始化操作
            this.init();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.CONFIGURING;
            this.beforeConfigure();
            this.configure();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILDING;
            //獲取構(gòu)建的對象,上面的方法可以先忽略
            O result = this.performBuild();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILT;
            return result;
        }
    }

             performBuild() 是一個抽象方法,由AuthenticationManagerBuilder、HttpSecurity、

             WebSecurity 三個子類實現(xiàn),在這里我們應(yīng)該看 HttpSecurity 中的實現(xiàn)

             HttpSecurity.performBuild() 方法的實現(xiàn)如下:        

@Override
	protected DefaultSecurityFilterChain performBuild() {
        //filters:保存所有的過濾器
        // 對所有的過濾器做排序
		this.filters.sort(OrderComparator.INSTANCE);
		List<Filter> sortedFilters = new ArrayList<>(this.filters.size());
		for (Filter filter : this.filters) {
			sortedFilters.add(((OrderedFilter) filter).filter);
		}
		// 然后生成 DefaultSecurityFilterChain
		return new DefaultSecurityFilterChain(this.requestMatcher, sortedFilters);
	}

             DefaultSecurityFilterChain 構(gòu)造方法如下:

public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
        if (!filters.isEmpty()) {
            logger.info(LogMessage.format("Will not secure %s", requestMatcher));
        } else {
            logger.info(LogMessage.format("Will secure %s with %s", requestMatcher, filters));
        }
        //綁定請求匹配規(guī)則
        this.requestMatcher = requestMatcher;
        //綁定過濾器集合
        this.filters = new ArrayList(filters);
    }

             在HttpSecurity構(gòu)造方法中綁定了對應(yīng)的請求匹配器和過濾器集合。                   

             對應(yīng)的請求匹配器則是 AnyRequestMatcher 匹配所有的請求。當(dāng)然我們會比較關(guān)心

            默認(rèn)的過濾器鏈中的過濾器是哪來的,這塊兒我們繼續(xù)來分析

2.3、AbstractConfiguredSecurityBuilder

        AbstractConfiguredSecurityBuilder 是一個抽象類,也可以看成是 SecurityBuilder 接口的

        實現(xiàn),AbstractConfiguredSecurityBuilder 類圖如下所示:               

類型功能
SecurityBuilder聲明了build方法
AbstractSecurityBuilder提供了獲取對象的方法以及控制一個對象只能build一次
AbstractConfiguredSecurityBuilder除了提供對對象細(xì)粒度的控制外還擴展了對configurer的操作

       AbstractConfiguredSecurityBuilder 對應(yīng)的三個實現(xiàn)類,如下所示:   

2.3.1、BuildState

            AbstractConfiguredSecurityBuilder 中定義了一個枚舉類BuildState,將整個構(gòu)建過程

            分為 5 種狀態(tài),也可 以理解為構(gòu)建過程生命周期的五個階段,通過這些階段來管理需

           要構(gòu)建的對象的不同階段 如下:   

          private enum BuildState {
		/**
		 * 還沒開始構(gòu)建
		 */
		UNBUILT(0),
		/**
		 * 構(gòu)建中
		 */
		INITIALIZING(1),
		/**
		 * 配置中
		 */
		CONFIGURING(2),
		/**
		 * 構(gòu)建中
		 */
		BUILDING(3),
		/**
		 * 構(gòu)建完成
		 */
		BUILT(4);
		private final int order;
		BuildState(int order) {
			this.order = order;
		}
		public boolean isInitializing() {
			return INITIALIZING.order == this.order;
		}
		/**
		 * Determines if the state is CONFIGURING or later
		 * @return
		 */
		public boolean isConfigured() {
			return this.order >= CONFIGURING.order;
		}
	}

2.3.2、AbstractConfiguredSecurityBuilder 常見方法

2.3.2.1、add() 方法

              add 方法,這相當(dāng)于是在收集所有的配置類。將所有的 xxxConfigure 收集起來存儲到

             configurers 中,將來再統(tǒng)一初始化并配置,configurers 本身是一個 LinkedHashMap ,

             key 是配置類的 class, value 是一個集合,集合里邊放著 xxxConfigure 配置類。當(dāng)

             需要對這些配置類進行集中配置的時候, 會通過 getConfigurers 方法獲取配置類,

              這個獲取過程就是把 LinkedHashMap 中的 value 拿出來, 放到一個集合中返回。

              add 方法代碼如下:        

private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
        Assert.notNull(configurer, "configurer cannot be null");
        //configurer必須是 SecurityConfigurer 的子類
        Class<? extends SecurityConfigurer<O, B>> clazz = configurer.getClass();
        synchronized(this.configurers) {
            if (this.buildState.isConfigured()) {
                throw new IllegalStateException("Cannot apply " + configurer + " to already built object");
            } else {
                List<SecurityConfigurer<O, B>> configs = null;
                if (this.allowConfigurersOfSameType) {
                    configs = (List)this.configurers.get(clazz);
                }
                List<SecurityConfigurer<O, B>> configs = configs != null ? configs : new ArrayList(1);
                ((List)configs).add(configurer);
                this.configurers.put(clazz, configs);
                if (this.buildState.isInitializing()) {
                    this.configurersAddedInInitializing.add(configurer);
                }
            }
        }
    }
//獲取指定的配置類
@SuppressWarnings("unchecked")
	public <C extends SecurityConfigurer<O, B>> List<C> getConfigurers(Class<C> clazz) {
		List<C> configs = (List<C>) this.configurers.get(clazz);
		if (configs == null) {
			return new ArrayList<>();
		}
		return new ArrayList<>(configs);
	}

2.3.2.2、doBuild()方法      

@Override
	protected final O doBuild() throws Exception {
		synchronized (this.configurers) {
			this.buildState = BuildState.INITIALIZING;
			beforeInit(); //是一個預(yù)留方法,沒有任何實現(xiàn)
			init(); // 就是找到所有的 xxxConfigure,挨個調(diào)用其 init 方法進行初始化,完成默認(rèn)過濾器的初始化
			this.buildState = BuildState.CONFIGURING;
			beforeConfigure(); // 是一個預(yù)留方法,沒有任何實現(xiàn)
			configure(); // 就是找到所有的 xxxConfigure,挨個調(diào)用其 configure 方法進行配置。
			this.buildState = BuildState.BUILDING;
			O result = performBuild();
// 是真正的過濾器鏈構(gòu)建方法,但是在 AbstractConfiguredSecurityBuilder中 performBuild 方法只是一個抽象方法,具體的實現(xiàn)在 HttpSecurity 中
			this.buildState = BuildState.BUILT;
			return result;
		}
	}

 init方法:完成所有相關(guān)過濾器的初始化

private void init() throws Exception {
		Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
		for (SecurityConfigurer<O, B> configurer : configurers) {
			configurer.init((B) this); // 初始化對應(yīng)的過濾器
		}
		for (SecurityConfigurer<O, B> configurer : this.configurersAddedInInitializing) {
			configurer.init((B) this);
		}
	}

configure方法:完成HttpSecurity和對應(yīng)的過濾器的綁定。

private void configure() throws Exception {
		Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
		for (SecurityConfigurer<O, B> configurer : configurers) {
			configurer.configure((B) this);
		}
	}

2.4、HttpSecurity

         HttpSecurity 做的事情,就是對各種各樣的 xxxConfigurer 進行配置;

         HttpSecurity 部分方法列表如下:                

         HttpSecurity 中有大量類似的方法,過濾器鏈中的過濾器就是這樣一個一個配置的。我們

          就不一一介紹 了。每個配置方法的結(jié)尾都會調(diào)用一次 getOrApply 方法,getOrApply

         方法是做什么的?

         getOrApply 方法如下:

private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(C configurer)
			throws Exception {
		C existingConfig = (C) getConfigurer(configurer.getClass());
		if (existingConfig != null) {
			return existingConfig;
		}
		return apply(configurer);
	}

          getConfigurer 方法是在它的父類 AbstractConfiguredSecurityBuilder 中定義的,目的就

          是去查看當(dāng)前 這個 xxxConfigurer 是否已經(jīng)配置過了。   

          如果當(dāng)前 xxxConfigurer 已經(jīng)配置過了,則直接返回,否則調(diào)用 apply 方法,這個 apply

           方法最終會調(diào) 用到 AbstractConfiguredSecurityBuilder#add 方法,將當(dāng)前配置

          configurer 收集起來 HttpSecurity 中還有一個 addFilter 方法.

          addFilter 方法如下所示:

@Override
	public HttpSecurity addFilter(Filter filter) {
		Integer order = this.filterOrders.getOrder(filter.getClass());
		if (order == null) {
			throw new IllegalArgumentException("The Filter class " + filter.getClass().getName()
					+ " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
		}
		this.filters.add(new OrderedFilter(filter, order));
		return this;
	}

          這個 addFilter 方法的作用,主要是在各個 xxxConfigurer 進行配置的時候,會調(diào)用到這

         個方法, (xxxConfigurer 就是用來配置過濾器的),把 Filter 都添加到 fitlers 變量中。

3、總結(jié)

      這就是 HttpSecurity 的一個大致工作流程。把握住了這個工作流程,剩下的就只是一些簡

      單的重 復(fù)的 xxxConfigurer 配置了

到此這篇關(guān)于SpringSecurity HttpSecurity 類處理流程的文章就介紹到這了,更多相關(guān)SpringSecurity HttpSecurity 類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文帶你搞懂Spring響應(yīng)式編程

    一文帶你搞懂Spring響應(yīng)式編程

    相信響應(yīng)式編程經(jīng)常會在各種地方被提到。本篇就為大家從函數(shù)式編程一直到Spring?WeFlux做一次簡單的講解,并給出一些示例,希望大家可以更好的理解響應(yīng)式編程
    2022-07-07
  • Java?IO及BufferedReader.readline()出現(xiàn)的Bug

    Java?IO及BufferedReader.readline()出現(xiàn)的Bug

    這篇文章主要介紹了Java?IO及BufferedReader.readline()出現(xiàn)的Bug,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java設(shè)計模式之責(zé)任鏈模式

    Java設(shè)計模式之責(zé)任鏈模式

    今天小編就為大家分享一篇關(guān)于Java設(shè)計模式之責(zé)任鏈模式,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • 快速了解JAVA中的Random()函數(shù)

    快速了解JAVA中的Random()函數(shù)

    這篇文章主要介紹了JAVA中的Random()函數(shù)的使用方法,文中代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • SpringBoot整合第三方技術(shù)的詳細(xì)步驟

    SpringBoot整合第三方技術(shù)的詳細(xì)步驟

    這篇文章主要介紹了SpringBoot整合第三方技術(shù),包括整合Junit、整合Mybatis、整合Mybatis-plus、整合Druid,本文通過實例代碼相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • 基于jni調(diào)用時,jvm報錯問題的深入分析

    基于jni調(diào)用時,jvm報錯問題的深入分析

    本篇文章是對jni調(diào)用時,jvm的報錯問題進行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • IDEA類存在但找不到的解決辦法

    IDEA類存在但找不到的解決辦法

    本文主要介紹了IDEA類存在但找不到的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • mybatis的dtd約束文件及配置文件xml自動提示操作

    mybatis的dtd約束文件及配置文件xml自動提示操作

    這篇文章主要介紹了mybatis的dtd約束文件及配置文件xml自動提示操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • FutureTask為何單個任務(wù)僅執(zhí)行一次原理解析

    FutureTask為何單個任務(wù)僅執(zhí)行一次原理解析

    這篇文章主要為大家介紹了FutureTask為何單個任務(wù)僅執(zhí)行一次原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • Java:泛型知識知多少

    Java:泛型知識知多少

    這篇文章主要介紹了java泛型基礎(chǔ)知識及通用方法,從以下幾個方面介紹一下java的泛型: 基礎(chǔ), 泛型關(guān)鍵字, 泛型方法, 泛型類和接口,感興趣的可以了解一下
    2021-08-08

最新評論