springboot 项目开发说明

一、前言

    次说明参照新的项目体系结构编写,具体哪些是新的项目体系,请参照:项目统计

    随着我们对技术的不断深入,项目结构配置也会趋于更加透明简洁,所以项目体系会不断的更新,如有问题请咨询架构组

    截至目前,本文采用的Nove版本为1.2.9.RELEASE

    注意:API包除了依赖ecej-model 尽量不要依赖其他任何自定义包,否则以后发布公共接口可能导致各种奇葩问题

模板工程:http://10.4.96.22/luqiang/ecej-xxx/

二、应用技术说明

新的项目体系主要采用spring boot 、mybatis 、druid 、dubbo 

 

三、项目结构说明

下面说下基本项目结构,先看下新结构包含什么,以用户中心为例

新的项目结构摒弃了老结构中的dao 、po 等jar依赖

dao的东西经过配置化管理,只剩下了UcBaseDao 和 DBConfiguration(包括了数据源等配置,大家可以依葫芦画瓢自己试试)

po的东西以后放到自己的api中,记住api包不允许依赖任何jar包,以免出现恶心自己的问题

父POM中删除了无用的依赖,继承了底层平台POM

 

下面说下核心的数据源配置DBConfiguration

这个继承了AbstractDruidDBConfig 其实内部就是帮助大家加载了下数据源,方便配置而已

这是我们需要配置的属性,配置在remote-db.properties中

这就是我们的数据源声明

 

事物的声明,其实大家会发现只是换了个形式写而已,省去了xml配置

 

 

 

 

 

四、Redis的使用

说下redis使用,如果想在自己的项目中使用redis,如下先加入依赖

<dependency>

          <groupId>com.nove</groupId>

          <artifactId>ecej-redis</artifactId>

</dependency>

就可以了,然后我们只要配置我们的配置文件,不需要其他多余的工作

redis集群分为两种,sentinel 还有3.x的cluster,根据你自己的需要选择集群配置,配置文件都放在resources下面的,没有特殊要求的话请都使用3.x配置

1、先说sentinel配置

用法:使用com.ecej.nove.redis.utils.JedisClusterUtils这个静态类

remote-redis.properties

这个大家可以直接下载用

ecej.redis.hostName=@ecej.redis.hostName@

ecej.redis.password=@ecej.redis.password@

ecej.redis.mastername=@ecej.redis.mastername@

以下配置可选择增加

ecej.redis.maxIdle=@ecej.redis.maxIdle@

ecej.redis.maxTotal=@ecej.redis.maxTotal@

ecej.redis.maxWaitMillis=@ecej.redis.maxWaitMillis@

 

这是properties的配置

下面说下POM里面profile的配置

<ecej.redis.hostName>10.32.32.58:26379,10.32.32.58:26380,10.32.32.58:26381</ecej.redis.hostName>
<ecej.redis.mastername>redismaster</ecej.redis.mastername>
<ecej.redis.password><![CDATA[4BZcIv&9]]></ecej.redis.password>
<ecej.redis.maxIdle>10</ecej.redis.maxIdle>
<ecej.redis.maxTotal>1000</ecej.redis.maxTotal>
<ecej.redis.maxWaitMillis>3000</ecej.redis.maxWaitMillis>

 

2、下面再说下3.x的配置

remote-redis.properties

ecej.redis.password=@ecej.redis.password@

ecej.redis.hostName=@ecej.redis.hostName@

以下配置可选择增加

ecej.redis.maxIdle=@ecej.redis.maxIdle@

ecej.redis.maxTotal=@ecej.redis.maxTotal@

ecej.redis.maxWaitMillis=@ecej.redis.maxWaitMillis@

ecej.redis.maxRedirects=@ecej.redis.maxRedirects@

 

下面贴出profile的配置

<ecej.redis.hostName>10.4.89.161:6379</ecej.redis.hostName>
<ecej.redis.maxRedirects>10</ecej.redis.maxRedirects>
<ecej.redis.password></ecej.redis.password>
<ecej.redis.maxIdle>10</ecej.redis.maxIdle>
<ecej.redis.maxTotal>1000</ecej.redis.maxTotal>
<ecej.redis.maxWaitMillis>3000</ecej.redis.maxWaitMillis>

两种配置都有了,那下面说下怎么选择用哪种集群模式

ecej.redis.cluster=true  使用3.x模式

ecej.redis.sentinel=true 使用sentinel模式

注意:这俩配置选一个,放在application.properties中,不要乱放。

 

最后一步,配置文件读取

在PropertiesConfig中

 

package  com.ecej.nove.sms.config;
import  org.springframework.context.annotation.Configuration;
import  org.springframework.context.annotation.ImportResource;
import  org.springframework.context.annotation.PropertySource;
import  com.ecej.nove.base.config.AbstractPropertiesConfig;
@Configuration
@PropertySource (value = {  "classpath:remote-db.properties" "classpath:remote-dubbo.properties" , "classpath:remote-redis.properties"  }) //在这里加入redis配置读取
@ImportResource ({  "classpath:dubbo/*.xml"  })
public  class  PropertiesConfig  extends  AbstractPropertiesConfig {
}

 

3.Key的命名规范

应用名称
key定义
说明
公共COMM_XXX 
运营ADMIN_XXX 
用户CUST_XXX 
员工 EMP_XXX  
     
     

 

五、RabbitMQ 使用

RabbitMQ 使用说明

首先加入依赖

<dependency>
    <groupId>com.nove</groupId>
    <artifactId>ecej-rabbitmq</artifactId>
</dependency>

编写配置文件到application.properties 

spring.rabbitmq.addresses=@ecej.rabbitmq.addresses@

注意:有密码就加下面的配置,没有千万不要加(正常都应该有密码,没密码找运维)

spring.rabbitmq.username=@ecej.rabbitmq.username@
spring.rabbitmq.password=@ecej.rabbitmq.password@

下面贴出profile

<!-- Rabbit MQ -->
<ecej.rabbitmq.addresses>10.32.32.35:5672,10.32.32.37:5672,10.32.32.40:5672</ecej.rabbitmq.addresses>

<ecej.rabbitmq.username>ecej</ecej.rabbitmq.username>
<ecej.rabbitmq.password>ecej</ecej.rabbitmq.password>

 

配置队列

package  com.ecej.nove.sms.config;
import  org.springframework.amqp.core.Queue;
import  org.springframework.context.annotation.Bean;
import  org.springframework.context.annotation.Configuration;
@Configuration
public  class  RabbitMQConfig {
     @Bean
     public  Queue mailQueue() {
         return  new  Queue( "ecejmail" );
     }
     @Bean
     public  Queue smsQueue() {
         return  new  Queue( "ecejsms" );
     }
     @Bean
     public  Queue jpushQueue() {
         return  new  Queue( "ecejjpush" );
     }
}

 

 

发送消息

 


  package  com.ecej.nove.test.sms;
import  java.util.Date;
import  javax.annotation.Resource;
import  org.junit.Test;
import  org.springframework.amqp.rabbit.core.RabbitTemplate;
import  org.springframework.stereotype.Component;
import  com.ecej.nove.base.mail.BaseMail;
@Component
public  class  SendMailTest {
     @Resource
     private  RabbitTemplate rabbitTemplate;
     @Test
     public  void  sendMQ() {
         BaseMail baseMail =  new  BaseMail();
         baseMail.setTo( new  String[] {  "598505651@qq.com"  });
         baseMail.setSubject( "这是一个神奇的网站" );
         baseMail.setText( "这是一个一格" );
         baseMail.setCc( new  String[] {  "35329425@qq.com"  });
         rabbitTemplate.convertAndSend( "ecejmail" , baseMail);
         System.out.println( "Sender : "  + baseMail.getText());
         String context =  "baseMail.getText() "  new  Date();
         rabbitTemplate.convertAndSend( "ecejmail" , context);
     }
}


 

接收消息

 

package  com.ecej.nove.sms.mail;
import  javax.annotation.Resource;
import  org.apache.commons.collections.MapUtils;
import  org.slf4j.Logger;
import  org.slf4j.LoggerFactory;
import  org.springframework.amqp.rabbit.annotation.RabbitHandler;
import  org.springframework.amqp.rabbit.annotation.RabbitListener;
import  org.springframework.beans.factory.annotation.Value;
import  org.springframework.stereotype.Component;
import  com.ecej.nove.base.mail.BaseMail;
import  com.ecej.nove.sms.service.api.MailSendService;
/**
  * 接收邮件信息
  *
  * @author QIANG
  *
  */
@Component
@RabbitListener (queues =  "ecejmail" )
public  class  MailReceiverService {
 
     @Resource
     private  MailSendService mailSendService;
 
     @RabbitHandler
     public  void  ReceiverMessage(BaseMail mail) {
     }
 
     @RabbitHandler
     public  void  ReceiverMessage(String mail) {
         System.out.println(mail);
     }
}

 

六、druid的监控

因为我们现在都有druid,所以有配套的数据源监控

监控地址

http://localhost:8080/druid/index.html

用户名密码 默认 admin

 

七、spring sts插件

这个就大家按喜好安装吧,主要为了方便我们开发,IDEA直接支持了boot,eclipse得我们自己弄个插件,所以这玩意就是了。

有什么好处呢?

可以在properties中提示,当然,只有在application.properties中可以提示,还有各种别的用法我就不一一说了

 


安装方法

Help -》  install new software  

然后下一步下一步就行了,这个安装包地址https://spring.io/tools/sts/all


八、应用监控

spring boot给我们提供了很多监控,什么bean的啊,状态啊等等,回头我有空写几个介绍在这

1.应用异常信息推送.

通用服务AOP切面会统一处理系统异常,异常捕获后会直接发起一个独立的线程像收集服务器发送数据.

项目配置.properties中增加如下配置

 ecej-core 1.2.0+版本配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#项目名称
spring.application.name=ecej-xx
#数据处理服务地址
ecej.ops.url=exwarn.ecej.com
#数据处理服务端口
ecej.ops.port= 80
#可选择配置
#连接超时
ecej.ops.connect.timeout= 2000
#读超时
ecej.ops.read.timeout= 3000
#是否推送, 0 -否, 1 -是,默认是 0
ecej.ops.iswitch= 1
 

九、部署

部署命令

nohup java -jar -Xms2048m -Xmx2048m -Xmn512m -Xss256k -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heapdump.hprof    xxx.jar  --server.port=8080 --log.home=/xxx/ --log.level=INFO --log.stdout=0 –ecej.ops.iswitch=1 --ecej.ops.port=80 --jmx.rmi.port=9999 &


server.port:内置tomcat端口,默认8999

jmx.rmi.port:JMX监控端口,默认9999

log.home:日志存放目录地址,默认为/data/dubbo/logs/应用名称

log.level:日志级别,默认DEBUG

log.stdout:是否输出日志到控制台,默认输出, "0"为不输出

ecej.ops.iswitch:是否开启异常推送

ecej.ops.port:异常推送服务端口

dubbo.port=默认分配,(如同一台部署多份请在默认端口值上加100以免重复)

server.context-path 项目访问路径(默认是,这样直接通过http://ip:port/就可以访问到index页面,如果要修改为http://ip:port/path/ 访问的话,那么需要在Application.properties文件中加入server.context-path = /你的path

 

 

十、单元测试

package  com.ecej.uc.test.base;
import  com.ecej.uc.run.Startup;
import  org.junit.After;
import  org.junit.Before;
import  org.junit.runner.RunWith;
import  org.springframework.boot.test.context.SpringBootTest;
import  org.springframework.test.context.junit4.SpringRunner;
/**
  * Created by mijp on 2017/1/11.
  */
@RunWith (SpringRunner. class )
@SpringBootTest (classes = Startup. class )
public  class  UcBaseTest {
 
     @Before
     public  void  before() {
         System.out.println( "测试开始>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" );
     }
     @After
     public  void  after() {
         System.out.println( "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<测试完成" );
     }
}

继承上边的类即可

十一、异常处理

1.基本异常处理流程

异常处理

总体原则说明,controller层服务调用必须有try{}catch处理,不能在向上抛.已经是顶层了.可以通过AOP切面统一处理.如果当前web服务返回包含数据返回(JSON)和页面返回,可以分为两个package,设置两个切面分别处理

案例1:controller处理异常方法. 使用AOP拦截器对异常统一处理,保证有一个合适的返回值

controller 不建议有业务处理流程,包括返回值的额外处理流程,所以只处理返回信息即可.

AOP simple

controllerAOP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import  org.aspectj.lang.JoinPoint;
import  org.aspectj.lang.annotation.AfterReturning;
import  org.aspectj.lang.annotation.AfterThrowing;
import  org.aspectj.lang.annotation.Aspect;
import  org.aspectj.lang.annotation.Before;
import  org.aspectj.lang.annotation.Pointcut;
import  org.slf4j.Logger;
import  org.slf4j.LoggerFactory;
import  org.slf4j.MDC;
import  org.springframework.stereotype.Component;
import  com.ecej.nove.utils.lang.UUIDUtils;
 
/**
 *
 * @author QIANG
 *
 */
@Component
@Aspect
public  class  NoveControllerInterceptor {
     private  Logger logger = LoggerFactory.getLogger(NoveControllerInterceptor. class );
     /**
     * @Description 指定切入点匹配表达式,注意它是以方法的形式进行声明的。 即切点集合是:com.ecej包下所有类所有方法
     *              如果要设置多个切点可以使用 || 拼接
     */
     @Pointcut ( "execution(* com..controller..*(..)) " )
     public  void  anyMethod() {
         // 切点使用与任何方法
    }
     /**
     * @Description 前置通知 在切点方法集合执行前,执行前置通知
     * @param jp
     * @throws Exception
     */
     @Before (value =  "anyMethod()" )
     public  void  doBefore(JoinPoint jp)  throws  Exception {
         if  (MDC.get( "requestId" ) ==  null ) {
            String id = UUIDUtils.randomUUID().toString();
             /*如果没有reguestId就重新生成一个,这种情况可能会发生漏传的情况,需要在开始就要控制好*/
            MDC.put( "requestId" , id); //
            logger.debug( "新请求生成请求唯一ID:[{}]" , id);
        }
    }
 
     /**
     * @Description 后置通知
     * @param jp
     * @param result
     */
     @AfterReturning (value =  "anyMethod()" , returning =  "result" )
     public  void  doAfter(JoinPoint jp, Object result) {
    }
 
     /**
     * @Description 环绕通知( ##环绕通知的方法中一定要有ProceedingJoinPoint 参数,与
     *              Filter中的doFilter方法类似) 异常统一捕获
     * @param pjp
     * @return
     * @throws Throwable
     */
     @SuppressWarnings ( "unchecked" )
     @Around (value =  "anyMethod()" )
     public  Object doAround(ProceedingJoinPoint pjp)  throws  Throwable {
        logger.debug( "Controller拦截器开始---->" );
       
        ResultModel<T> result =  new  ResultModel<>();
         try  {
            Object r = pjp.proceed();
             if  (r  instanceof  ResultModel<?>) {
                result = (ResultModel<T>) r;
         /*断言打断方法,里面自动判断返回值如果非000000,就抛业务异常NoveServiceException*/
                 //AssertUtil.noServiceException(result);
            }  else  {
                 return  r;
            }
        }  catch  (Exception e) {
             if  (e  instanceof  NoveServiceException) {
                /*如果是业务异常的处理*/
            }  else  if  (e  instanceof  NoveSystemException) {
                /*如果是系统异常的处理*/
            }  else  {
                 /*未知异常的处理*/
            }
        }
        logger.debug( "Controller拦截器,服务结束---->" );
         return  result;
    }
     /**
     * @Description 异常通知
     * @param jp
     */
     @AfterThrowing (value =  "anyMethod()" )
     public  void  doThrow(JoinPoint jp) {
    }
}


案例二:service编写异常使用

1.nove有内置的全局service AOP异常处理, 异常最终会分为两类, NoveServiceException(主动打断,可控异常),NoveSystemException(系统异常,非可控异常)

主动打断业务代码写法

s = testInterface.executeTest(name);
 
if (s ==  null ){
     throw  new  NoveServiceException(code, message);
}

公共AOP处理流程

如果是未知异常会有消息推送报警, 并封装为NoveSystemException

AssertUtil.noServiceException(result); 会判断如果返回码不是"000000",就会打断程序, 实现服务节点逐级打断. 

 

2.如果有特殊要求建议处理返回值,建议处理方式

业务代码编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public  String executeTest(String name)  throws  Exception {
         log.info( "服务1111111111提供的内容,测试内容:[{}]" , name);
         String s =  "" ;
         try  {
             s = testInterface.executeTest(name);
         catch  (Exception e) {
             if  (e  instanceof  NoveServiceException) {
                 NoveServiceException ne = ((NoveServiceException) e);
                 String errorCode = ne.getErrorCode();
                 /*处理逻辑*/
             else  {
                 throw  e;
             }
         }
         return  s;
     }

 


响应码设计

响应码设计

 

 

十二、拦截器

拦截器可以简单的分为两种,一种是web的拦截器,一种是我们拦截service之类的,下面先说下web拦截器

上代码:

 

package  com.ecej.nove.sms.config;
import  org.springframework.context.annotation.Configuration;
import  org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import  com.ecej.nove.base.config.AbstractConfigurerAdapter;
import  com.ecej.nove.sms.interceptor.DemoInterceptor;
@Configuration
public  class  WebConfigurerConfig  extends  AbstractConfigurerAdapter {
     @Override
     public  void  addInterceptors(InterceptorRegistry registry) {
         registry.addInterceptor( new  DemoInterceptor()).addPathPatterns( "/**" );
     }
}

addPathPatterns方法参数是 String... patterns ,so你们懂得

上边是添加一个拦截器的方法,下面说下怎么定义一个拦截器

package  com.ecej.nove.sms.interceptor;
import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;
import  org.springframework.web.servlet.ModelAndView;
import  org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public  class  DemoInterceptor  extends  HandlerInterceptorAdapter {
     @Override
     public  boolean  preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
             throws  Exception {
         System.out.println( ">>>MyInterceptor>>>>>>>在请求处理之前进行调用(Controller方法调用之前)" );
         return  true ; // 只有返回true才会继续向下执行,返回false取消当前请求
     }
     @Override
     public  void  postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
             ModelAndView modelAndView)  throws  Exception {
         System.out.println( ">>>MyInterceptor>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)" );
     }
     @Override
     public  void  afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
             throws  Exception {
         System.out.println( ">>>MyInterceptor>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)" );
     }
}

上边拦截器继承了HandlerInterceptorAdapter 所以想拦截哪部分就选择哪个方法,不用的可以不重写

 

十三、配置属性读取

1、下面是直接使用spring提供的注解进行读取,不需要额外的配置,直接用

@Value(“${test.name}”)

 Private String name;

2、使用nove内置方法读取

如果需要从内存中读取属性,请使用以下方法

com.ecej.nove.utils.common.PropertyConfigUtils

PropertyConfigUtils.getProperty(key)

PropertyConfigUtils.getProperty(key,defValue)

十四、静态资源处理

有时候也需要用到前端页面,当然就不可或缺地需要访问其他一些静态资源,比如图片、css、js等文件。那么如何设置Spring Boot网站可以访问得到这些静态资源,以及静态资源如何布局?

项目默认的路径如下:/META-INF/resources/,/resources/,/static/,/public/,比如静态文件放到如下路径就可以访问了。

src/main/resource

          |_____static

                        |____js

                        |____images

                        |____css

例如,imges目录下的demo.jpg 在HTML/JSP中访问是的路径就是<img src="/images/demo.jpg">, 因为Spring Boot的缺省工作目录就是src/main/java, 当访问资源时,就是src/main/resources, 而/static/**被SPRING BOOT被映射到了classpath:/static下。所以也可以不带起始的“/”,直接写成<img src="images/demo.jpg">。

 以下代码示例为Hello World 加了个图片显示, 这里的demo.jpg在maven工程的位置存放就是src/main/resource/static/images/demo.jpg,

可用<img src="image/demo.jpg">访问。

import  org.springframework.stereotype.Controller;
import  org.springframework.web.bind.annotation.RequestMapping;
import  org.springframework.web.bind.annotation.ResponseBody;
 
@Controller
 
public  class  HelloController {
     @RequestMapping ( "/" )
     @ResponseBody
     public  String hello() {
         return  "hello world <img src=\"images/demo.jpg\">" ;
     }
}

添加自定义资源路径:

直接上代码

import  org.springframework.context.annotation.Configuration;
import  org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import  org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 
@Configuration
public  class  MyWebAppConfig  extends  WebMvcConfigurerAdapter {
     @Override
     public  void  addResourceHandlers(ResourceHandlerRegistry registry) {
         registry.addResourceHandler( "/myResource/**" ).addResourceLocations( "classpath:/myResource/" );
         super .addResourceHandlers(registry);
     }
}

这里添加了一个新位置:

src/main/resource 
          |____myResource

如果newDemo.jpg放在src/main/resource/myResource/images/newDemo.jpg,那么就可用<img src="myResource/images/newDemo.jpg">访问了。 


十五、事物机制

在需要使用事物的方法上加@Transactional ,详细资料可自行查询

多数据源事物应用:@Transactional(transactionManager="xxx")

注意在单独使用不带任何参数的 @Transactional 注释时,传播模式要设置为 REQUIRED,只读标志设置为 false,事务隔离级别设置为 READ_COMMITTED,而且事务不会针对受控异常(checked exception)回滚


十六、数据源

多数据源配置请咨询架构组

下面给出druid可定制化配置选项,此选项在启动时有默认值,各个项目组可根据需求选择添加

#druid config
druid.initialSize= 10
druid.maxActive= 300
druid.minIdle= 50
druid.maxWait= 60000
druid.timeBetweenEvictionRunsMillis= 60000
druid.minEvictableIdleTimeMillis= 3600000
druid.validationQuery= "SELECT USER()"
druid.testWhileIdle= true
druid.testOnBorrow= false
druid.testOnReturn= false
druid.filters= "mergeStat,config,wall"
druid.connectionProperties=
#Monit
druid.monit.allow=
druid.monit.deny=
druid.monit.username=admin
druid.monit.password=admin

 

十七 、版本管理

项目版本管理 

十八、发送短信 | 邮件 | JPUSH

FSDX-发送短信

FSYJ-发送邮件

JPUSH-极光推送


十九、全局异常拦截

 

package  com.ecej.ordercenter.exception;
import  javax.servlet.http.HttpServletRequest;
import  org.slf4j.Logger;
import  org.slf4j.LoggerFactory;
import  org.springframework.web.bind.annotation.ControllerAdvice;
import  org.springframework.web.bind.annotation.ExceptionHandler;
import  org.springframework.web.bind.annotation.ResponseBody;
import  org.springframework.web.servlet.ModelAndView;
import  com.ecej.ordercenter.api.enums.ActionResultEnum;
import  com.ecej.ordercenter.utils.MessageUtil;
@ControllerAdvice
public  class  GlobalExceptionHandler {
     private  static  final  Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler. class );
     @ExceptionHandler (value = Exception. class )
     @ResponseBody
     public  ModelAndView resolveException(HttpServletRequest request, Exception ex) {
         logger.error( "ExceptionHandler异常" , ex);
         return  MessageUtil.makeModel(ActionResultEnum.INTERNAL_ERROR.getCode(),
                 ActionResultEnum.INTERNAL_ERROR.getDesc());
     }
}
 
 

二十、JMX监控

默认地址为部署机

默认监控端口为9999

具体参数可在部署时动态更改,详情参照第九章部署


二十一、定时任务

定时任务采用注解的模式使用

1、增加开启定时任务配置

package  com.ecej.meterread.task.base.config;
import  org.springframework.context.annotation.Configuration;
import  org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@EnableScheduling
public  class  SchedulConfig {
}

2、编写定时任务业务

package  com.ecej.meterread.task.base.run;
import  org.springframework.scheduling.annotation.Scheduled;
import  org.springframework.stereotype.Service;
@Service
public  class  Test {
     @Scheduled (fixedRate =  50000 )
     public  void  testSchedul() {
         System.out.println( "Test Schedul ..." );
     }
}

二十二、SESSION 共享

目前项目有两种模式,一种springboot配置,一种传统xml,所以对于session共享的配置方式也给出两种,可自行优化

1、spring boot方式

目前使用spring-session redis 实现session共享问题

1、添加依赖

 

<dependency> 
<groupId>org.springframework.session</groupId> 
<artifactId>spring-session-data-redis</artifactId> 
</dependency>

2、添加 RedisSessionConfig

package  com.ecej.uc.config;
import  org.springframework.context.annotation.Configuration;
import  org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@Configuration
@EnableRedisHttpSession (maxInactiveIntervalInSeconds= 1800 ) //默认超时时间1800S
public  class  RedisSessionConfig {
}

 

注意:因为共享session需要redis支持,请参考redis章节进行redis配置

2、传统spring xml配置

1、首先配置jar依赖

 

<!-- Spring Session -->
<dependency>
     <groupId>org.springframework.session</groupId>
     <artifactId>spring-session</artifactId>
     <version> 1.3 . 0 .RELEASE</version>
</dependency>
<dependency>
     <groupId>org.springframework.data</groupId>
     <artifactId>spring-data-redis</artifactId>
</dependency>

 

2、在web.xml添加过滤器

<filter>
         <filter-name>springSessionRepositoryFilter</filter-name>
         <filter- class >org.springframework.web.filter.DelegatingFilterProxy</filter- class >
     </filter>
     <filter-mapping>
         <filter-name>springSessionRepositoryFilter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>

3、添加spring xml配置文件(有兴趣可以自行转换成config,这里写成xml为了保持一致性,方便未来替换)

<!-- session共享配置 -->
    <bean  class = "org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" />
    <!-- spring redis -->
    <bean id= "jedisPoolConfig"  class = "redis.clients.jedis.JedisPoolConfig" >
        <property name= "maxIdle"  value= "10" />
        <property name= "maxTotal"  value= "500" />
        <property name= "maxWaitMillis"  value= "3000" />
    </bean>
    <bean id= "node"  class = "org.springframework.data.redis.connection.RedisNode" >
        <constructor-arg name= "host"  value= "${ecej.session.redis.ip}" />
        <constructor-arg name= "port"  value= "${ecej.session.redis.port}" />
    </bean>
    <bean id= "redisClusterConfiguration"  class = "org.springframework.data.redis.connection.RedisClusterConfiguration" >
        <property name= "clusterNodes" >
            <list>
                <ref bean= "node" />
            </list>
        </property>
        <property name= "maxRedirects"  value= "10" />
    </bean>
    <bean  class = "org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
        <constructor-arg name= "clusterConfig"  ref= "redisClusterConfiguration" />
        <constructor-arg name= "poolConfig"  ref= "jedisPoolConfig" />
    </bean>

4、添加properties配置

ecej.session.redis.ip=${ecej.session.redis.ip}
ecej.session.redis.port=${ecej.session.redis.port}

5、添加maven profile

<!-- session共享 -->
<ecej.session.redis.ip>10.4.89.161</ecej.session.redis.ip>
<ecej.session.redis.port>6379</ecej.session.redis.port>

配置完成

二十三、菜单权限验证

此功能为菜单权限验证设计,使用内置可配置拦截器

如需使用此功能必须配置以下参数,为了方便请把参数放在application.properties中

ecej.menu.auth.path 权限验证地址(最好配置域名)

可选配置参数

ecej.menu.auth.path.patterns拦截规则(默认拦截规则 “/**”)  

样例:

ecej.menu.auth.path=www.ecej.auth.path

ecej.menu.auth.path.patterns=/user/auth,/passwd,/menu  (这样配置将以这三个规则拦截/user/auth   /passwd  /menu )

 

二十四、热部署

spring-boot-devtools

添加 POM 文件依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional> true </optional> <!-- 这个需要为  true  热部署才有效 -->
</dependency>
<plugin>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-maven-plugin</artifactId>
     <configuration>
            <fork> true </fork>
     </configuration>
</plugin>
            

 

随意更改代码即可看到效果。

如果我们想指定让 devtools 监听指定文件夹,那么可以在 application.properties配置
spring.devtools.restart.additional-paths=your path,注意这里需要改成 yml 文件的格式。

 

这里要特别注意下,由于热部署是监听 Class 文件的变化,它自身不会主动去编译 Java 文件,所以我们得在 Java 文件改动时,自动编译成 Class 文件,然后热部署工具创造的新的类加载器才会加载改变后的 Class 文件。

所以,如果你使用 IDEA 开发工具的话,记得要把自动编译打开。

二十五、访问路径配置

有的时候可能需要特殊的路径统一配置,正常情况下 http://ip:port , 如果要修改为http://ip:port/ecej/ 访问的话,那么需要在application.properties文件中加入server.context-path = /你的path,比如:spring-boot,那么访问地址就是http://ip:port/spring-boot 路径。

如果配置了server.context-path 记得把静态资源的访问地址加上 你所配置的路径

二十六、内置HttpClient最大线程数

可通过ecej.http.client.maxTotal 参数配置内置全局HttpClient,默认线程数300

二十七 HBase工具组件使用

1.pom引用

<dependency>
<groupId>com.nove</groupId>
<artifactId>ecej-hbase</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>

2.主要方法 com.ecej.nove.hbase.utils.HBaseTemplate

3.使用方式, 需要注入使用.

@Service("hBaseTemplate")
public class HBaseTemplate{}

代码中

@Resource
private HBaseTemplate hBaseTemplate;

src/main/resources下面增加配置文件remote-hbase.properties.(不要忘记添加springboot项目对应配置文件读取)

#HBase zookeeper address
ecej.hbase.zookeeper=@hbase.zookeeper.host@

#base pool size
ecej.hbase.corePoolSize=@ecej.hbase.corePoolSize@
#max pool size
ecej.hbase.maxPoolSize=@ecej.hbase.maxPoolSize@

ecej.hbase.queueCapacity=@ecej.hbase.queueCapacity@

对应在pom里面增加profile的值

二十八、添加postgres数据源支持

在remote-db.properties中添加

druid.driverClassName=org.postgresql.Driver

添加依赖

 

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>

请使用NOVE版本大于或等于1.3.8


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值