电竞比分网-中国电竞赛事及体育赛事平台

分享

SSM項(xiàng)目基于注解整合,含事務(wù)和緩存配置(零xml配置版)

 oldzhoua 2019-04-14

前面學(xué)習(xí)ssm項(xiàng)目整合的時(shí)候都是配置一堆的xml文件,今天改成使用一堆的配置類替代xml文件,還是spring+mybatis+spring mvc項(xiàng)目整合,同時(shí)還會(huì)介紹其它額外的如整合shiro、redis的配置、事務(wù)管理與緩存管理的配置、異步線程池配置。

我可能不會(huì)介紹得很詳細(xì),挑先難點(diǎn)說(shuō)幾句就好了,其它的看xml配置就能看懂的就不介紹了。

推薦博客

我在配置的過(guò)程中參考了下面幾篇博客才解決的一些坑。

  • Spring 4 學(xué)習(xí)筆記7:MVC 配置(JAVA方式):https://blog.csdn.net/w1196726224/article/details/52687324

  • Spring MVC 無(wú)XML配置入門(mén)示例:https://blog.csdn.net/classicer/article/details/50753019

  • SpringMvc+Spring+MyBatis 基于注解整合:https://www.cnblogs.com/niechen/p/springmvc.html#_label2

  • spring4.0 @PropertySource讀取配置文件:https://blog.csdn.net/zz210891470/article/details/68948723

ServletContainerInitializer

在 Servlet 3.0 的環(huán)境中,容器會(huì)在 classpath 中尋找繼承了 javax.servlet.ServletContainerInitializer 接口的類,用它來(lái)配置 servlet 容器。 Spring 提供了一個(gè)繼承這個(gè)接口的類 SpringServletContainerInitializer,在這個(gè)類中,它會(huì)尋找任何繼承了 WebApplicationInitializer 接口的類并用其來(lái)配置 servlet 容器。Spring 3.2 提供了一個(gè)繼承了 WebApplicationInitializer 接口的基類 AbstractAnnotationConfigDispatcherServletInitializer。所以,你的 servlet 配置類只需要繼承 AbstractAnnotationConfigDispatcherServletInitializer,就會(huì)被發(fā)現(xiàn)而用于 servlet 容器的配置。

這句話的意思就是說(shuō),只要我們創(chuàng)建一個(gè)類且繼承AbstractAnnotationConfigDispatcherServletInitializer類,那么我們就可以去掉之前在web.xml文件中配置的DispatcherServlet還有初始化spring容器的監(jiān)聽(tīng)器,甚至其它的過(guò)濾器等所有配置都可以在這個(gè)類中完成配置了。

首先,如果你在pom.xml文件中聲明依賴的servlet-api版本是低于3.0的,那么你需要修改servlet-api的依賴配置,改為如下。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
</dependency>

同時(shí)清除web.xml文件下的所有配置

<web-app xmlns:xsi='http://www./2001/XMLSchema-instance'
         xmlns='http://java./xml/ns/javaee'
         xsi:schemaLocation='http://java./xml/ns/javaee
         http://java./xml/ns/javaee/web-app_2_5.xsd'

         id='WebApp_ID' version='2.5'>


    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

</web-app>
WebConfigServletInitializer

WebConfigServletInitializer是我創(chuàng)建的一個(gè)繼承AbstractAnnotationConfigDispatcherServletInitializer的類。

public class WebConfigServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMVCConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{'/'};
    }


    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);

        FilterRegistration.Dynamic  characterEncodingDynamic= servletContext.addFilter('characterEncodingFilter', CharacterEncodingFilter.class);
        characterEncodingDynamic.addMappingForUrlPatterns(null,true,'/*');
        characterEncodingDynamic.setInitParameter('encoding','UTF-8');

        FilterRegistration.Dynamic shiroFilterDynamic = servletContext.addFilter('shiroFilter',DelegatingFilterProxy.class);
        shiroFilterDynamic.addMappingForUrlPatterns(null,true,'/*');

        servletContext.addListener(InitRedisService.class);
    }
}

其中g(shù)etRootConfigClasses方法、getServletConfigClasses方法、getServletMappings方法是必須要重寫(xiě)的。getRootConfigClasses是獲取spring的配置類、getServletConfigClasses是獲取配置DispatcherServlet的類(spring-mvc的配置類),getServletMappings是獲取DispatcherServlet要攔截的路徑。

onStartup方法是我重寫(xiě)父類的方法,在該方法中配置字符編碼過(guò)濾器和shiro的代理過(guò)濾器等。這樣就不需要在web.xml文件中做任何配置了。我們也不需要配置這個(gè)類,因?yàn)檫@個(gè)類是在服務(wù)啟動(dòng)的時(shí)候被全局掃描出來(lái)調(diào)用的。

spring-mvc的配置

先來(lái)看spring-mvc的配置,這個(gè)配置類就是WebConfigServletInitializer的getServletConfigClasses方法中指定的類。

@Configuration
//包掃描
@ComponentScans(
        value = {
                @ComponentScan('wjy.weiai7lv.controller'),
                @ComponentScan('wjy.weiai7lv.exception')
        }
)
@EnableWebMvc//將此注釋添加到@Configuration類將從WebMvcConfigurationSupport導(dǎo)入Spring MVC配置。
public class SpringMVCConfig extends WebMvcConfigurerAdapter {

        @Autowired
        private WebConstantConfig webConstantConfig;

        /**
         * 靜態(tài)資源配置
         * @param registry
         */

        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
                //圖片資源路由,需要在tomcat的server.xml配置中對(duì)應(yīng)的<Host>內(nèi)容添加配置:
                // <Context docBase='文件路徑' path='/images'/>
                registry.addResourceHandler('/images/**')
                        //定向到外部文件目錄
                        .addResourceLocations('file:'+webConstantConfig.getPrivateUploadFileRootPath()+'/');
        }


        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {

        }

        /**
         * 添加消息轉(zhuǎn)換器
         * @param converters
         */

        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
                MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
                List<MediaType> mediaTypeList = new ArrayList<>();
                mediaTypeList.add(MediaType.parseMediaType('text/json;charset=UTF-8'));
                mediaTypeList.add(MediaType.parseMediaType('application/json;charset=UTF-8'));
                //支持的媒體類型
                messageConverter.setSupportedMediaTypes(mediaTypeList);
                ObjectMapper objectMapper = new ObjectMapper();
                //設(shè)置不輸出值為null的字段
                objectMapper.setSerializationInclusion(NON_NULL);
                messageConverter.setObjectMapper(objectMapper);
                converters.add(messageConverter);
        }

        /**
         * 配置視圖解析器
         * @param registry
         */

        @Override
        public void configureViewResolvers(ViewResolverRegistry registry) {
                InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
                viewResolver.setPrefix('/WEB-INF/pages/');
                viewResolver.setSuffix('.jsp');
                registry.viewResolver(viewResolver);
        }

        /**
         *
         * @return
         */

        @Bean
        public CommonsMultipartResolver multipartResolver(){
                CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
                multipartResolver.setDefaultEncoding('utf-8');
                multipartResolver.setMaxUploadSize(1024*1024*100);
                return multipartResolver;
        }

}

@Configuration注解:可以理解是將一個(gè)類聲明為spring的配置類吧,同時(shí)被@Configuration注解的類也是一個(gè)bean,可以在其它bean中使用@Autowired獲取到。

@ComponentScans和@ComponentScan注解:這兩個(gè)注解都是配置包掃描的,前一個(gè)多了一個(gè)'s',很容易理解就是一個(gè)集合,多個(gè)@ComponentScan組稱@ComponentScans,這樣可以聲明多個(gè)包。

@EnableWebMvc注解:開(kāi)啟mvc。就這么簡(jiǎn)單,再?gòu)?fù)雜的我也不懂了。

@Bean注解:用戶注解在一個(gè)方法上,@Bean注解必須是在被@Configuration注解的類中的方法上使用,被@Bean聲明的方法會(huì)在初始化時(shí)候被調(diào)用,且調(diào)用該方法返回的對(duì)象將作為bean保存在spring容器中。如果@Bean沒(méi)有配置bean名稱,則默認(rèn)使用方法名作為beanName。

SpringMVCConfig類中的addResourceHandlers方法配置靜態(tài)資源訪問(wèn)的,就是當(dāng)訪問(wèn)的url以“/images”開(kāi)頭的都定位到系統(tǒng)文件目錄“/目錄”中去找文件。

configureMessageConverters方法是添加消息轉(zhuǎn)換器的,就是配置使用jackson將數(shù)據(jù)轉(zhuǎn)成json字符串。對(duì)應(yīng)xml文件中的如下配置:

<!-- 開(kāi)啟注解驅(qū)動(dòng),使用注解映射器和注解適配器 -->
    <mvc:annotation-driven>
        <!-- 指定消息轉(zhuǎn)換器 -->
        <mvc:message-converters>
            <ref bean='mappingJackson2HttpMessageConverter'/>
        </mvc:message-converters>

    </mvc:annotation-driven>

configureViewResolver方法用于注冊(cè)視圖解析器,而multipartResolver方法是用來(lái)注冊(cè)一個(gè)CommonsMultipartResolver,解決文件上傳的,對(duì)應(yīng)xml配置文件中的如下配置。

 <!-- 文件上傳,id不能少,id='multipartResolver' -->
    <bean id='multipartResolver' class='org.springframework.web.multipart.commons.CommonsMultipartResolver'>
        <!-- 設(shè)置上傳文件的最大為100MB 100*1024*1024,maxUploadSize屬性的限制不是針對(duì)單個(gè)文件,而是所有文件的容量之和 -->
        <property name='maxUploadSize' value='104857600' />
        <!-- 文件默認(rèn)編碼 -->
        <property name='defaultEncoding' value='utf-8' />
    </bean>
spring的配置文件

WebConfigServletInitializer類中的getRootConfigClasses方法返回的類就是spring的配置類。需要自己創(chuàng)建。

@Configuration
//配置包掃描,mvc的交給mvc配置
@ComponentScans(value = {
        @ComponentScan('wjy.weiai7lv.service.impl')
,
        @ComponentScan('wjy.weiai7lv.aspect'),
        @ComponentScan('wjy.weiai7lv.tasks.impl'),
        @ComponentScan('wjy.weiai7lv.listener'),
        @ComponentScan('wjy.weiai7lv.shiro')
})
@Import(value = {
        RedisConfig.class,
        MyBatisConfig.class,
        TxAndCacheConfig.class,
        ShiroConfig.class,
        AsyncConfig.class,
        WebConstantConfig.class
})
//其它@Configuration類
public class SpringConfig{

    /**
     * 要想使用@Value 用${}占位符注入屬性,這個(gè)bean是必須的。
     * @return
     */

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

}

這個(gè)類就是一堆注解,也很容易理解,其中@Configuration前面已經(jīng)說(shuō)過(guò)了,接著@ComponentScans和@ComponentScan注解也說(shuō)過(guò)了,不過(guò)配置有點(diǎn)區(qū)別,前面mvc配置類的@ComponentScans注解配置的是掃描Handler處理器(也叫控制器)的類,即被@Controller注解的類,而這里則是配置掃描普通bean以及數(shù)據(jù)持久化層Dao層的bean和業(yè)務(wù)處理層Server層的bean,當(dāng)然還有其它如切面類的bean。

@Import注解,import這個(gè)詞在導(dǎo)入類的時(shí)候用得特別多,所以很容易理解這個(gè)注解就是用于導(dǎo)入其它被@Configuration注解聲明的類,這樣我們就可以把mybatis的配置、shiro的配置等單獨(dú)寫(xiě)一個(gè)java類完成配置,然后在這里導(dǎo)入就可以。

下面這個(gè)方法照著寫(xiě)進(jìn)去就行了,這是解決使用@Value注解注入properties文件中的屬性獲取不到的問(wèn)題的。

    /**
     * 要想使用@Value 用${}占位符注入屬性,這個(gè)bean是必須的。
     * @return
     */

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
mybatis的配置

配置mybatis需要完成的工作:配置一個(gè)數(shù)據(jù)源DataSource、連接工程sqlSessionFactory,還有一個(gè)事務(wù)管理者TransactionManager。同時(shí)還需要聲明掃描mapper接口。

@Configuration
//導(dǎo)入properties配置文件
@PropertySource('classpath:mybatis/database.properties')
//配置mapper接口掃描,掃描Mybatis的Mapper接口
@MapperScan(basePackages = 'wjy.weiai7lv.dao', sqlSessionFactoryRef = 'sqlSessionFactory')
//開(kāi)啟事務(wù)管理
//@EnableTransactionManagement
public class MyBatisConfig{


    @Value('${dataSource.driver}')
    private String driverClass;
    @Value('${dataSource.url}')
    private String jdbcUrl;
    @Value('${dataSource.username}')
    private String user;
    @Value('${dataSource.password}')
    private String password;

    @Value('${c3p0.initialPoolSize}')
    private Integer initialPoolSize;
    @Value('${c3p0.maxPoolSize}')
    private Integer maxPoolSize;
    @Value('${c3p0.minPoolSize}')
    private Integer minPoolSize;
    @Value('${c3p0.maxStatements}')
    private Integer maxStatements;
    @Value('${c3p0.acquireIncrement}')
    private Integer acquireIncrement;
    @Value('${c3p0.maxIdleTime}')
    private Integer maxIdleTime;
    @Value('${c3p0.idleConnectionTestPeriod}')
    private Integer idleConnectionTestPeriod;


    /**
     * 配置數(shù)據(jù)源
     *
     * @return
     */

    @Bean //不指定bean的名稱默認(rèn)使用方法名為bean的名稱(id),并首字母小寫(xiě)
    public ComboPooledDataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setAutoCommitOnClose(false);//關(guān)閉自動(dòng)提交
        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setUser(user);
        dataSource.setPassword(password);
        //c3p0的配置
        dataSource.setInitialPoolSize(initialPoolSize);
        dataSource.setMaxPoolSize(maxPoolSize);
        dataSource.setMinPoolSize(minPoolSize);
        dataSource.setMaxStatements(maxStatements);
        dataSource.setAcquireIncrement(acquireIncrement);
        dataSource.setMaxIdleTime(maxIdleTime);
        dataSource.setIdleConnectionTestPeriod(idleConnectionTestPeriod);
        return dataSource;
    }

    /**
     * 配置SqlSessionFactory
     *
     * @param dataSource
     * @return
     * @throws Exception
     */

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier('dataSource') DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources('classpath:mapper/*.xml'));
        sqlSessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResource('classpath:mybatis/mybatis-config.xml'));
        return sqlSessionFactory.getObject();
    }

    /**
     * 配置事務(wù)管理者
     *
     * @param dataSource
     * @return
     */

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier('dataSource') DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

這些配置我就不多說(shuō)了,跟xml配置的一樣,不過(guò)就是將注入的配置直接調(diào)用set方法賦值罷了。細(xì)心的你會(huì)發(fā)現(xiàn)這個(gè)配置類有一個(gè)@EnableTransactionManagement的注解被我注釋了,其實(shí)這個(gè)@EnableTransactionManagement注解的作用就是開(kāi)啟事務(wù)管理的,如果去掉注釋那么事務(wù)管理的配置也就完成了,@Transactional注解也就可以用了,因?yàn)槲覀冎宦暶髁艘粋€(gè)事務(wù)管理者(dataSourceTransactionManager方法)。但是這里我將事務(wù)管理放到另一個(gè)類中和緩存一起配置。

Redis的配置
@Configuration
@PropertySource('classpath:redis/redis.properties')
//@EnableCaching
public class RedisConfig{

    @Value('${redis.host}')
    private String host;
    @Value('${redis.port}')
    private Integer port;
    @Value('${redis.dbIndex}')
    private Integer dbIndex;

    @Value('${redis.maxTotal}')
    private Integer maxTotal;
    @Value('${redis.maxIdle}')
    private Integer maxIdle;
    @Value('${redis.minIdle}')
    private Integer minIdle;
    @Value('${redis.maxWaitMillis}')
    private Integer maxWaitMillis;
    @Value('${redis.testOnBorrow}')
    private Boolean testOnBorrow;
    @Value('${redis.expiration}')
    private Long expiration;

    /**
     * 配置JedisPoolConfig實(shí)例,JedisPoolConfig是連接池的配置
     * @return
     */

    @Bean
    public JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(maxTotal);
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setTestOnBorrow(testOnBorrow);
        return jedisPoolConfig;
    }

    /**
     * 配置JedisConnectionFactory,連接池工廠
     * @param jedisPoolConfig JedisPoolConfig實(shí)例,使用@Autowired聲明自動(dòng)注入
     * @return
     */

    @Bean
    public JedisConnectionFactory jedisConnectionFactory(@Autowired JedisPoolConfig jedisPoolConfig){
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
        jedisConnectionFactory.setUsePool(true);
        jedisConnectionFactory.setPoolConfig(jedisPoolConfig);
        jedisConnectionFactory.setDatabase(dbIndex);
        jedisConnectionFactory.setHostName(host);
        jedisConnectionFactory.setPort(port);
        return jedisConnectionFactory;
    }


    /**
     * 配置操作redis的RedisTemplate對(duì)象
     * spring-data-redis封裝了RedisTemplate對(duì)象來(lái)進(jìn)行對(duì)Redis的各種操作,它支持所有的Redis原生的api。
     * @param jedisConnectionFactory
     * @return
     */

    @Bean
    public RedisTemplate redisTemplate(@Autowired JedisConnectionFactory jedisConnectionFactory){
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.setConnectionFactory(jedisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
        return redisTemplate;
    }

    /**
     * 配置一個(gè)緩存管理者,使用spring-data-redis提供的RedisCacheManager類配置,
     *         RedisCacheManager實(shí)現(xiàn)了spring cache提供的CacheManager接口
     * @param redisTemplate
     * @return
     */

    @Bean
    public RedisCacheManager redisCacheManager(@Autowired RedisTemplate redisTemplate){
        RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate);

        //注入緩存名稱
        Set<String>  cacheNames = new HashSet<>();
        cacheNames.add('userCache');
        cacheNames.add('rolesCache');
        cacheNames.add('movieBoxOffice');
        redisCacheManager.setCacheNames(cacheNames);

        //默認(rèn)緩存過(guò)期時(shí)間
        redisCacheManager.setDefaultExpiration(expiration);

        //指定某個(gè)緩存名稱下的緩存的過(guò)期時(shí)間
        Map<String,Long> expirationMap = new HashMap<>();
        expirationMap.put('userCache',3600l);
        redisCacheManager.setExpires(expirationMap);

        return redisCacheManager;
    }
}

最終要獲取的是一個(gè)CacheManager對(duì)象,即緩存管理者,Redis提供的實(shí)現(xiàn)CacheManager的類是RedisCacheManager。就是redisCacheManager方法配置的bean。能看懂xml的配置這里也就不難看懂了。

同樣,這里的@EnableCaching注解也被我注釋了,就是因?yàn)槲乙獙⑹聞?wù)管理和緩存單獨(dú)配置。

事務(wù)管理和緩存配置

因?yàn)槲蚁胍獙?shí)現(xiàn)像xml配置那樣指定默認(rèn)的事務(wù)管理者和默認(rèn)的緩存管理者。

/**
 * 開(kāi)啟緩存
 * 開(kāi)啟事務(wù)管理
 */

@Configuration
// 配合CachingConfigurerSupport可指定緩存管理者,
// 否則spring從bean容器中查找一個(gè)實(shí)現(xiàn)CacheManager的對(duì)象
@EnableCaching
// 配合TransactionManagementConfigurer可指定事務(wù)管理者,
// 為@TransactionManager注解配置默認(rèn)的緩存管理者
@EnableTransactionManagement
public class TxAndCacheConfig extends CachingConfigurerSupport implements TransactionManagementConfigurer {

    /**
     * 在MyBatisConfig中配置了dataSourceTransactionManager,所以@Autowired注入的就是dataSourceTransactionManager
     */

    @Autowired
    private PlatformTransactionManager dataSourceTransactionManager;

    /**
     * 在RedisConfig中配置了redisCacheManager,所以@Autowired注入的就是redisCacheManager
     */

    @Autowired
    private CacheManager cacheManager;

    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return dataSourceTransactionManager;
    }


    @Override
    public CacheManager cacheManager() {
        return cacheManager;
    }
}

@EnableCaching開(kāi)啟緩存,@EnableTransactionManagement開(kāi)啟事務(wù)管理。這里使用@Autowired注入了之前配置的事務(wù)管理者和redis緩存管理者。

CachingConfigurerSupport實(shí)現(xiàn)CachingConfigurer接口,雖然CachingConfigurerSupport是CachingConfigurer接口的空實(shí)現(xiàn),但是我們沒(méi)有必要直接去實(shí)現(xiàn)CachingConfigurer接口,因?yàn)槲覀兿胍闹皇菍?shí)現(xiàn)cacheManager這一個(gè)方法。重寫(xiě)CachingConfigurerSupport的cacheManager方法返回緩存管理者就是指定默認(rèn)的緩存管理者。

實(shí)現(xiàn)TransactionManagementConfigurer接口,在annotationDrivenTransactionManager方法中返回事務(wù)管理者就是指定默認(rèn)事務(wù)管理者。

Shiro權(quán)限驗(yàn)證的配置

由于并不是很多人都采用Shiro做權(quán)限驗(yàn)證,所以這里就不介紹它的配置了,給個(gè)參考大家看就行了。

@Configuration
public class ShiroConfig {

    @Autowired
    private AuthorizingRealm realm;

    /**
     * 配置SecurityManager
     * @return
     */

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;
    }

    /**
     * 被代理的shiroFilter
     * @param securityManager
     * @return
     */

    @Bean('shiroFilter')
    public ShiroFilterFactoryBean shiroFilterFactory(@Qualifier('securityManager') SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //注入SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //注入過(guò)濾器
        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put('authc'new WeiAi7LvUserAuthcFilter());
        filterMap.put('roles'new WeiAi7LvRolesAuthorizationFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        //過(guò)濾器Chain定義,指定哪些資源(url)交給哪個(gè)過(guò)濾器過(guò)濾,責(zé)任鏈模式
        Map<String, String> map = new HashMap<>();
        map.put('/''anon');
        map.put('/sms/send''anon');
        map.put('/user/login''anon');
        map.put('/user/regist''anon');
        map.put('/user/logout''authc');
        map.put('/lover/record''roles[lover]');
        map.put('/lover/*''authc');
        map.put('/found/*''authc');
        map.put('/**''roles[lover]');
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

}
spring線程池的配置

使用@EnableAsync注解開(kāi)啟異步管理,如果項(xiàng)目中配置了多個(gè)線程池,則可以實(shí)現(xiàn)AsyncConfigurer接口指定當(dāng)@Async注解不指定線程池時(shí)使用的默認(rèn)線程池。這里我為了偷懶就不使用@Value注入屬性了,直接賦值。

@Configuration
// 啟用spring線程池,配合AsyncConfigurer接口使用指定線程池
// 如果不配合AsyncConfigurer使用則spring會(huì)從bean容器中查找一個(gè)實(shí)現(xiàn)Executor接口的bean對(duì)象作為默認(rèn)的線程池
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    private Integer corePoolSize = 5;
    private Integer maxPoolSize = 10;
    private Integer queueCapacity = 200;
    private Integer keepAlive = 300;//單位秒

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix('weiai-executor-');
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        executor.setKeepAliveSeconds(keepAlive);
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncUncaughtExceptionHandler() {
            @Override
            public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
                System.err.println(method.getName()+'異步方法執(zhí)行異常===>'+throwable.getMessage());
                throwable.printStackTrace();
            }
        };
    }
}

完成。。。。

本文的很多配置都是我根據(jù)spring提供的注解的詞意猜出來(lái)的,像@Import、@EnableAsync等注解的使用都是猜出來(lái)的。其實(shí)可以看出個(gè)規(guī)律,如@EnableCaching、@EnableTransactionManagement注解分別是用來(lái)開(kāi)啟緩存管理和事務(wù)管理的,所以@Enable開(kāi)頭的注解都是用來(lái)聲明開(kāi)啟xx的,而且實(shí)現(xiàn)CachingConfigurer接口可以指定默認(rèn)的緩存管理者、實(shí)現(xiàn)TransactionManagementConfigurer接口可以指定默認(rèn)的事務(wù)管理者,那么@EnableXXX注解一定提供一個(gè)XXXConfigurer接口來(lái)實(shí)現(xiàn)指定默認(rèn)XXX。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多