• 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
    "
    
    			+ "return redis.call('expire', KEYS[1], KEYS[3]);
    " + "end
    " + "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
    "
    
    	 * "return redis.call('expire', KEYS[1], KEYS[3]);
    " + "end
    " + "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/

  • 相关阅读:
    F版本SpringCloud1—大白话为啥要有微服务?啥是微服务?SpringCloud为什么有那么多组件?
    Java已五年1—二本物理到前端实习生到Java程序员「回忆贴」
    SpringBoot图文教程17—上手就会 RestTemplate 使用指南「Get Post」「设置请求头」
    SpringBoot图文教程15—项目异常怎么办?「跳转404错误页面」「全局异常捕获」
    SpringBoot图文教程14—SpringBoot集成EasyExcel「上」
    SpringBoot图文教程12—SpringData Jpa的基本使用
    SpringBoot图文教程11—从此不写mapper文件「SpringBoot集成MybatisPlus」
    SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」
    SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」
    SpringBoot图文教程8 — SpringBoot集成MBG「代码生成器」
  • 原文地址:https://www.cnblogs.com/niejunlei/p/5980544.html
Copyright © 2020-2023  润新知