Spring Boot 基于注解式开发 maven REST 示例项目

   项目地址:https://github.com/windwant/spring-boot-service

   项目地址:https://github.com/windwant/spring-dubbo-service

项目特色:

1.  servlet、listener、interceptor、filter配置

2.  mybatis配置集成,多数据源 RouingDataSource

3.  集成jmx监控 MBean

4.  定时任务配置 Scheduled

5.  aop配置

6.  ftp服务 FTPTranport

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 服务

一、 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 {
...

二、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;
}
 

三、集成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;
    }
}
八、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);
        }
    }
}
 
九、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;
	}
}
 
十、SPI机制

参考:Java SPI机制

 
十一、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);
    }
 
十二、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", "");
        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;
    }
}

十三、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/

Spring Boot 示例项目的更多相关文章

  1. 有哪些值得学习的spring boot开源项目?

    1. awesome-spring-boot 首先给大家介绍的就是Spring Boot 中文索引,这是一个专门收集 Spring Boot 相关资料的开源项目,也有对应的导航页面. 产品主页 htt ...

  2. Spring Boot 商城项目

    Spring Boot 商城项目 angularJS Demo1 <html> <head> <title>angularJS Demo1</title> ...

  3. SpringCloud 微服务一:spring boot 基础项目搭建

    spring cloud是建立在spring boot的基础上的,而之前虽然听说过,也随便看了一下spring boot,却没有真正使用,因此还必须先花时间学一下spring boot. spring ...

  4. 15 个优秀开源的 Spring Boot 学习项目,一网打尽!

    Spring Boot 算是目前 Java 领域最火的技术栈了,松哥年初出版的 <Spring Boot + Vue 全栈开发实战>迄今为止已经加印了 8 次,Spring Boot 的受 ...

  5. Spring boot Gradle项目搭建

    Spring boot Gradle项目搭建 使用IDEA创建Gradle工程     操作大致为:File->new->Project->Gradle(在左侧选项栏中)     创 ...

  6. 【spring】1.2、Spring Boot创建项目

    Spring Boot创建项目 在1.1中,我们通过"Spring Starter Project"来创建了一个项目,实际上是使用了Pivotal团队提供的全新框架Spring B ...

  7. 15 个优秀开源的 Spring Boot 学习项目

    Spring Boot 算是目前 Java 领域最火的技术栈了,松哥年初出版的 <Spring Boot + Vue 全栈开发实战>迄今为止已经加印了 8 次,Spring Boot 的受 ...

  8. 最近做的一个Spring Boot小项目,欢迎大家访问 http://39.97.115.152/

    最近做的一个Spring Boot小项目,欢迎大家访问 http://39.97.115.152/,帮忙找找bug,网站里有源码地址 网站说明 甲壳虫社区(Beetle Community) 一个开源 ...

  9. 1.spring boot初始化项目

    初始化spring boot项目的方式非常多,如使用Spring Tool Suite.使用IntelliJ IDEA.使用NetBeans.在start.spring.io网站中.curl命令.sp ...

随机推荐

  1. STS使用git下载项目代码

    在自己的eclipse 上安装git 插件,一般都自带了现在. 4.选择Clone URI 5.下一步输入刚才的复制的路劲,填写自己的github 账户名密码即可 6.选择要克隆的分支 7.设置本地g ...

  2. DBUtils连接池,websocket

    1.mysql数据库连接池 概念:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放. 这样 ...

  3. python3爬虫编码问题

    使用爬虫爬取网页经常遇到各种编码问题,因此产生乱码今天折腾了一天,全部总结一遍环境:win10,pycharm,python3.41.首先先来网页编码是utf-8的:以百度首页为例:使用request ...

  4. js中两个日期大小比较,获取当前日期,日期加减一天

    一.两个日期大小比较 1.日期参数格式:yyyy-mm-dd // a: 日期a, b: 日期b, flag: 返回的结果 function duibi(a, b,flag) { var arr = ...

  5. 一个 Safari 的 new Date() bug

    开发「bufpay.com 个人即时到账收款平台」后台套餐修改功能的时候碰到一个 new Date() bug. 既在 Safari 里面不支持 var t = new Date('2018-06-1 ...

  6. MySQL学习【第三篇用户管理】

    一.用户管理 1.给mysql用户设密码以及删除用户 1.给mysql的root用户设置密码 [root@db02 scripts]# mysqladmin -uroot -p password '1 ...

  7. MySQL学习之事务安全

    事务安全 事务概念 事务(transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit),事务通常由高级数据操纵语言或编程语言 书写的用户程序的执行所引起.事务有事务开始(b ...

  8. dmesg功能介绍

    dmesg 命令的使用范例 ‘dmesg’命令设备故障的诊断是非常重要的.在‘dmesg’命令的帮助下进行硬件的连接或断开连接操作时,我们可以看到硬件的检测或者断开连接的信息.‘dmesg’命令在多数 ...

  9. URL参数获取/转码

    JS中对URL进行转码与解码 1.escape 和 unescape escape()不能直接用于URL编码,它的真正作用是返回一个字符的Unicode编码值. 采用unicode字符集对指定的字符串 ...

  10. linux系统快速安装宝塔

    宝塔面板分linux面板和windows面板,安装宝塔linux面板首先要访问宝塔官网查看对应版本进行选择 宝塔面板的安装需要注意的地方有: 1.纯净系统 2.确保是干净的操作系统,没有安装过其它环境 ...