应用自动配置

应用自动配置

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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
import ch.qos.logback.ext.spring.web.LogbackConfigListener;
import cn.mysteel.data.redis.service.AbstractRedisCache;
import com.banksteel.middleware.storage.api.dubbo.StoredFileDubboApi;
import com.banksteel.middleware.storage.api.dubbo.StoredFileStreamDubboApi;
import com.banksteel.openerp.authentication.BaseEACAuthenticationInterceptor;
import com.banksteel.openerp.authentication.DuplicateCheckUserLoginHandler;
import com.banksteel.openerp.common.bone.ReportRequestAutoConfiguraction;
import com.banksteel.openerp.commons.auth.RedisTokenManager;
import com.banksteel.openerp.commons.auth.RedisTokenManagerConfig;
import com.banksteel.openerp.commons.auth.TokenManager;
import com.banksteel.openerp.commons.dozer.BeanFactory;
import com.banksteel.openerp.commons.fastjson.FilterSerializerFeatureAspect;
import com.banksteel.openerp.commons.framework.CustomDispatcherServlet;
import com.banksteel.openerp.commons.framework.GlobalExceptionHandler;
import com.banksteel.openerp.commons.log.WriteBuzLogAspect;
import com.banksteel.openerp.commons.permission.CommandConfigLoader;
import com.banksteel.openerp.commons.permission.PermissionContext;
import com.banksteel.openerp.commons.permission.PermissionSpringListener;
import com.banksteel.openerp.commons.redisson.DistributeRedisLockAspect;
import com.banksteel.openerp.commons.utils.StoredFileClient;
import com.banksteel.openerp.component.finance.DealingsTool;
import com.banksteel.openerp.user.AuthUser;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.velocity.VelocityAutoConfiguration;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.util.IntrospectorCleanupListener;

import javax.annotation.Resource;
import javax.servlet.DispatcherType;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;

/**
* 应用自动配置
*/
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
// 当前类不能在basePackages描到的包下, 否则会出现死循环
@ComponentScan(basePackages = { "com.banksteel.openerp.*.ao.impl", "com.banksteel.openerp.memberinit",
"com.banksteel.openerp.memberinit.eacinit", "com.banksteel.openerp.*.ao","com.banksteel.openerp.*.vo",
"com.banksteel.openerp.common","com.banksteel.openerp.component", "com.banksteel.openerp.*.controller",
"com.banksteel.openerp.user.qrcode"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {DealingsTool.class}))
@ImportResource(locations = { "classpath:/spring/spring-context.xml", "classpath:/spring/spring-mvc.xml" })
@Import(ReportRequestAutoConfiguraction.class)
@PropertySource({"classpath:rabbitmq.properties", "classpath:dubbo.properties", "classpath:app_param.properties"})
@EnableAutoConfiguration(exclude = { VelocityAutoConfiguration.class})
@EnableConfigurationProperties(value = {RedisTokenManagerConfig.class})
@EnableAsync
public class AppAutoConfiguraction extends WebMvcConfigurerAdapter {
@Resource(name = "amqpTemplate")
private RabbitTemplate amqpTemplate;
@Resource(name = "yucangAmqpTemplate")
private RabbitTemplate yucangAmqpTemplate;
@Resource
private StringRedisTemplate eacRedisTemplate;
@Autowired
private StoredFileStreamDubboApi storedFileStreamDubboApi;
@Autowired
private StoredFileDubboApi storedFileDubboApi;
@Value("${secretKey}")
private String secretKey;

private static String apiPath = "/api";
static {
PermissionContext.setApiPath(apiPath);
BeanFactory.init();
}


@Bean
public ServletRegistrationBean restServlet() { // 注解扫描上下文
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();

// 通过构造函数指定dispatcherServlet的上下文
CustomDispatcherServlet customDispatcherServlet = new CustomDispatcherServlet();
customDispatcherServlet.setApplicationContext(applicationContext);

// 用ServletRegistrationBean包装servlet
ServletRegistrationBean registrationBean = new ServletRegistrationBean();
registrationBean.setLoadOnStartup(1);
registrationBean.setServlet(customDispatcherServlet);
// 指定urlmapping
registrationBean.addUrlMappings(apiPath + "/*");
// 指定name,如果不指定默认为dispatcherServlet
registrationBean.setName("customDispatcherServlet");
return registrationBean;
}

@Bean
public CommandConfigLoader commandConfigLoader(){
Set<String> exculdeUrls = new HashSet<>();
exculdeUrls.add("/api/websocket");
return new CommandConfigLoader("dispatcher.properties",exculdeUrls);
}

/**
* logback配置监听器
* @return
* @author:商家进销存项目组 康健
* @createTime:2017年7月25日 下午3:34:33
*/
@Bean
public ServletListenerRegistrationBean<LogbackConfigListener> LogbackConfigListener() {
ServletListenerRegistrationBean<LogbackConfigListener> listenerBean = new ServletListenerRegistrationBean<LogbackConfigListener>();
LogbackConfigListener logbackConfigListener = new LogbackConfigListener();
listenerBean.setListener(logbackConfigListener);
return listenerBean;
}

/**
* 对Spring Scope中request、Session的支持
*/
@Bean
public ServletListenerRegistrationBean<RequestContextListener> RequestContextListener() {
ServletListenerRegistrationBean<RequestContextListener> listenerBean = new ServletListenerRegistrationBean<RequestContextListener>();
RequestContextListener requestContextListener = new RequestContextListener();
listenerBean.setListener(requestContextListener);
return listenerBean;
}

/**
* 内存清理的Bean
*/
@Bean
public ServletListenerRegistrationBean<IntrospectorCleanupListener> introspectorCleanupListener() {
ServletListenerRegistrationBean<IntrospectorCleanupListener> listenerBean = new ServletListenerRegistrationBean<IntrospectorCleanupListener>();
IntrospectorCleanupListener introspectorCleanupListener = new IntrospectorCleanupListener();
listenerBean.setListener(introspectorCleanupListener);
return listenerBean;
}

/**
* 编码的统一处理
*/
@Bean
public FilterRegistrationBean encodingFilter() {
FilterRegistrationBean filterBean = new FilterRegistrationBean();
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true);

filterBean.setFilter(filter);
EnumSet<DispatcherType> dispatcherTypes = EnumSet.allOf(DispatcherType.class);
dispatcherTypes.add(DispatcherType.REQUEST);
dispatcherTypes.add(DispatcherType.FORWARD);
filterBean.setDispatcherTypes(dispatcherTypes);
filterBean.setEnabled(true);
filterBean.addUrlPatterns("/*");
return filterBean;
}

@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/index.htm");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
super.addViewControllers(registry);
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
// eac拦截器
BaseEACAuthenticationInterceptor eacInterceptor = new BaseEACAuthenticationInterceptor();
//redis模板直连,不要修改属性名称
eacInterceptor.setEacRedisTemplate(eacRedisTemplate);
InterceptorRegistration addInterceptor = registry.addInterceptor(eacInterceptor);
addInterceptor.excludePathPatterns("/webap/**", "/css/**", "/js/**","/images/**");
super.addInterceptors(registry);
}


/**
* @description: 配置内容适配
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
configurer.favorParameter(true);
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}

@Bean
public TokenManager<AuthUser> tokenManager(AbstractRedisCache abstractRedisCache,RedisTokenManagerConfig redisTokenManagerConfig){
DuplicateCheckUserLoginHandler duplicateCheckUserLoginHandler = new DuplicateCheckUserLoginHandler(abstractRedisCache, redisTokenManagerConfig);
return new RedisTokenManager<>(abstractRedisCache,redisTokenManagerConfig,duplicateCheckUserLoginHandler);
}

@Bean
public WriteBuzLogAspect writeBuzLogAspect(AmqpTemplate amqpTemplate){
return new WriteBuzLogAspect(amqpTemplate);
}

@Bean
public StoredFileClient writeStoredFileClient(StoredFileStreamDubboApi storedFileStreamDubboApi, StoredFileDubboApi storedFileDubboApi) {
return new StoredFileClient(storedFileStreamDubboApi, storedFileDubboApi, secretKey);
}

@Bean
public PermissionSpringListener permissionSpringListener(){
return new PermissionSpringListener();
}

@Bean
public GlobalExceptionHandler globalExceptionHandler(){
return new GlobalExceptionHandler();
}

@Bean
public FilterSerializerFeatureAspect filterSerializerFeatureAspect(){
return new FilterSerializerFeatureAspect();
}

@Bean
public DistributeRedisLockAspect distributeRedisLockAspect(){
return new DistributeRedisLockAspect();
}

@Bean
public RabbitMessagingTemplate rabbitMessagingTemplate() {
return new RabbitMessagingTemplate(amqpTemplate);
}

@Bean
public RabbitMessagingTemplate yuncangRabbitMessagingTemplate() {
return new RabbitMessagingTemplate(yucangAmqpTemplate);
}
}

自定义转发servlet,用来处理前端发送过来的请求

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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import static com.banksteel.openerp.commons.permission.PermissionContext.checkIsLegalReq;
import static com.banksteel.openerp.commons.permission.PermissionContext.checkIsUrlReq;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.DispatcherServlet;

import com.alibaba.fastjson.JSONObject;
import com.banksteel.openerp.commons.framework.entiy.RequestEntiy;
import com.banksteel.openerp.commons.framework.entiy.RequestEntiyFace;
import com.banksteel.openerp.commons.framework.entiy.ResponseEntity;
import com.banksteel.openerp.commons.framework.exception.CommondNotFoundException;
import com.banksteel.openerp.commons.permission.PermissionContext;
import com.banksteel.openerp.commons.permission.PermissionRequest;

public class CustomDispatcherServlet extends DispatcherServlet {
public static final String QUOT = "&quot;";
private static final long serialVersionUID = -3983568685367864966L;
public static final String REQUEST_COMMAND = "request_command";
private static Logger LOGGER = LoggerFactory.getLogger(CustomDispatcherServlet.class);
private static final List<String> PARAMS = new ArrayList<String>();

static {
PARAMS.add("announcementContent");
PARAMS.add("xmlFilePath");
}

@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
String requestUrl = request.getRequestURI();
String method = request.getMethod();
try{
request.setCharacterEncoding("UTF-8");
if (!checkIsUrlReq(PermissionContext.getApiPath(requestUrl) , method) && checkIsLegalReq(requestUrl)) {
// 非过滤URL
RequestEntiyFace requestEntiyface = null;
RequestEntiy requestEntiy = getRequestEntiy(request);
if (requestEntiy != null) {
// 请求参数可以正常解析
request.setAttribute(REQUEST_COMMAND, requestEntiy.getCommand());
String command = requestEntiy.getCommand();
LOGGER.info("请求命令:" + command);
if (StringUtils.isBlank(command)){
throw new CommondNotFoundException(String.format("请求[%s,%s]不为url直接访问的请求,请求参数中不存在command",method,requestUrl));
}

if (!PermissionContext.containsCommand(command)){
throw new CommondNotFoundException("命令:"+command);
}
requestEntiyface = doRequestPath(requestEntiy);
if (requestEntiyface != null) {
request = new HttpResquestWrapper(request, requestEntiyface);
}
}
}
super.doService(request, response);
}catch(Exception e) {
LOGGER.error(String.format("请求[%s,%s]分发失败",method,requestUrl),e);
ResponseEntity result=returnException("4001","请求分发失败"+","+e.getMessage(),"");
response.setContentType("application/json; charset=UTF-8");
try
{
response.getWriter().write(JSONObject.toJSONString(result));
} catch (Exception e2)
{
throw new IOException(e2.getMessage());
}
}
}

protected RequestEntiyFace doRequestPath(RequestEntiy requestEntiy) {
RequestEntiyFace requestEntiyface = new RequestEntiyFace();
String command = requestEntiy.getCommand();

PermissionRequest request = PermissionContext.getPermissionByCommand(command);

if (request.getRequestMethod() != null){
requestEntiyface.setMethod(request.getRequestMethod().toString());// 设置请求方法
}

requestEntiyface.setURI(request.getRequestPath());// 设置请求路径
Map<String, String> heads = new HashMap<String, String>();
heads.put("x-openerp-token", requestEntiy.getAccessToken());
requestEntiyface.setHeads(heads);

if (StringUtils.startsWith(requestEntiy.getData(),"{")){ // 说明data数据是对象
JSONObject json = JSONObject.parseObject(requestEntiy.getData());
json = (JSONObject) objectFilter(json);
requestEntiy.setData(json.toJSONString());
Map<String, String[]> params = new HashMap<String, String[]>();
for (String key : json.keySet()) {
String[] param = new String[1];
param[0] = json.get(key) + "";
params.put(key, param);
}
requestEntiyface.setGetParam(params);
}
requestEntiyface.setBodyData(requestEntiy.getData());
return requestEntiyface;
}

/**
*
* @description:获取请求数据为对象
* @param request
* @return
* @throws Exception
* @author:商家进销存项目组 xuxp
* @createTime:2016年8月8日 下午2:09:04
*/
private RequestEntiy getRequestEntiy(HttpServletRequest request) throws Exception {
String encode = "UTF-8";
InputStream inputStream = request.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] tmp = new byte[2048];
int i = inputStream.read(tmp);
while (i > 0) {
baos.write(tmp, 0, i);
i = inputStream.read(tmp);
}
String value = new String(baos.toByteArray(), encode);
if(value != null && !"".equals(value)){
RequestEntiy requestEntiy = JSONObject.parseObject(value, RequestEntiy.class);
requestEntiy.setData(requestEntiy.getData());
return requestEntiy;
}
return null;
}

/**
* @description:过滤特殊字符串
* @param needToFormat
* @return
* @author:商家进销存项目组 xuxp
* @createTime:2016年8月8日 下午2:06:54
*/
public static String formatHtml(String needToFormat) {
if (needToFormat != null && needToFormat.length() > 0) {
needToFormat = needToFormat.replace("<script>", "");
needToFormat = needToFormat.replace("&", "&amp;");
needToFormat = needToFormat.replace("\"", QUOT);
needToFormat = needToFormat.replace("“", QUOT);
needToFormat = needToFormat.replace("”", QUOT);
needToFormat = needToFormat.replace("<", "&lt;");
needToFormat = needToFormat.replace(">", "&gt;");
needToFormat = needToFormat.replace("'", "&#39;");
needToFormat = needToFormat.replace("\r\n", "");
return needToFormat;
}
return "";
}

private Object objectFilter(Object json) {
Object result = null;
if (json == null) {
result = "";
}
else if (json instanceof JSONObject) {
JSONObject jsono = (JSONObject) json;
Set<String> keys = jsono.keySet();
if (!keys.isEmpty())
{
for (String k : keys)
{
if (PARAMS.indexOf(k) != -1)
{
continue;
}
jsono.put(k, objectFilter(jsono.get(k)));
}
}
result = jsono;
}
else if (json instanceof String) {
result = formatHtml(json.toString());
}
else {
result = json;
}
return result;
}
private ResponseEntity returnException(String code, String mess, Object data) {
ResponseEntity responseEntity = new ResponseEntity();
responseEntity.setCode(Integer.parseInt(code));
Calendar calendar = Calendar.getInstance(Locale.CHINA);
responseEntity.setTimeStamp(calendar.getTimeInMillis());
responseEntity.setResult("exception");
responseEntity.setMess(mess);
responseEntity.setData(data);
return responseEntity;
}
}