一、事件监听机制
- ApplicationEvent+@EventListener 基于观察者模式 实现自定义监听器
- 自定义事件 SysLogEvent继承 ApplicationEvent
- 两种方式
- 定义事件监听器 实现 ApplicationListener
- 在监听方法添加@EventListener(SysLogEvent.class)
- 定义事件监听基类(为了多类型事件,可以做统一监听,监听基类事件即可)
- 定义事件监听子类
- 发布事件 测试
- WebServerInitializedEvent:tomcat启动后,springboot会发布此事件
package com.grea.qz.event;
import org.springframework.context.ApplicationEvent;
public class BaseEvent<E, S> extends ApplicationEvent {
protected E event;
protected S service;
public BaseEvent(Object source, E event, S service) {
super(source);
this.event = event;
this.service = service;
}
public void handleEvent(){}
public E getEvent() {
return event;
}
public void setEvent(E event) {
this.event = event;
}
public S getService() {
return service;
}
public void setService(S service) {
this.service = service;
}
}
package com.grea.qz.listener;
import com.grea.qz.event.BaseEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class EventListener implements ApplicationListener<BaseEvent> {
@Async
@Override
public void onApplicationEvent(BaseEvent baseEvent) {
System.out.println("事件触发!处理自己的业务逻辑");
baseEvent.handleEvent();
}
}
package com.grea.qz.event;
import com.grea.qz.enums.OrderStatus;
import com.grea.qz.model.modules.OrderRecord;
import com.grea.qz.model.modules.User;
import com.grea.qz.service.OrderRecordService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
public class OrderRecordEvent extends BaseEvent<OrderStatus,OrderRecordService> {
private final static Logger logger = LoggerFactory.getLogger(OrderRecordEvent.class);
protected Integer orderId;
protected String remarks;
protected User user;
/**
* 订单类型
* 1数据订单
* 2画像订单
* 3固定画像
*
protected Integer type;*/
public OrderRecordEvent(Object source, OrderStatus event, OrderRecordService service, Integer orderId, String remarks, User user) {
super(source, event, service);
this.orderId = orderId;
this.remarks = remarks;
this.user = user;
}
@Override
public void handleEvent() {
OrderRecord record = new OrderRecord();
record.setCreateBy(user.getId());
record.setUserName(user.getUsername());
record.setCreateTime(new Date());
record.setOrderId(orderId);
record.setOperationType(event.getValue());
record.setRemarks(remarks);
service.add(record);
}
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
二、属性编辑器
- 处理请求映射到方法之间的数据处理,通常放在控制层的基类。用于处理所有的请求参数
- @InitBinder注册编辑器(在控制层基类注册,所有的接口调用都会进行参数处理)
- 创建自定义编辑器(DateEditor等)
- 也可以绑定spring提供的默认的编辑器
package com.grea.qz.config.json;
import org.springframework.util.StringUtils;
import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
public class DateEditor extends PropertyEditorSupport {
private final static ArrayList<SimpleDateFormat> dateFormats = new ArrayList<>(4);
static {
dateFormats.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
dateFormats.add(new SimpleDateFormat("yyyy-MM-dd HH:mm"));
dateFormats.add(new SimpleDateFormat("yyyy-MM-dd"));
dateFormats.add(new SimpleDateFormat("HH:mm:ss"));
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.isEmpty(text)) {
setValue(null);
} else {
for (SimpleDateFormat dateFormat : dateFormats) {
try {
setValue(dateFormat.parse(text));
break;
} catch (ParseException e) {
continue;
}
}
}
}
@Override
public String getAsText() {
Date value = (Date) getValue();
return (value != null ? dateFormats.get(0).format(value) : "");
}
}

三、异常处理机制
- @ControllerAdvice、@ExceptionHandler 与 ErrorController类
- 单独使用 @ExceptionHandler(单独使用 只能放在控制层或者控制层基类)
- 只能处理控制器抛出的异常。也就是进入接口后发生的异常(此方式可以配合ErrorController共同使用)
- @ControllerAdvice+ @ExceptionHandler
- 定义在控制层或者控制层基类
- 拦截所有异常包括未进入控制器的,并且不会走ErrorController的异常拦截
- 定义单独的拦截类会拦截所有的请求
- 但会走ErrorController的异常拦截(异常会被ErrorController重新处理);不推荐此用法
- 实现ErrorController,自定义错误处理异常
- 可以处理未进入控制器(未进接口的异常,类似404等)和进入控制器的
- 如果存在@ExceptionHandler(单独使用或者在控制层的),则只会处理未进入控制器
package com.grea.qz.common;
import com.grea.qz.base.vo.RestBody;
import com.grea.qz.exception.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@RestController
public class CustomErrorController extends BaseController implements ErrorController {
private static Logger logger = LoggerFactory.getLogger(CustomErrorController.class);
@Value("${error.path:/error}")
private String errorPath;
@Override
public String getErrorPath() {
return errorPath;
}
@RequestMapping(value = "${server.error.path:${error.path:/error}}")
public RestBody handleError(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> attributes = getErrorAttributes(request);
int code = (int) attributes.get("status");
String message = (String) attributes.get("message");
if (code < ErrorCode.SERVER_OK.getCode()) {
message = (String) attributes.get("error");
}
logger.error("error :{}--{}", code, message);
return failure(code, message);
}
private Map<String, Object> getErrorAttributes(HttpServletRequest request) {
ServletWebRequest servletWebRequest = new ServletWebRequest(request);
ErrorAttributes errorAttributes = new DefaultErrorAttributes();
return errorAttributes.getErrorAttributes(servletWebRequest, false);
}
}
四、事务机制
- 默认情况下,非public的方法会造成事务失效
- 在AbstractFallbackTransactionAttributeSource类中,spring隔离了public方法
- allowPublicMethodsOnly方法,被赋值未true,因此,可以修改allowPublicMethodsOnly的变量为false即可
- // Don’t allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
- 事务中的异常机制
- 默认的Spring事务,只会回滚RunTimeException异常
- @Transactional(isolation = Isolation.READ_UNCOMMITTED, rollbackFor = Exception.class)
- 设置rollbackFor 确定需要回滚的异常类型