feat(Java_SpringExample): 增加Properties文件字段读取两种方式(propertiesScan),PostConstruct的使用、BeanPostProcessor在Bean初始化前后进行处理(init)、统一异常处理的两种方式(exceptionHandler)、统一出参报文处理(response)、新增上下文刷新判断处理类(refreshEvent)、添加HttpSession监听器(listener)
This commit is contained in:
@@ -3,4 +3,7 @@
|
||||
##更新记录
|
||||
2020/5/22 : 创建工程(代码有问题,先提交)
|
||||
|
||||
2020/5/26 : AspectJ代码提交,代码报错未解决
|
||||
2020/5/26 : AspectJ代码提交,代码报错未解决
|
||||
|
||||
2020/5/29 : 增加Properties文件字段读取两种方式(propertiesScan),PostConstruct的使用、BeanPostProcessor在Bean初始化前后进行处理(init)、统一异常处理的两种方式(exceptionHandler)、统一出参报文处理(response)
|
||||
新增上下文刷新判断处理类(refreshEvent)、添加HttpSession监听器(listener)
|
||||
@@ -76,8 +76,8 @@ public class MvcComponentLoader extends WebMvcConfigurerAdapter {
|
||||
* @return
|
||||
*/
|
||||
// @Bean
|
||||
// public MyExceptionHandler getExceptionHandler() {
|
||||
// return new MyExceptionHandler();
|
||||
// public ExceptionResolver getExceptionHandler() {
|
||||
// return new ExceptionResolver();
|
||||
// }
|
||||
|
||||
/**
|
||||
@@ -86,7 +86,7 @@ public class MvcComponentLoader extends WebMvcConfigurerAdapter {
|
||||
*/
|
||||
@Override
|
||||
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
|
||||
// exceptionResolvers.add(new MyExceptionHandler());
|
||||
// exceptionResolvers.add(new ExceptionResolver());
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package config;
|
||||
|
||||
import config.refreshEvent.ContextRefreshEvent;
|
||||
import filter.FilterDelegator;
|
||||
import filter.WelcomeHandlingFilter;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -30,11 +31,12 @@ public class WebInitializer extends AbstractAnnotationConfigDispatcherServletIni
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
super.onStartup(servletContext);
|
||||
/**配置和监听器*/
|
||||
// 配置和监听器
|
||||
registerServletFilters(servletContext);
|
||||
registerListeners(servletContext);
|
||||
// QuartzListener quartzListener = new QuartzListener();
|
||||
// servletContext.addListener(quartzListener.getClass());
|
||||
//刷新事件需要作为监听器在这边配置
|
||||
ContextRefreshEvent refreshEvent = new ContextRefreshEvent();
|
||||
servletContext.addListener(refreshEvent.getClass());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package config.exceptionHandler;
|
||||
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@ControllerAdvice
|
||||
public class AnnoExceptionHandler {
|
||||
|
||||
/**
|
||||
* @a
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(CustomGenericException.class)//可以直接写@ExceptionHandler,不指明异常类,会自动映射
|
||||
public ModelAndView customGenericExceptionHnadler(CustomGenericException exception){ //还可以声明接收其他任意参数
|
||||
ModelAndView modelAndView = new ModelAndView("generic_error");
|
||||
modelAndView.addObject("errCode",exception.getErrCode());
|
||||
modelAndView.addObject("errMsg",exception.getErrMsg());
|
||||
return modelAndView;
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)//可以直接写@EceptionHandler,IOExeption继承于Exception
|
||||
public ModelAndView allExceptionHandler(Exception exception){
|
||||
ModelAndView modelAndView = new ModelAndView("generic_error");
|
||||
modelAndView.addObject("errMsg", "this is Exception.class");
|
||||
return modelAndView;
|
||||
}
|
||||
|
||||
|
||||
public class CustomGenericException extends RuntimeException{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String errCode;
|
||||
private String errMsg;
|
||||
|
||||
public String getErrCode() {
|
||||
return errCode;
|
||||
}
|
||||
|
||||
|
||||
public String getErrMsg() {
|
||||
return errMsg;
|
||||
}
|
||||
|
||||
public CustomGenericException(String errCode, String errMsg) {
|
||||
this.errCode = errCode;
|
||||
this.errMsg = errMsg;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package config.exceptionHandler;
|
||||
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author 志军
|
||||
* 继承spring的问题处理类, spring有默认的异常处理体系,默认的异常处理体系是先进行处理的。
|
||||
* 这里继承Order接口可以把我们的处理器作为位置0的处理器。但是默认的异常处理器的位置也是0,所以我们无法控制他们谁先处理
|
||||
*
|
||||
* 可以参考MvcComponentLoader的描述
|
||||
*
|
||||
* 通过继承接口进行处理是第一种方式
|
||||
*/
|
||||
@Order(value = 0)
|
||||
public class ExceptionResolver implements HandlerExceptionResolver {
|
||||
|
||||
|
||||
/**
|
||||
* 厉害了。这边也可测试一下如果是不给这个异常放在第一位的话,会出现什么情况,
|
||||
* 其他的异常处理体系是不是会把异常进行处理
|
||||
*/
|
||||
@Override
|
||||
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
System.out.printf("发现了异常,进入%s类", ExceptionResolver.class.getName());
|
||||
System.out.printf("错误信息:%s", ex.getMessage());
|
||||
//这里是匹配错误类型,把错误信息加上的地方 - 你可能会匹配很多的错误,这里的做法应该是对错误进行分类。
|
||||
ExceptionResponse exceptionResponse = null;
|
||||
if (ex instanceof MethodArgumentNotValidException) {
|
||||
MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) ex;
|
||||
//这里面包含了错误的信息
|
||||
System.out.println(methodArgumentNotValidException.toString());
|
||||
exceptionResponse = new ExceptionResponse("500","报错");
|
||||
}
|
||||
//最后就是异常处理返回
|
||||
MappingJackson2JsonView view = new MappingJackson2JsonView();
|
||||
view.setExtractValueFromSingleKeyModel(true);
|
||||
return new ModelAndView(view, "response",exceptionResponse);
|
||||
}
|
||||
|
||||
}
|
||||
class ExceptionResponse{
|
||||
private String code;
|
||||
private String message;
|
||||
|
||||
ExceptionResponse(String code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package config.init;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* @author 志军
|
||||
* 测试一下<code>@PostConstruct</code>注解
|
||||
*/
|
||||
@Component
|
||||
public class InitPost {
|
||||
|
||||
/**
|
||||
* 该注解相当于servlet的init方法,且只会执行一次
|
||||
* 不知道这个的执行顺序,后面可以再了解一下
|
||||
*/
|
||||
@PostConstruct
|
||||
public void initPost(){
|
||||
System.out.println("我被初始化了");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @(#) MyBeanPostProcess
|
||||
* 版权声明 黄志军, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:黄志军
|
||||
* <br> @author selfImpr
|
||||
* <br> 2018-05-28 22:19:40
|
||||
* <br> @description
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package config.init;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author 志军
|
||||
* 自定义Bean初始化前后处理的方法
|
||||
* 这边Spring使用的也是模板模式
|
||||
*/
|
||||
@Component
|
||||
public class SelfBeanPostProcess implements BeanPostProcessor {
|
||||
|
||||
/**
|
||||
* 在Bean初始化之前进行处理
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
System.out.println("beanName-----------" + beanName);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在Bean初始化之后进行处理
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package config.propertiesScan;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
|
||||
/**
|
||||
* @author selfimpr
|
||||
* @description 通过该配置来实现对properties的属性进行读取
|
||||
* @date 2017/11/11 21:25
|
||||
*
|
||||
* <code>@PropertySource</code>注解 解决中文乱码问题 好像还是需要设置IDEA的编码
|
||||
* //参考地址:http://blog.csdn.net/j3oker/article/details/53839210
|
||||
*/
|
||||
@Configuration
|
||||
@PropertySource(value = "classpath:appilcation.properties",encoding = "UTF-8")
|
||||
public class PropertiesScan {
|
||||
|
||||
@Value("${area_id}")
|
||||
public String isBorder;
|
||||
|
||||
@Value("${local_request_id}")
|
||||
public String borderColor;
|
||||
|
||||
public String getIsBorder() {
|
||||
return isBorder;
|
||||
}
|
||||
|
||||
public String getBorderColor() {
|
||||
return borderColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 要想使用@Value 用${}占位符注入属性,这个bean是必须的,这个就是占位bean,另一种方式是不用value直接用Envirment变量直接getProperty('key')
|
||||
*/
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package config.propertiesScan;
|
||||
|
||||
import util.FileUtil;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.annotation.WebListener;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 通过这个类来扫描获取所有的properties下面的文件
|
||||
* 这个监听器在Servlet上下文初始化过程中进行处理
|
||||
* @author 志军
|
||||
*/
|
||||
@WebListener
|
||||
public class PropertiesScanByListener implements ServletContextListener {
|
||||
|
||||
private Map<String, String> map = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext servletContext = sce.getServletContext();
|
||||
String resourcesPath = servletContext.getRealPath("/") + "WEB-INF\\classes\\cache";
|
||||
traceFilesAndGetProperties(resourcesPath);
|
||||
servletContext.setAttribute("properties", map);
|
||||
System.out.println(map);
|
||||
}
|
||||
|
||||
private void traceFilesAndGetProperties(String path) {
|
||||
if (FileUtil.isDir(path)) {
|
||||
File[] files = new File(path).listFiles();
|
||||
if (files == null || files.length == 0) {
|
||||
System.out.println("文件夹是空的!");
|
||||
} else {
|
||||
for (File file2 : files) {
|
||||
if (file2.isDirectory()) {
|
||||
System.out.println("文件夹:" + file2.getAbsolutePath());
|
||||
traceFilesAndGetProperties(file2.getAbsolutePath());
|
||||
} else {
|
||||
//是否是配置文件
|
||||
if (file2.getAbsolutePath().contains(".properties")) {
|
||||
getProperties(file2.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (FileUtil.isFile(path)){
|
||||
if (new File(path).getAbsolutePath().contains(".properties")) {
|
||||
getProperties(new File(path).getAbsolutePath());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("文件不存在");
|
||||
}
|
||||
|
||||
private void getProperties(String filePath) {
|
||||
Properties properties = new Properties();
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(filePath);
|
||||
properties.load(in);
|
||||
for (Object o : properties.keySet()) {
|
||||
String key = (String) o;
|
||||
String value = properties.getProperty(key);
|
||||
map.put(key, value);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e );
|
||||
} finally {
|
||||
try {
|
||||
if (null != in) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("文件流关闭失败:"+e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package config.refreshEvent;
|
||||
|
||||
import org.quartz.*;
|
||||
import org.quartz.impl.StdSchedulerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@PropertySource("classpath:/app.properties")
|
||||
public class ContextRefreshEvent implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
* 程序启动,上下文刷新或者初始化的时候会调用该方法
|
||||
* Event raised when an {@code ApplicationContext} gets initialized or refreshed.
|
||||
* 这边是选择在 onStartup方法上去配置这个监听器,但是也可以直接用@WebListener去注册这个监听器
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
//因为Spring有两个上下文容器,所以这边加上一个判断,让程序运营在住容器的时候就进行定时任务的执行.
|
||||
if (event.getApplicationContext().getParent() == null) {
|
||||
try {
|
||||
//"0 0 3/1 3 * ? * ";
|
||||
String timerTime = environment.getProperty("cron");
|
||||
Trigger trigger = TriggerBuilder
|
||||
.newTrigger()
|
||||
.withIdentity("dummyTriggerName", "group1")
|
||||
.withSchedule(CronScheduleBuilder.cronSchedule(timerTime))
|
||||
.build();
|
||||
JobDetail job = JobBuilder.newJob(HelloJob.class)
|
||||
.withIdentity("dummyJobName", "group1").build();
|
||||
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
|
||||
scheduler.start();
|
||||
scheduler.scheduleJob(job, trigger);
|
||||
} catch (SchedulerException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class HelloJob implements Job {
|
||||
@Override
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||
System.out.print("hello quartz ");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* @(#) ShareResponseObject
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-11-13 20:34:52
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
package config.response;
|
||||
|
||||
/**
|
||||
* 响应对象。
|
||||
*
|
||||
*/
|
||||
public class ResponseObject<T> {
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 描述信息
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String errorMessage;
|
||||
|
||||
/**
|
||||
* 数据对象
|
||||
*/
|
||||
private T dataView;
|
||||
|
||||
public ResponseObject(String code, String message, T value) {
|
||||
this.status = code;
|
||||
this.message = message;
|
||||
this.dataView = value;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public T getDataView() {
|
||||
return dataView;
|
||||
}
|
||||
|
||||
public void setDataView(T dataView) {
|
||||
this.dataView = dataView;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* @(#) ResponseConfiguration
|
||||
* 版权声明 黄志军, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:黄志军
|
||||
* <br> @author selfImpr
|
||||
* <br> 2018-05-31 14:59:23
|
||||
* <br> @description
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package config.response;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJacksonValue;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.AbstractMappingJacksonResponseBodyAdvice;
|
||||
|
||||
/**
|
||||
* 这里通过一个注解和继承的方式,对所有出控制器(被某一个注解标注的类) - 这里自定了一个注解为TestResponse
|
||||
* 对这种类进行参数的处理
|
||||
* 好像这个注解还有叠加的作用....
|
||||
* 这个注解也可以作为异常处理的操作。即在每个方法上面添加处理的class。还想这样很麻烦啊,还不如用异常处理器
|
||||
* @author 志军
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class ResponseProcess extends AbstractMappingJacksonResponseBodyAdvice {
|
||||
|
||||
/**
|
||||
* 这个注解好像是必须捕获ResponseBody这个解决才会进行执行,@ResponseBody表明这个返回的东西是在报文里面,
|
||||
* 且如果不配置转换器,spring会自动提供7个,但是如果我们想规定顺序就要自己配置
|
||||
*/
|
||||
@Override
|
||||
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
System.out.println( returnType.getMethod().getName());
|
||||
return returnType.hasMethodAnnotation(ResponseBody.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType, MethodParameter returnType,
|
||||
ServerHttpRequest request, ServerHttpResponse response) {
|
||||
Object value = bodyContainer.getValue();
|
||||
ResponseObject<Object> object = new ResponseObject<>("200", "调度成功", value);
|
||||
bodyContainer.setValue(object);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package controller;
|
||||
|
||||
import config.propertiesScan.PropertiesScan;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* @author selfimpr
|
||||
* @description 测试SpringConfig利用注解来实现properties配置文件的读取
|
||||
* @date 2017/11/11 21:26
|
||||
*/
|
||||
|
||||
@Controller
|
||||
public class PropertiesGetController {
|
||||
|
||||
@Autowired
|
||||
private PropertiesScan propertiesConfig;
|
||||
|
||||
@RequestMapping("/get/properties")
|
||||
public void getProperties() {
|
||||
System.out.println(propertiesConfig.getIsBorder());
|
||||
System.out.println(propertiesConfig.getBorderColor());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package listener;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.servlet.annotation.WebListener;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
/**
|
||||
* 处理Session创建和消亡的类,这边通过<code>@WebListener</code>注解直接声明为监听器
|
||||
* @author 志军
|
||||
*/
|
||||
@WebListener
|
||||
public class TestHttpSessionListener implements HttpSessionListener {
|
||||
|
||||
private Logger logger = Logger.getLogger(HttpSessionListener.class);
|
||||
@Override
|
||||
public void sessionCreated(HttpSessionEvent se) {
|
||||
|
||||
SessionListenerTask sessionListenerTask = new SessionListenerTask();
|
||||
HttpSession session = se.getSession();
|
||||
// 设置session过期时间 --这种方式并不科学
|
||||
se.getSession().setMaxInactiveInterval(20);
|
||||
logger.debug("session创建时间:"+session.getCreationTime());
|
||||
|
||||
//为了让页面加载看起来更流畅,这里模拟了两个情况,一个是用线程实现不等待,一个是加载数据库等待
|
||||
if(SessionListenerTask.isIsFirst()){
|
||||
sessionListenerTask.run();
|
||||
SessionListenerTask.setIsFirst(false);
|
||||
}else{
|
||||
//这里是同步情况
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
System.out.println("session 加载开始,时间为:" + System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionDestroyed(HttpSessionEvent se) {
|
||||
se.getSession().getCreationTime();
|
||||
System.out.println("session过期了");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
package model;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class FileItem {
|
||||
|
||||
private String fileName;
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public void setInputStream(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
|
||||
|
||||
package util;
|
||||
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import model.FileItem;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huangzj1
|
||||
*/
|
||||
public class FileUtil {
|
||||
|
||||
private static final byte[] BUF = new byte[1024];
|
||||
|
||||
private static final int BUF_SIZE = 1024;
|
||||
|
||||
public static void deleteFile(String filePath) {
|
||||
File file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("文件不存在");
|
||||
}
|
||||
|
||||
file.delete();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 支持输入流存储到对应文件夹下,仅对文件夹有效
|
||||
* @param fileItems 输入流、文件名 数组
|
||||
* @param dirPath 文件夹路径
|
||||
*/
|
||||
public static void storeFiles(List<FileItem> fileItems, String dirPath) {
|
||||
File file = new File(dirPath);
|
||||
if (!file.exists() && !file.isDirectory()) {
|
||||
file.mkdir();
|
||||
}
|
||||
|
||||
fileItems.forEach(fileItem -> {
|
||||
File fileItemFile = new File(dirPath + File.separator + fileItem.getFileName());
|
||||
FileOutputStream fileOutputStream;
|
||||
|
||||
try {
|
||||
//创建文件
|
||||
fileItemFile.createNewFile();
|
||||
fileOutputStream = new FileOutputStream(fileItemFile);
|
||||
int len;
|
||||
while ((len = fileItem.getInputStream().read(BUF, 0, BUF_SIZE)) != -1) {
|
||||
fileOutputStream.write(BUF, 0, len);
|
||||
}
|
||||
|
||||
fileOutputStream.close();
|
||||
fileItem.getInputStream().close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("生成文件错误");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean fileExist(String filePath){
|
||||
File file = new File(filePath);
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
public static boolean isFile(String filePath){
|
||||
File file = new File(filePath);
|
||||
if ( file.exists()){
|
||||
return file.isFile();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isDir(String filePath){
|
||||
File file = new File(filePath);
|
||||
if ( file.exists()){
|
||||
return file.isDirectory();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件已存在或者创建成功返回true
|
||||
* 文件不存在或者非文件(文件夹)或者创建失败,返回false
|
||||
*/
|
||||
public static boolean createFile(String filePath){
|
||||
if(fileExist(filePath)){
|
||||
return isFile(filePath);
|
||||
}
|
||||
File file = new File(filePath);
|
||||
try {
|
||||
return file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并获取一个File对象
|
||||
* 如果是文件、创建成功返回对应的文件对象
|
||||
* 其他情况直接返回null.
|
||||
*/
|
||||
public static File createGetFile(String filePath){
|
||||
if(fileExist(filePath)){
|
||||
if ( isFile(filePath)){
|
||||
return new File(filePath);
|
||||
}
|
||||
}
|
||||
File file = new File(filePath);
|
||||
try {
|
||||
boolean result = file.createNewFile();
|
||||
if (result){
|
||||
return file;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件转换成byte数组
|
||||
*/
|
||||
public static byte[] fileToByte(String filePath) {
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(new File(filePath));
|
||||
byte[] bytes = new byte[in.available()];
|
||||
in.read(bytes);
|
||||
return bytes;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("转换失败",e);
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* byte数组写入文件
|
||||
*/
|
||||
public static void bytesToFile(String filePath,byte[] content){
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(new File(filePath));
|
||||
out.write(content);
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("写入失败",e);
|
||||
} finally {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拿到文件夹下面的所有文件夹(包括它自己)
|
||||
*/
|
||||
public static List<File> findAllDirFromDir(String dirPath){
|
||||
File dir = new File(dirPath);
|
||||
if(!dir.exists() || !dir.isDirectory()){
|
||||
throw new RuntimeException("非文件夹或者文件夹位置错误");
|
||||
}
|
||||
List<File> result = findDir(dir);
|
||||
result.add(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<File> findDir(File file ){
|
||||
List<File> list = Lists.newArrayList();
|
||||
for(File child : Objects.requireNonNull(file.listFiles())){
|
||||
if(child.isDirectory()){
|
||||
list.add(child);
|
||||
List<File> tempList = findDir(child);
|
||||
if(!CollectionUtils.isEmpty(tempList)){
|
||||
list.addAll(tempList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拿到文件夹下面的所有空文件夹
|
||||
*/
|
||||
public static List<File> findAllEmptyDirFromDir( String dirPath){
|
||||
List<File> list = Lists.newArrayList();
|
||||
File dir = new File(dirPath);
|
||||
if(!dir.exists() || !dir.isDirectory()){
|
||||
throw new RuntimeException("非文件夹或者文件夹位置错误");
|
||||
}
|
||||
List<File> allList = findAllDirFromDir(dirPath);
|
||||
for(File dirFile:allList){
|
||||
if(isEmptyFile(dirFile)){
|
||||
list.add(dirFile);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过目录获取目录下所有的文件
|
||||
*/
|
||||
public static List<File> findAllFile(File dir){
|
||||
List<File> list = Lists.newArrayList();
|
||||
for (File file : Objects.requireNonNull(dir.listFiles())){
|
||||
if(file.isFile()){
|
||||
list.add(file);
|
||||
}else{
|
||||
List<File> tempList = findAllFile(file);
|
||||
if(!CollectionUtils.isEmpty(tempList)){
|
||||
list.addAll(tempList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static boolean isEmptyFile(File dir) {
|
||||
List<File> child = findAllFile(dir);
|
||||
return CollectionUtils.isEmpty(child);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拿到文件夹下面的所有非空文件夹
|
||||
*/
|
||||
public static List<File> findAllNotEmptyDirFromDir( String dirPath){
|
||||
List<File> list = Lists.newArrayList();
|
||||
File dir = new File(dirPath);
|
||||
if(!dir.exists() || !dir.isDirectory()){
|
||||
throw new RuntimeException("非文件夹或者文件夹位置错误");
|
||||
}
|
||||
List<File> allList = findAllDirFromDir(dirPath);
|
||||
for(File dirFile:allList){
|
||||
if(!isEmptyFile(dir)){
|
||||
list.add(dirFile);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#spring 提供的Environment会加载application.properties和application-$(profile).properties文件。
|
||||
#这里就是测试一下
|
||||
#用于做quartz定时任务
|
||||
cron=0 0 3/1 3 * ? *
|
||||
@@ -0,0 +1,2 @@
|
||||
area_id=\u9EC4\u5FD7\u519B
|
||||
local_request_id=JOINT_THEME
|
||||
@@ -0,0 +1 @@
|
||||
b=1
|
||||
Reference in New Issue
Block a user