一、前言
次说明参照新的项目体系结构编写,具体哪些是新的项目体系,请参照:项目统计
随着我们对技术的不断深入,项目结构配置也会趋于更加透明简洁,所以项目体系会不断的更新,如有问题请咨询架构组
截至目前,本文采用的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"
})
@ImportResource
({
"classpath:dubbo/*.xml"
})
public
class
PropertiesConfig
extends
AbstractPropertiesConfig {
}
|
3.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
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();
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;
}
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
;
}
@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
)
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