package com.aggrepoint.winlet.spring; import java.net.URLEncoder; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import com.aggrepoint.utils.StringUtils; import com.aggrepoint.winlet.ContextUtils; import com.aggrepoint.winlet.LogInfoImpl; import com.aggrepoint.winlet.ReqInfoImpl; import com.aggrepoint.winlet.RespHeaderConst; import com.aggrepoint.winlet.form.FormImpl; import com.aggrepoint.winlet.spring.annotation.Action; import com.aggrepoint.winlet.spring.annotation.Unspecified; import com.aggrepoint.winlet.spring.annotation.Window; import com.aggrepoint.winlet.spring.def.ControllerMethodDef; import com.aggrepoint.winlet.spring.def.ReturnDef; import com.aggrepoint.winlet.spring.def.WinletDef; /** * <pre> * Winlet的View和Action方法的返回处理 * * 1. 如果返回值为空,则不处理 * * </pre> * * @author Jiangming Yang (yangjm@gmail.com) */ public class WinletHandlerInterceptor implements HandlerInterceptor { static final String WINLET_FORM_RESP = "WINLET_FORM_RESP:"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { LogInfoImpl.getLogInfo(request, response).setHandler(handler); // 表单处理 if (handler instanceof HandlerMethod) { HandlerMethod hm = (HandlerMethod) handler; Class<? extends Exception> exp = ContextUtils .getAuthorizationEngine(request).check(hm.getBeanType(), hm.getMethod()); if (exp != null) { if (exp == Unspecified.class) return false; throw exp.newInstance(); } WinletDef def = WinletDef.getDef(hm.getBeanType()); if (def == null) // 不是Winlet return true; Action action = AnnotationUtils.findAnnotation(hm.getMethod(), Action.class); // 不是Action ReqInfoImpl ri = ContextUtils.getReqInfo(); if (action == null) { if (ri.isFromContainer() && !ri.isWinInclude()) { // container中只允许调用action,不能调用window // action的JSP include其他window是可以的 return false; } return true; } FormImpl form = ((FormImpl) ri.getForm()); form.validate(ri, hm.getBean(), hm.getMethod()); } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { LogInfoImpl li = LogInfoImpl.getLogInfo(request, response) .setHandler(handler).setModelAndView(modelAndView); if (handler instanceof HandlerMethod) { HandlerMethod hm = (HandlerMethod) handler; String viewName = null; if (modelAndView == null) viewName = ""; else viewName = modelAndView.getViewName(); if (viewName == null) // 直接指定了View对象而不是ViewName,不是Winlet的开发方式,不加处理 return; ReturnDef rd = null; WinletDef def = WinletDef.getDef(hm.getBeanType()); if (def == null) { // 不是Winlet // 处理普通Spring MVC Controller方法上定义的@Return ControllerMethodDef mdef = ControllerMethodDef.getDef(hm .getMethod()); rd = PsnReturnDefFinder.getReturnDef(mdef .getReturnDef(viewName)); if (rd != null) { li.setReturnDef(rd); if (rd.getViewName() != null && modelAndView != null) modelAndView.setViewName(rd.getViewName()); } return; } ContextUtils.setHandlerMethod(request, hm); Window win = null; Action action = null; win = AnnotationUtils.findAnnotation(hm.getMethod(), Window.class); if (win != null) rd = PsnReturnDefFinder.getReturnDef(def.getWindow(win.value()) .getReturnDef(viewName)); else { action = AnnotationUtils.findAnnotation(hm.getMethod(), Action.class); if (action != null) rd = PsnReturnDefFinder.getReturnDef(def.getAction( action.value()).getReturnDef(viewName)); } if (win == null && action == null) // 被调用的既不是Window也不是Action return; ReqInfoImpl reqInfo = ContextUtils.getReqInfo(); boolean cache = false; if (rd != null) { li.setReturnDef(rd); FormImpl form = (FormImpl) reqInfo.getForm(); reqInfo.setReturnDef(rd); if (action != null && reqInfo.isValidateField()) { // 表单字段校验,返回校验结果 response.setHeader("Content-Type", "application/json; charset=UTF-8"); response.getOutputStream().write( StringUtils.fixJson(form.getJsonChanges()) .getBytes("UTF-8")); if (modelAndView != null) modelAndView.clear(); return; } if (rd.getViewName() != null) if (modelAndView != null) modelAndView.setViewName(rd.getViewName()); if (rd.getTitle() != null) response.setHeader(RespHeaderConst.HEADER_TITLE, URLEncoder.encode(rd.getTitle(), "UTF-8")); if (action != null) { if (rd.getUpdate() != null) { response.setHeader(RespHeaderConst.HEADER_UPDATE, rd.getUpdate()); } if (rd.getTarget() != null) { response.setHeader(RespHeaderConst.HEADER_TARGET, rd.getTarget()); } if (rd.cache()) { response.setHeader(RespHeaderConst.HEADER_CACHE, "yes"); cache = true; } if (rd.getMsg() != null && !"".equals(rd.getMsg())) response.setHeader(RespHeaderConst.HEADER_MSG, URLEncoder.encode(rd.getMsg(), "UTF-8")); if (rd.isDialog()) response.setHeader(RespHeaderConst.HEADER_DIALOG, "yes"); else { if (!viewName.startsWith(Const.REDIRECT) && form.isValidateForm() && form.hasError(true)) { // 表单校验出错 response.getOutputStream().write( (WINLET_FORM_RESP + StringUtils .fixJson(form.getJsonChanges())) .getBytes("UTF-8")); if (modelAndView != null) modelAndView.clear(); return; } } } } if (modelAndView != null && modelAndView.getViewName() != null) { if (modelAndView.getViewName().startsWith(Const.REDIRECT)) { response.setHeader(RespHeaderConst.HEADER_REDIRECT, modelAndView.getViewName().substring(9)); modelAndView.clear(); return; } if (!"".equals(modelAndView.getViewName())) { if (modelAndView.getViewName().indexOf("/") != 0) { modelAndView.setViewName(def.getViewPath() + "/" + modelAndView.getViewName()); return; } } } if (modelAndView != null) { if (!reqInfo.isFromContainer() && !cache && (modelAndView.getViewName() == null || "" .equals(modelAndView.getViewName())) && action != null) response.getOutputStream().write( reqInfo.getWindowContent(null, null, null, modelAndView.getModel(), null).getBytes( "UTF-8")); if ("".equals(modelAndView.getViewName())) modelAndView.clear(); } } } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { LogInfoImpl.getLogInfo(request, response).setException(ex).complete(); } }