Spring Boot 示例项目
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", "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/