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方法。
@Configurationpublic class ApplicationConfig { @Configuration public class WebMvcConfigurer extends WebMvcConfigurerAdapter { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new BootInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry); }...3. listenenr:实现各种listener@WebListenerpublic 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: trueDataSource 注解配置:
/** * Created by windwant on 2016/12/30. * implements EnvironmentAware, ApplicationContextAware */@Configurationpublic 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配置:
@Beanpublic 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 @Componentpublic 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验证提示信息:@Beanpublic 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 addCorsMappingsaddMapping:请求拦截allowedOrigins:拦截请求源allowedMethods:拦截方法@Configurationpublic 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权限配置@Configurationpublic 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. */@Componentpublic 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资源配置个性化资源路径:@Configurationpublic 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. */@Configurationpublic 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; }}十三、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/