Spring Boot 示例項目

  

Spring Boot 基於註解式開發 maven REST 示例項目css

 

   項目地址:https://github.com/windwant/spring-boot-servicehtml

   項目地址:https://github.com/windwant/spring-dubbo-servicejava

項目特點:

1.  servlet、listener、interceptor、filter配置node

2.  mybatis配置集成,多數據源 RouingDataSourcemysql

3.  集成jmx監控 MBeangit

4.  定時任務配置 Scheduledgithub

5.  aop配置web

6.  ftp服務 FTPTranportredis

7.  測試 SpringBootTest算法

8.  Metrics監控

9.  參數驗證 javax.validation hibernate.validator

   a)  測試:/hellox?name=

10. 跨域處理 Cors

11. 權限控制 shiro權限框架

   a)  測試用戶:userName: admin passwd: admin

   b)  驗證碼:/login/checkcode

   c)  登陸:/login?userName=&passwd=&code=

   d)  測試:/hellox?name=

12. 導出Excel SXSSFWorkBook 海量數據導出

   a)  測試:/export

13. Consul服務註冊與發現;

   a) 服務啓動註冊到consul;

   b) 測試獲取redis服務,初始化redis資源;

   c) consul 監控redis服務;

   d) 注意consul客戶端和consul程序版本問題

14. reids分佈式鎖

   a) lua腳本 獲取redis分佈式鎖

15. SPI機制:org/windwant/spring/core/spi

   a) 運行時配置:META-INF/services/org.windwant.spring.core.spi.Calc

16. static資源,「/」映射

17. 使用druid數據源鏈接池;配置druid數據源監控:http://localhost:8081/druid/index.html

18. Dubbo RPC 服務

 

1、 Web servlet、listener、interceptor等

1. servlet:

啓動類添加註解@ServletComponentScan
編寫servlet:
@WebServlet("/web")
public class BootSevlet implements Servlet {
...
2. Interceptor:
編寫:
/**
 * BootInterceptor
 */
public class BootInterceptor implements HandlerInterceptor {
...

註冊:WebMvcConfigurerAdapter->addInterceptor方法。

@Configuration
public class ApplicationConfig {
 
    @Configuration
    public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
 
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new BootInterceptor()).addPathPatterns("/**");
            super.addInterceptors(registry);
        }
 
...
3. listenenr:實現各類listener
@WebListener
public class BootListener implements ServletContextListener {
...

2、mybatis配置集成,多數據源配置

配置文件:

1. 接口方式開發dao,掃描包配置 :@MapperScan(basePackages = "org.windwant.spring.mapper")

2. 配置dataSource,sqlSessionFactory

datasource 根據application.yml配置的數據源配置

application.yml

datasource:
    local:
        url: $[datasource.local.url]
        username: $[datasource.local.user]
        password: $[datasource.local.password]
        driverClassName: com.mysql.jdbc.Driver
        type: org.apache.commons.dbcp.BasicDataSource
        max-active: 30
        max-idle: 10
        max-wait: 10
        test-while-idle: true
    remote:
        url: $[datasource.remote.url]
        username: $[datasource.remote.user]
        password: $[datasource.remote.password]
        driverClassName: com.mysql.jdbc.Driver
        type: org.apache.commons.dbcp.BasicDataSource
        max-active: 30
        max-idle: 10
        max-wait: 10
        test-while-idle: true
 

DataSource 註解配置:

/**
 * Created by windwant on 2016/12/30.
 * implements EnvironmentAware, ApplicationContextAware
 */
@Configuration
public class MybatisConfig {
 
//    private Environment environment;
//
//    @Override
//    public void setEnvironment(Environment environment) {
//        this.environment = environment;
//    }
 
    @Primary
    @Bean(name = "localDataSource")
    @Order(value = 1)
    @ConfigurationProperties(prefix = "datasource.local")
    public DataSource localDataSource(){
        return DataSourceBuilder.create().build();
    }
 
    @Order(value = 2)
    @Bean(name = "remoteDataSource")
    @ConfigurationProperties(prefix = "datasource.remote")
    public DataSource remoteDataSource() {
        return DataSourceBuilder.create().build();
    }
 
    @Bean(name = "routingDataSource")
    @Order(value = 3)
    public DataSource routingDataSource(@Qualifier("localDataSource") DataSource localDataSource,
                                        @Qualifier("remoteDataSource") BasicDataSource remoteDataSource){
        RoutingDataSource routingDataSource = new RoutingDataSource();
        Map<Object, Object> dataSources = new HashMap<>();
        dataSources.put(Type.LOCAL.name(), localDataSource);
        dataSources.put(Type.REMOTE.name(), remoteDataSource);
        routingDataSource.setTargetDataSources(dataSources);
        routingDataSource.setDefaultTargetDataSource(localDataSource);
        return routingDataSource;
    }
 
 
    @Bean
    @Order(value = 4)
    @Lazy
    public SqlSessionFactory sqlSessionFactory(@Qualifier("remoteDataSource") DataSource remoteDataSource,
                                               @Qualifier("localDataSource") DataSource localDataSource,
                                               @Qualifier("routingDataSource") DataSource routingDataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(routingDataSource);
        factoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/*.xml"));
        factoryBean.afterPropertiesSet();
        return factoryBean.getObject();
    }
 
//    private ApplicationContext ctx;
//
//    @Override
//    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//        this.ctx = applicationContext;
//    }
}

項目添加Bean配置:

@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
    MapperScannerConfigurerProxy mapperScannerConfigurerProxy = new MapperScannerConfigurerProxy();
    mapperScannerConfigurerProxy.setBasePackage("org.windwant.spring.mapper");
    return mapperScannerConfigurerProxy;
}
 

3、集成jmx監控 MBean

/**
 * Created by windwant on 2017/4/6.
 * JMX Mbean 監控 能夠經過jconsole進行mbean暴露操做
 */
@Component
@ManagedResource(description = "sboot svr")
public class WAMBean {
    // 屬性
    private String name;
    private int age;
    private String message;
 
    @ManagedAttribute
    public String getName() {
        System.out.println("name: " + name);
        return name;
    }
 
    @ManagedAttribute
    public void setName(String name) {
        this.name = name;
    }
 
    @ManagedAttribute
    public int getAge() {
        System.out.println("age: "+age);
        return age;
    }
 
    @ManagedAttribute
    public void setAge(int age) {
        this.age = age;
    }
 
    @ManagedAttribute
    public String getMessage() {
        System.out.println("message: " + message);
        return message;
    }
 
    @ManagedAttribute
    public void setMessage(String message) {
        this.message = message;
    }
 
    @ManagedOperation
    @ManagedOperationParameter(name = "message", description = "message")
    public void call(String message) {
        System.out.println("call:" + message);
    }
 
    @ManagedOperation
    @ManagedOperationParameter(name = "who", description = "who")
    @ManagedOperationParameter(name = "what", description = "what")
    public void look(String who, String what){
        System.out.println(who + " 發現了 " + what);
    }
 
    @Autowired
    FTPTransport ftpTransport;
 
    @ManagedOperation
    public void upload() throws FileNotFoundException {
        FileInputStream f = null;
        try {
            f = new FileInputStream(new File("D:\\a.json"));
            ftpTransport.uploadFile("ajson", f);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if(f != null){
                    f.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
 
        System.out.println("to play....");
    }
 
}
四:定時任務配置 Scheduled 
@Component
public class BootJob {
 
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
 
    @Scheduled(fixedRate = 1000)
    public void reportTime(){
        System.out.println("current time is: " +  dateFormat.format(new Date()));
    }
}
 
五:參數驗證
 
參數Bean:驗證註解 @NotBlank @NotNull等
public class Guest {
    @NotBlank(message = "{guest.name}")
    private String name;
 
    private Integer sex;

Controller:參數添加@Valid註解

@RequestMapping("/hellox")
Map<String, Object> hellox(@Valid Guest guest, BindingResult result){
    if(result.hasErrors()){
        return Response.response(-1, Constants.FAILED, result.getAllErrors());
    }
使用lang驗證提示信息:
@Bean
public LocalValidatorFactoryBean localValidatorFactoryBean(){
    LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
    localValidatorFactoryBean.setProviderClass(HibernateValidator.class);
    ReloadableResourceBundleMessageSource rrbms = new ReloadableResourceBundleMessageSource();
    rrbms.setBasename("classpath:/lang/messages");
    rrbms.setUseCodeAsDefaultMessage(false);
    rrbms.setDefaultEncoding("UTF-8");
    localValidatorFactoryBean.setValidationMessageSource(rrbms);
    return localValidatorFactoryBean;
}
六:跨域處理 Cors 
 
配置WebMvcConfigureAdapter addCorsMappings
addMapping:請求攔截
allowedOrigins:攔截請求源
allowedMethods:攔截方法
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
 
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new BootInterceptor()).addPathPatterns("/**");
            super.addInterceptors(registry);
        }
 
        /**
         * 跨域處理 映射全部路徑 容許全部來源 如下方法請求
         * @param registry
         */
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH");
        }
 
七:shiro權限配置
 
@Configuration
public class ShiroConfig implements EnvironmentAware {
	
	private final static int REMEMBER_ME_MAX_AGE = 365 * 24 * 3600;
	
	// 這是個DestructionAwareBeanPostProcessor的子類,負責org.apache.shiro.util.Initializable類型bean的生命週期的,
	// 初始化和銷燬。主要是AuthorizingRealm類的子類,以及EhCacheManager類
	@Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
	
	@Bean
	public SimpleCookie rememberMeCookie(){
	      SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
	      simpleCookie.setMaxAge(REMEMBER_ME_MAX_AGE);
	      return simpleCookie;
	}
	
	@Bean
	public CookieRememberMeManager rememberMeManager(){
	      CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
	      cookieRememberMeManager.setCookie(rememberMeCookie());
	      //rememberMe cookie加密的密鑰 建議每一個項目都不同 默認AES算法 密鑰長度(128 256 512 位)
	      cookieRememberMeManager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag=="));
	      return cookieRememberMeManager;
	}
	
	// 爲了對密碼進行編碼的,防止密碼在數據庫裏明碼保存,固然在登錄認證,這個類也負責對form裏輸入的密碼進行編碼。
	@Bean(name = "hashedCredentialsMatcher")
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher credentialsMatcher = new ComHashedCredentialsMatcher();
		credentialsMatcher.setHashAlgorithmName("MD5");//散列算法:這裏使用MD5算法;
		credentialsMatcher.setHashIterations(1);//散列的次數,好比散列兩次,至關於 md5(md5(""));
		credentialsMatcher.setStoredCredentialsHexEncoded(true);//true時密碼加密用的是Hex編碼;false時用Base64編碼
		return credentialsMatcher;
	}
	
	// 增長緩存減小對數據庫的查詢壓力
	@Bean(name = "ehcacheManager")
    public EhCacheManager getEhCacheManager() {  
        EhCacheManager em = new EhCacheManager();  
        em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");  
        return em;  
    }  
	
	// 自定義的認證類,繼承自AuthorizingRealm,負責用戶的認證和權限的處理
	@Bean(name = "shiroRealm")
    public MyAuthorizingRealm shiroRealm() {
		MyAuthorizingRealm realm = new MyAuthorizingRealm();
		realm.setCredentialsMatcher(hashedCredentialsMatcher());
        realm.setCachingEnabled(true);
        realm.setCacheManager(getEhCacheManager());
        return realm;
    }
 
	//權限管理,這個類組合了登錄,登出,權限,session的處理
	@Bean(name = "securityManager")
	public DefaultWebSecurityManager securityManager(){
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(shiroRealm());
		securityManager.setCacheManager(getEhCacheManager());
		securityManager.setRememberMeManager(rememberMeManager());
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        defaultWebSessionManager.setGlobalSessionTimeout(Long.parseLong(environment.getProperty("session.timeout")));
        securityManager.setSessionManager(defaultWebSessionManager);
        return securityManager;
	}
	
	// 開啓Shiro的註解(如@RequiresRoles,@RequiresPermissions),需藉助SpringAOP掃描使用Shiro註解的類,並在必要時進行安全邏輯驗證 * 配置如下
	// 兩個bean(DefaultAdvisorAutoProxyCreator(可選)和AuthorizationAttributeSourceAdvisor)便可實現此功能
	@Bean(name = "advisorAutoProxyCreator")
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
	
	@Bean(name = "authorizationAttributeSourceAdvisor")
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }
 
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
 
        shiroFilterFactoryBean.getFilters().put("comauth", new ComAuthFilter());
 
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        shiroFilterFactoryBean.setLoginUrl("/");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/notlogin");
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        filterChainDefinitionMap.put("/", "user");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/", "anon");
        filterChainDefinitionMap.put("/**.html", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/login/checkcode", "anon");
        filterChainDefinitionMap.put("/login/notlogin", "anon");
        filterChainDefinitionMap.put("/export", "anon");
        filterChainDefinitionMap.put("/spiCalc", "anon");
        filterChainDefinitionMap.put("/hello/**", "anon"); //配置不控制權限請求 anon
        filterChainDefinitionMap.put("/hellox", "anon");
        filterChainDefinitionMap.put("/", "anon");
        filterChainDefinitionMap.put("/**", "comauth");
 
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
 
        return shiroFilterFactoryBean;
    }
 
    private Environment environment;
 
    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
8、Consul服務註冊與發現
/**
 * consul agent -server -bootstrap-expect=1  -data-dir=data -node=server0 -bind=127.0.0.1 -client 0.0.0.0 -ui
 * Created by windwant on 2016/8/18.
 */
@Component
public class ConsulMgr {
 
    private static final Logger logger = LoggerFactory.getLogger(ConsulMgr.class);
 
    @org.springframework.beans.factory.annotation.Value("${consul.host}")
    private String consulHost;
    @org.springframework.beans.factory.annotation.Value("${server.port}")
    private Integer port;
 
    @org.springframework.beans.factory.annotation.Value("${redis.host}")
    private String redisHost;
 
    @org.springframework.beans.factory.annotation.Value("${redis.port}")
    private Integer redisPort;
 
    private KeyValueClient keyValueClient;
    private HealthClient healthClient;
    private AgentClient agentClient;
    private CatalogClient catalogClient;
    private String redisService = "redis";
    private String bootService = "boot";
 
    public void init(){
        Consul consul = Consul.builder()
                .withConnectTimeoutMillis(3000)
                .withPing(true)
                .withReadTimeoutMillis(2000)
                .withWriteTimeoutMillis(2000)
                .withHostAndPort(HostAndPort.fromParts(consulHost, 8500)).build();
        keyValueClient = consul.keyValueClient();
        healthClient = consul.healthClient();
        agentClient = consul.agentClient();
 
        //註冊本服務到consul
        registerService(bootService, bootService, bootService, consulHost, port, 5);
 
        //註冊測試redis服務
        registerService(redisService, redisService, redisService, redisHost, redisPort, 5);
 
        //獲取可用redis服務
        getHealthService(redisService);
 
        //監控redis服務
        watchSvrx();
    }
 
    /**
     * 註冊服務
     */
    public void registerService(String svrId, String svrName, String tags, String host, Integer port, Integer interval){
        //健康檢查
        ImmutableRegCheck immutableRegCheck = ImmutableRegCheck.builder().tcp(host + ":" + port).interval(interval + "s").build();
        ImmutableRegistration immutableRegistration = ImmutableRegistration.builder().
                id(svrId).
                name(svrName).
                addTags(tags).
                address(host).
                port(port).
                addChecks(immutableRegCheck).
                build();
        agentClient.register(immutableRegistration);
    }
 
    /**
     * 獲取正常服務
     * @param serviceName
     */
    public void getHealthService(String serviceName){
        List<ServiceHealth> nodes = healthClient.getHealthyServiceInstances(serviceName).getResponse();
        dealHealthSvr(nodes);
    }
 
    private void dealHealthSvr(List<ServiceHealth> services){
        if(StringUtils.isNotBlank(JedisUtils.getHost()) && services.size() > 0) {
            services.forEach((resp) -> {
                if (StringUtils.equals(resp.getService().getAddress(), JedisUtils.getHost()) &&
                        resp.getService().getPort() == JedisUtils.getPort()) {
                    if(JedisUtils.getJedisPool().isClosed()){
                        JedisUtils.init(resp.getService().getAddress(), resp.getService().getPort());
                        return;
                    }
                    return;
                }
            });
        }
 
        if(StringUtils.isBlank(JedisUtils.getHost()) && services.size() > 0) {
            services.forEach((resp) -> {
                Service service = resp.getService();
                System.out.println("service port: " + service.getPort());
                System.out.println("service address: " + service.getAddress());
 
                //選取一個服務器初始化redis jedispool
                if (JedisUtils.init(service.getAddress(), service.getPort())) {
                    return;
                }
            });
        }
 
        if(JedisUtils.getJedisPool() != null) {
            //測試redis
            JedisUtils.set("test key", "test value");
            JedisUtils.get("test key");
            //測試redis分佈式鎖
            JedisUtils.setLockKey("test lock key", "test lock value", 3);
            JedisUtils.get("test lock key");
        }
    }
 
    //監控redis可用服務
    ScheduledExecutorService scheduled = Executors.newSingleThreadScheduledExecutor();
 
    public void watchSvrx(){
        scheduled.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                getHealthService(redisService);
            }
        }, 0, 10, TimeUnit.SECONDS);
    }
 
 
    public void watchSvr(){
        try {
            ServiceHealthCache serviceHealthCache = ServiceHealthCache
                    .newCache(healthClient, redisService);
            serviceHealthCache.addListener(map -> {
                logger.info("ServiceHealthCache change event");
                List<ServiceHealth> list = new ArrayList<ServiceHealth>();
                for (ServiceHealth serviceHealth : map.values()) {
                    list.add(serviceHealth);
                }
                ConsulMgr.this.dealHealthSvr(list);
            });
            serviceHealthCache.start();
        } catch (Exception e) {
            logger.info("ServiceHealthCache e: {}", e);
        }
    }
}
 
9、reids分佈式鎖
 
public class JedisUtils {
	private static final Logger logger = LoggerFactory.getLogger(JedisUtils.class);
 
	//設置鎖的lua腳本
	private static final String SETNX_EXPIRE_SCRIPT = "if redis.call('setnx', KEYS[1], KEYS[2]) == 1 then\n"
			+ "return redis.call('expire', KEYS[1], KEYS[3]);\n" + "end\n" + "return nil;";
 
	private static JedisPool jedisPool;
 
	public static JedisPool getJedisPool() {
		return jedisPool;
	}
 
	public static void setJedisPool(JedisPool jedisPool) {
		JedisUtils.jedisPool = jedisPool;
	}
 
	private static String host;
 
	private static Integer port;
 
	public static String getHost() {
		return host;
	}
 
	public static void setHost(String host) {
		JedisUtils.host = host;
	}
 
	public static Integer getPort() {
		return port;
	}
 
	public static void setPort(Integer port) {
		JedisUtils.port = port;
	}
 
	public static boolean init(String host, Integer port){
		try {
			JedisUtils.host = host;
			JedisUtils.port = port;
			jedisPool = new JedisPool(host, port);
			System.out.println(jedisPool);
			return true;
		}catch (Exception e){}
		return false;
	}
 
	public static boolean checkExist(String key) {
		if(jedisPool == null) return false;
		try (Jedis jedis = jedisPool.getResource()) {
			logger.info("get redis key record: {}", jedis.get(key));
			return jedis.exists(key);
		}catch (Exception e) {
			logger.warn("get redis key record failed , the message is " + e.getMessage());
		}
		return false;
	}
 
	public static void set(String key, String value) {
		if(jedisPool == null) return;
		try (Jedis jedis = jedisPool.getResource()) {
			logger.info("set key: {}, value: {}", key, value);
			jedis.set(key, value);
			jedis.expire(key, 20);
		}catch (Exception e) {
			logger.warn("set key failed , the message is " + e.getMessage());
		}
	}
 
	public static String get(String key) {
		if(jedisPool == null) return null;
		try (Jedis jedis = jedisPool.getResource()) {
			String value = jedis.get(key);
			logger.info("get key: {}, value: {}", key, value);
			return value;
		}catch (Exception e) {
			logger.warn("get key failed , the message is " + e.getMessage());
		}
		return null;
	}
 
	/**
	 * 設置鎖的lua腳本
	 * private static final String SETNX_EXPIRE_SCRIPT = "if redis.call('setnx', KEYS[1], KEYS[2]) == 1 then\n"
	 * "return redis.call('expire', KEYS[1], KEYS[3]);\n" + "end\n" + "return nil;";
	 *
	 * @param key
	 * @return
	 */
	public static boolean setLockKey(String key, String value, Integer seconds) {
		if (jedisPool == null) return false;
		try (Jedis jedis = jedisPool.getResource()) {
			if(jedis.eval(SETNX_EXPIRE_SCRIPT, 3, key, value, String.valueOf(seconds)) != null){
				logger.info("set lock key: {}, value: {}", key, value);
				return true;
			}
		}catch (Exception e) {
			logger.warn("set lock key failed , the message is " + e.getMessage());
		}
		return false;
	}
}
 
10、SPI機制

參考:Java SPI機制

 
11、static資源
 
配置個性化資源路徑:
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
 
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/uploadImg/**").addResourceLocations("file:/data/share/plane_images/");
        super.addResourceHandlers(registry);
    }
 
12、druid數據源
 
package org.windwant.spring.config;
 
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.support.spring.stat.BeanTypeAutoProxyCreator;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.windwant.spring.service.BootService;
 
import java.util.Arrays;
 
/**
 * Created by Administrator on 2018/2/6.
 */
@Configuration
public class DruidConfig {
 
    /**
     * 註冊 StatViewServlet druid web頁面使用
     * @return
     */
    @Bean
    public ServletRegistrationBean druidServlet() {
        ServletRegistrationBean reg = new ServletRegistrationBean();
        reg.setServlet(new StatViewServlet());
        reg.addUrlMappings("/druid/*");
        return reg;
    }
 
    @Bean
    public FilterRegistrationBean druidWebStatFilter(){
        FilterRegistrationBean reg = new FilterRegistrationBean();
        reg.setFilter(new WebStatFilter());
        reg.setUrlPatterns(Arrays.asList("/*"));
        reg.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        reg.addInitParameter("sessionStatMaxCount", "1000");
        reg.addInitParameter("sessionStatEnable", "true");
        reg.addInitParameter("principalSessionName", "druid.user");
        reg.addInitParameter("profileEnable", "true");
        return reg;
    }
 
    /**
     * Spring和Jdbc的關聯監控。
     * DruidStatInterceptor:標準的Spring MethodInterceptor。能夠靈活進行AOP配置
     * Advice
     * @return
     */
    @Bean
    public DruidStatInterceptor interceptorNames(){
        DruidStatInterceptor inc = new DruidStatInterceptor();
        return inc;
    }
 
    //=====================按類型攔截 配置Spring監控============================================
    /**
     * 按類型攔截配置
     * @return
     */
    @Bean
    public BeanTypeAutoProxyCreator beanTypeAutoProxyCreator(){
        BeanTypeAutoProxyCreator cut = new BeanTypeAutoProxyCreator();
        cut.setTargetBeanType(BootService.class);
        cut.setInterceptorNames("interceptorNames");
        return cut;
    }
 
    //=====================按方法名正則匹配攔截 配置Spring監控====================================
 
    /**
     * pointcut
     * @return
     */
    @Bean
    public JdkRegexpMethodPointcut jdkRegexpMethodPointcut(){
        JdkRegexpMethodPointcut cut = new JdkRegexpMethodPointcut();
        cut.setPatterns("org.windwant.spring.mapper.*");
        return cut;
    }
 
    /**
     * Advisor
     * @param pointcut
     * @param interceptor
     * @return
     */
    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor(JdkRegexpMethodPointcut pointcut, DruidStatInterceptor interceptor){
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setPointcut(pointcut);
        advisor.setAdvice(interceptor);
        return advisor;
    }
 
    /**
     * AOP proxy based on beans in Spring
     * @return
     */
    @Bean
    public ProxyFactoryBean proxyFactoryBean(){
        ProxyFactoryBean proxy = new ProxyFactoryBean();
        proxy.setInterceptorNames("defaultPointcutAdvisor");
        return proxy;
    }
}

十3、dubbo rpc

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:property-placeholder location="classpath:application.yml"/>
 
    <dubbo:application name="${dubbo.application.name}" owner="boot-server"
                       organization="windwant"/>
 
    <dubbo:registry id="bootRegistry" address="${dubbo.registry.address}"/>
 
    <dubbo:protocol port="${dubbo.protocal.port}" serialization="${dubbo.protocal.serialization}"
                    dispatcher="all" optimizer="org.windwant.common.api.SerializationOptimizerImpl"
                    threadpool="cached" threads="${dubbo.provider.threads}"/>
 
    <dubbo:protocol id="publicApi" port="${dubbo.protocal.port}" serialization="${dubbo.protocal.serialization}"
                    dispatcher="all" threadpool="cached" threads="${dubbo.provider.threads}"/>
 
    <dubbo:provider timeout="${dubbo.provider.timeout}" filter="dubboCatFilter"
                    proxy="${dubbo.provider.proxy}" retries="${dubbo.provider.retries}"/>
 
    <dubbo:service interface="org.windwant.common.api.DubboService" ref="dubbosvr"
                   registry="bootRegistry"/>
</beans>

。。。

 

    Spring Boot 官網:https://projects.spring.io/spring-boot/

相關文章
相關標籤/搜索