说明文档更新:https://gitee.com/heHouHui/jfinal_validated/wikis/Home
提供异常统一扑捉实现IErrorRequestResponseAdvice类即可:
/**
* @Auther: hehh
* @Date: 2018/12/27 12:40
* @Description: 注意异常向下兼容
*/
public interface IErrorRequestResponseAdvice<T extends Throwable,E extends Render>{
/**验证支持*/
boolean supports(T throwable);
/**异常处理*/
E laterBodyWrite(T throwable,RenderManager renderManager,String[] urlPara,Action action,int code);
}提供响应处理链实现IResponseAdvice即可:
/**
* @Auther: hehh
* @Date: 2018/12/26 18:00
* @Description: 响应切面
*/
public interface IResponseAdvice<T extends Render> {
/**
* 排序
* @return
*/
default int sort(){ return Integer.MAX_VALUE;}
/**
* 是否支持
* @param clazz 响应的render calss
* @param t render
* @return
*/
boolean supports(Class<? extends Render> clazz, Render t);
/**
* 处理响应
* @param rqquestBody 响应render
* @param renderManager render工厂
* @param urlPara 请求url
* @param action 请求action
* @param controller 请求controller
* @return
*/
T beforeBodyWrite(Render rqquestBody, RenderManager renderManager,String[] urlPara,Action action, Controller controller);
}实现方案替换actionHander在不干扰源代码的情况下,插入自定义功能
/**
* @Auther: hehh
* @Date: 2018/12/26 17:41
* @Description:
*/
public class ActionHandlerAdivce extends ActionHandler {
private static final Log log = Log.getLog(ActionHandlerAdivce.class);
/** 响应处理类 */
public static Map<Class<? extends Render>,List<? extends IResponseAdvice<? extends Render>>> responseAdviceMap = new ConcurrentHashMap();
/**异常处理器*/
public static Map<Class<? extends Throwable>,IErrorRequestResponseAdvice> errorAdviceMap = new ConcurrentHashMap<>();
/***
* 获取异常处理器
* @param aClass
* @return
*/
private List<IErrorRequestResponseAdvice> getErrorAdvice(Class<? extends Throwable> aClass){
if(aClass == null){
return null;
}
List<Class<? extends Throwable>> temp = new ArrayList<>();
errorAdviceMap.keySet().forEach(new Consumer<Class<? extends Throwable>>() {
@Override
public void accept(Class<? extends Throwable> bClass) {
if(bClass.isAssignableFrom(aClass) || bClass.equals(aClass)){
temp.add(bClass);
}
}
});
if(CollUtil.isEmpty(temp)){return null;}
List<Class<? extends Throwable>> sort = CollUtil.sort(temp, new Comparator<Class<? extends Throwable>>() {
@Override
public int compare(Class<? extends Throwable> o1, Class<? extends Throwable> o2) {
return o1.isAssignableFrom(o2) ? -1 : 1;
}
});
if(CollUtil.isEmpty(sort)){return null;}
List<IErrorRequestRequestAdvice> advice = new ArrayList<>();
sort.forEach(new Consumer<Class<? extends Throwable>>() {
@Override
public void accept(Class<? extends Throwable> cClass) {
advice.add(errorAdviceMap.get(cClass));
}
});
return advice;
}
/**
* handle
* 1: Action action = actionMapping.getAction(target)
* 2: new Invocation(...).invoke()
* 3: render(...)
*
* @param target
* @param request
* @param response
* @param isHandled
*/
@Override
public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
if (target.indexOf('.') != -1) {
return ;
}
isHandled[0] = true;
String[] urlPara = {null};
Action action = actionMapping.getAction(target, urlPara);
if (action == null) {
String qs = request.getQueryString();
String error = "404 Action Not Found: " + (qs == null ? target : target + "?" + qs);
if (log.isWarnEnabled()) {
log.warn(error);
}
List<IErrorRequestResponseAdvice> errorAdvice = getErrorAdvice(RenderException.class);
Render render = renderManager.getRenderFactory().getErrorRender(404).setContext(request, response);
if(CollUtil.isEmpty(errorAdvice)){
render.render();
return;
}else{
throw new RenderException(error);
}
}
/**跨域在前*/
if(!RequestBodyUtil.configurationCrossOrigin(action,request,response)){
renderManager.getRenderFactory().getJsonRender(new ErrorResult<>(Code.REST_ERROR,"请求错误")).setContext(request,response).render();
return;
}
RequestBodyUtil.resolutionBody(action,request);//解析body
Controller controller = null;
try {
controller = controllerFactory.getController(action.getControllerClass());
if (injectDependency) {com.jfinal.aop.Aop.inject(controller);}
CPI._init_(controller,action,request,response,urlPara[0]);
//TODO 进入拦截器前
if (devMode) {
if (ActionReporter.isReportAfterInvocation(request)) {
new Invocation(action, controller).invoke();
ActionReporter.report(target, controller, action);
} else {
ActionReporter.report(target, controller, action);
new Invocation(action, controller).invoke();
}
}
else {
new Invocation(action, controller).invoke();
}
Render render = controller.getRender();
if (render instanceof ForwardActionRender) {
String actionUrl = ((ForwardActionRender)render).getActionUrl();
if (target.equals(actionUrl)) {
throw new RuntimeException("The forward action url is the same as before.");
} else {
handle(actionUrl, request, response, isHandled);
}
return ;
}
if (render == null) {
render = renderManager.getRenderFactory().getDefaultRender(action.getViewPath() + action.getMethodName());
}
//TODO 响应前 执行响应处理链
if(MapUtil.isNotEmpty(responseAdviceMap)){
List<? extends IResponseAdvice<? extends Render>> iResponseAdvices = responseAdviceMap.get(render.getClass());
if(CollUtil.isNotEmpty(iResponseAdvices)){
for (IResponseAdvice<? extends Render> iResponseAdvice : iResponseAdvices) {
if(iResponseAdvice.supports(render.getClass(),render)){
Render beforeRender = iResponseAdvice.beforeBodyWrite(render, renderManager, urlPara, action, controller);
if(beforeRender == null){
throw new ResponseAdviceExceptor("响应处理异常:"+iResponseAdvice.getClass()+" beforeBodyWrite 方法不能返回 null.");
}
render = beforeRender;
}
}
}
}
render.setContext(request, response, action.getViewPath()).render();
} catch (Exception e) {
/**异常处理*/
List<IErrorRequestResponseAdvice> errorAdvice = getErrorAdvice(e.getClass());
if(CollUtil.isNotEmpty(errorAdvice)){
int code = e instanceof RenderException?404:(e instanceof ActionException?((ActionException)e).getErrorCode():500);
errorAdvice.forEach(new Consumer<IErrorRequestRequestAdvice>() {
@Override
public void accept(IErrorRequestRequestAdvice iErrorRequestRequestAdvice) {
if(iErrorRequestRequestAdvice.supports(e)){
Render render1 = iErrorRequestRequestAdvice.laterBodyWrite(e, renderManager, urlPara, action, code);
if(render1 != null){
render1.setContext(request,response).render();
return;
}
}
}
});
}else{
//TODO 异常响应不处理
if(e instanceof RenderException){
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(qs == null ? target : target + "?" + qs, e);
}
}else if(e instanceof ActionException){
handleActionException(target, request, response, action, (ActionException)e);
}else{
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(qs == null ? target : target + "?" + qs, e);
}
renderManager.getRenderFactory().getErrorRender(500).setContext(request, response, action.getViewPath()).render();
}
}
} finally {
if (controller != null) {
CPI._clear_(controller);
}
}
}
/**
* 抽取出该方法是为了缩短 handle 方法中的代码量,确保获得 JIT 优化,
* 方法长度超过 8000 个字节码时,将不会被 JIT 编译成二进制码
*
* 通过开启 java 的 -XX:+PrintCompilation 启动参数得知,handle(...)
* 方法(73 行代码)已被 JIT 优化,优化后的字节码长度为 593 个字节,相当于
* 每行代码产生 8.123 个字节
*/
private void handleActionException(String target, HttpServletRequest request, HttpServletResponse response, Action action, ActionException e) {
int errorCode = e.getErrorCode();
String msg = null;
if (errorCode == 404) {
msg = "404 Not Found: ";
} else if (errorCode == 400) {
msg = "400 Bad Request: ";
} else if (errorCode == 401) {
msg = "401 Unauthorized: ";
} else if (errorCode == 403) {
msg = "403 Forbidden: ";
}
if (msg != null) {
if (log.isWarnEnabled()) {
String qs = request.getQueryString();
msg = msg + (qs == null ? target : target + "?" + qs);
if (e.getMessage() != null) {
msg = msg + "\n" + e.getMessage();
}
log.warn(msg);
}
} else {
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(errorCode + " Error: " + (qs == null ? target : target + "?" + qs), e);
}
}
e.getErrorRender().setContext(request, response, action.getViewPath()).render();
}
}加载处理器的IPlugin
/**
* @Auther: hehh
* @Date: 2018/12/26 09:08
* @Description: 处理响应
*/
public class RequestAdivcePlugin implements IPlugin {
/**初始化 响应处理器*/
private void initRequestAdivce(){
ThreadUtil.excAsync(new Runnable() {
Set<Class<?>> validates = ClassUtil.scanPackageBySuper("",IResponseAdvice.class);
@Override
public void run() {
if(CollUtil.isNotEmpty(validates)){
Map<ResponseAdviceMapSort,IResponseAdvice> responseAdviceMap = new HashMap<>();
validates.forEach(new Consumer<Class<?>>() {
@Override
public void accept(Class<?> aClass) {
if(!ClassUtil.isAbstract(aClass) && !aClass.isInterface()){
Type t =aClass.getGenericInterfaces()[0];
//返回表示此类型实际类型参数的 Type 对象的数组
Type[]params = ((ParameterizedType) t).getActualTypeArguments();
Type param = params[0];
try {
IResponseAdvice iResponseAdvice = (IResponseAdvice) aClass.newInstance();
ResponseAdviceMapSort eesponseAdviceMapSort = new ResponseAdviceMapSort();
eesponseAdviceMapSort.setAClass((Class<? extends Render>) TypeUtil.getClass(param));
eesponseAdviceMapSort.setSort(iResponseAdvice.sort());
responseAdviceMap.put(eesponseAdviceMapSort,iResponseAdvice);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
});
if(MapUtil.isNotEmpty(responseAdviceMap)){
for (ResponseAdviceMapSort responseAdviceMapSort : responseAdviceMap.keySet()) {
Class<? extends Render> aClass = responseAdviceMapSort.getAClass();
if(!ActionHandlerAdivce.responseAdviceMap.containsKey(aClass)) {
List<? extends IResponseAdvice<? extends Render>> responseAdvice = getResponseAdvice(aClass, responseAdviceMap);
ActionHandlerAdivce.responseAdviceMap.put(aClass, responseAdvice);
}
}
}
}
}
},true);
}
/**
* 初始化异常处理
*/
private void initError(){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Set<Class<?>> validates = ClassUtil.
scanPackageBySuper("",IErrorRequestResponseAdvice.class);
if(CollUtil.isNotEmpty(validates)){
for (Class<?> aClass : validates) {
Type t =aClass.getGenericInterfaces()[0];
//返回表示此类型实际类型参数的 Type 对象的数组
Type[]params = ((ParameterizedType) t).getActualTypeArguments();
Type param = params[0];
try {
ActionHandlerAdivce.
errorAdviceMap.put((Class<? extends Throwable>)
TypeUtil.getClass(param),
(IErrorRequestResponseAdvice)aClass.newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
});
thread.start();
}
@Override
public boolean start() {
initRequestAdivce();
initError();
return true;
}
@Override
public boolean stop() {
return true;
}
/***
* 得到响应处理器
* @param clazz
* @param <T>
* @return
*/
private <T extends Render>
List<IResponseAdvice<T>> getResponseAdvice(Class<T> clazz,
Map<ResponseAdviceMapSort,IResponseAdvice> responseAdviceMap){
if(clazz == null || MapUtil.isEmpty(responseAdviceMap))
{ return null; }
/***
* 得到指定处理 T 的处理器
*/
List<ResponseAdviceMapSort> filter = new ArrayList<>();
responseAdviceMap.forEach(new BiConsumer<ResponseAdviceMapSort,
IResponseAdvice>() {
@Override
public void accept(ResponseAdviceMapSort responseAdviceMapSort,
IResponseAdvice iResponseAdvice) {
if (responseAdviceMapSort.getAClass().
isAssignableFrom(clazz)
|| responseAdviceMapSort.getAClass().equals(clazz)) {
filter.add(responseAdviceMapSort);
}
}
});
if(CollUtil.isEmpty(filter)){
return null;
}
/***
* 排序
*/
List<ResponseAdviceMapSort> sort =
CollUtil.sort(filter, new Comparator<ResponseAdviceMapSort>() {
/**compare方法大于0,就把前一个数和后一个数交换,
也就是把大的数放后面了,即所谓的升序了*/
@Override
public int compare(ResponseAdviceMapSort o1,
ResponseAdviceMapSort o2) {
return o1.getSort() - o2.getSort();
}
});
List<IResponseAdvice<T>> temp = new ArrayList<>();
sort.forEach(new Consumer<ResponseAdviceMapSort>() {
@Override
public void accept(ResponseAdviceMapSort responseAdviceMapSort) {
temp.add(responseAdviceMap.get(responseAdviceMapSort));
}
});
return temp;
}
}在config中替换原有的actionHander即可
/**
* 配置处理器 如在规模开发中 定制Handler来实现自定义的url映射
*/
public void configHandler(Handlers me) {
me.setActionHandler(new ActionHandlerAdivce());
}异常效果
异常(扑捉昨天的参数验证(action 与非action都可以))
**
* @Auther: Administrator
* @Date: 2018/10/8 16:40
* @Description:
*/
@Validated
public class PoemsService extends BaseService<Poems> {
public String aa(@Size(min = 5,msg = "名字长度不能小于5!") String aa){
return "xxx";
}
}
部分验证代码
/**得到校验类*/
ValidateAbstract iValidate = ValidateAbstract.validates.
get(parameterAnnotation.annotationType());
/**校验是否符合规则*/
if (iValidate.supports(method, parameter,
parameterAnnotation.annotationType())) {
/**校验*/
Result verify = iValidate.verify(parameterAnnotation,
inv.getArg(i), method, parameter);
/**code != 0 为失败 */
if (verify.getCode() != 0) {
if (takeError != null &&
Result.class.isAssignableFrom(method.getReturnType())) {
inv.setReturnValue(verify);
return;
}
throw new ValidateException(verify.getMsg());
//TODO 不是action而又没接管就直接报错
}
}
}
扑捉
**
* @Auther: hehh
* @Date: 2018/12/27 13:56
* @Description:
*/
public class ValidateErrorAdvice implements
IErrorRequestResponseAdvice<ValidateException,JsonRender>{
/**
* 验证支持
*
* @param throwable
*/
@Override
public boolean supports(ValidateException throwable) {
return true;
}
/**
* 异常处理
*
* @param throwable
* @param renderManager
* @param urlPara
* @param action
* @param code
*/
@Override
public JsonRender laterBodyWrite(ValidateException throwable,
RenderManager renderManager, String[] urlPara, Action action, int code) {
return (JsonRender)renderManager.getRenderFactory().
getJsonRender(new ErrorResult<>
(Code.PARAM_ERROR,throwable.getMessage()));
}
}效果

响应效果
扑捉自定义的result
/**
* @Auther: hehh
* @Date: 2018/12/27 09:54
* @Description: 处理json 有数据响应
*/
public class RequestJsonAdvice implements IResponseAdvice<JsonRender> {
/**
* 排序
*
* @return
*/
@Override
public int sort() {
return 0;
}
/**
* 是否支持
*
* @param clazz 响应的render calss
* @param jsonRender render
* @return
*/
@Override
public boolean supports(Class<? extends Render> clazz, Render jsonRender) {
boolean b = jsonRender != null && jsonRender != null && jsonRender.getClass().equals(clazz);
if(b){
JsonRender jsonRender1 = (JsonRender) jsonRender;
if(StrKit.notBlank(jsonRender1.getJsonText())){
JSONObject object = new JSONObject(jsonRender1.getJsonText());
if(null == object.getInt("code")){
b = false;
}
}
}
return b;
}
/**
* 处理响应
*
* @param rqquestBody 响应render
* @param renderManager render工厂
* @param urlPara 请求url
* @param action 请求action
* @param controller 请求controller
* @return
*/
@Override
public JsonRender beforeBodyWrite(Render rqquestBody, RenderManager renderManager, String[] urlPara, Action action, Controller controller) {
JsonRender rqquestBody1 = (JsonRender) rqquestBody;
System.out.println("============处理响应:"+rqquestBody1.getJsonText());
rqquestBody1 = new JsonRender("bbbbb");
return rqquestBody1;
}
}原响应
@Validated
@RequestBody
public void index(@NotBlank(msg = "不能为空啊!!!") String name){
renderJson(ps.aa(name));
}效果:

源码地址:https://gitee.com/heHouHui/jfinal_validated.git
有什么不对的地方,还请各位指正