Java tutorial
/* * Copyright 2011-2016 ZXC.com All right reserved. This software is the confidential and proprietary information of * ZXC.com ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into with ZXC.com. */ package com.ms.commons.summer.web.handler; import java.lang.reflect.Method; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.ModelMap; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.LastModified; import org.springframework.web.servlet.mvc.multiaction.MethodNameResolver; import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException; import org.springframework.web.util.UrlPathHelper; import org.springframework.web.util.WebUtils; import com.ms.commons.log.LoggerFactoryWrapper; import com.ms.commons.summer.web.annotations.ControllerAction; import com.ms.commons.summer.web.annotations.ValidationToken; import com.ms.commons.summer.web.exception.ValidationException; import com.ms.commons.summer.web.servlet.mvc.ComponentMethodController; import com.ms.commons.summer.web.servlet.result.Forward; import com.ms.commons.summer.web.servlet.result.Redirect; import com.ms.commons.summer.web.servlet.result.View; import com.ms.commons.summer.web.servlet.result.WebResult; import com.ms.commons.summer.web.servlet.result.WebResultModelAndView; import com.ms.commons.summer.web.servlet.result.mime.MimeModelAndView; import com.ms.commons.summer.web.servlet.result.mime.MimeResult; import com.ms.commons.summer.web.view.Widget; import com.ms.commons.summer.web.view.velocity.SummerVelocityLayoutView; /** * @author zxc Apr 12, 2013 4:12:04 PM */ public class ComponentMethodHandlerAdapter implements HandlerAdapter { public static final String MODEL_KEY = "_$_MODEL_KEY_$_"; public static final String NAMESPACE_KEY = "_$_NAMESPACE_KEY_$_"; private UrlPathHelper urlPathHelper = new UrlPathHelper(); private MethodNameResolverAdapter methodNameResolverAdapter = new MethodNameResolverAdapter();; private static final Logger logger = LoggerFactoryWrapper.getLogger(ComponentMethodHandlerAdapter.class); public boolean supports(Object handler) { return (handler instanceof ComponentMethodController); } @SuppressWarnings("unchecked") public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ExtendedModelMap model = new ExtendedModelMap(); ModelMap map = (ModelMap) request.getAttribute(MODEL_KEY); if (map != null) { model.putAll(map); } ComponentMethodController controller = (ComponentMethodController) handler; injectServletObject(controller, request, response); Object result = handleRequest(handler, request, response, model); // ModelAndView ModelAndView mv = buildModelAndView(request, response, result, model); request.setAttribute(MODEL_KEY, model); String ns = getNameSpace(request, controller, result); String viewName = buildViewName(request, mv, ns); mv.setViewName(viewName); return mv; } /** * @return the methodNameResolverAdapter */ public MethodNameResolverAdapter getMethodNameResolverAdapter() { return methodNameResolverAdapter; } /** * @param methodNameResolverAdapter the methodNameResolverAdapter to set */ public void setMethodNameResolverAdapter(MethodNameResolverAdapter methodNameResolverAdapter) { this.methodNameResolverAdapter = methodNameResolverAdapter; } private Object handleRequest(Object handle, HttpServletRequest request, HttpServletResponse response, ExtendedModelMap model) throws Exception { String methodName = getHandlerMethodName(request); if (StringUtils.isEmpty(methodName)) { return null; } Method invokeMethod = getInvokeMethod(handle, methodName); if (invokeMethod == null) { return null; } return invokeNamedMethod(handle, invokeMethod, model, request, response); } /** * @param request * @return */ private String getHandlerMethodName(HttpServletRequest request) { if (isWidget(request)) { String uri = String.valueOf(request.getAttribute(Widget.WIDGET_URI)); return WebUtils.extractFilenameFromUrlPath(uri); } return getInvokeMethodName(request); } /** * ??? * * @param request * @return */ protected String getInvokeMethodName(HttpServletRequest request) { try { String lookupPath = urlPathHelper.getLookupPathForRequest(request); MethodNameResolver methodNameResolver = methodNameResolverAdapter.getMethodNameResolver(lookupPath); return methodNameResolver.getHandlerMethodName(request); } catch (NoSuchRequestHandlingMethodException ex) { return null; } } private Method getInvokeMethod(Object handle, String methodName) { try { Method[] methods = handle.getClass().getMethods(); Method invokeMethod = null; for (Method method : methods) { if (method.getName().equals(methodName) && method.getAnnotation(ControllerAction.class) != null) { invokeMethod = method; } } if (invokeMethod == null) { return null; } return invokeMethod; } catch (SecurityException e) { return null; } } /** * ?widget * * @param request * @return */ protected final boolean isWidget(HttpServletRequest request) { Object o = request.getAttribute(Widget.IS_WIDGET); if (o != null && "true".equals(o.toString())) { return true; } return false; } @SuppressWarnings("unchecked") private Object invokeNamedMethod(Object handle, Method method, ExtendedModelMap model, HttpServletRequest request, HttpServletResponse response) throws Exception { Object object = checkToken(handle, method, model, request, response); if (object != null) { return object; } Object[] args = DataBinderUtil.getArgs(method, model, request, response, this.getClass()); // try { return method.invoke(handle, args); } catch (Exception e) { Throwable cause = e.getCause(); if (cause != null && cause instanceof Exception) { throw (Exception) cause; } throw e; } } /** * token? * * @param method * @param model * @param request * @param response * @param c * @return */ private Object checkToken(Object handle, Method method, Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { ValidationToken validation = method.getAnnotation(ValidationToken.class); if (validation == null) { return null; } Method validationMethod = getValidationMethod(validation, handle.getClass()); if (validationMethod == null) { String msg = "??:[" + validation.methodName() + "]!!"; logger.error(msg); throw new ValidationException(msg); } String content = validation.content(); // try { return validationMethod.invoke(handle, model, content); } catch (Exception e) { Throwable cause = e.getCause(); if (cause != null && cause instanceof Exception) { throw (Exception) cause; } throw e; } } private Method getValidationMethod(ValidationToken validation, Class<?> c) { String methodName = null; if (StringUtils.isNotEmpty(validation.methodName())) { methodName = validation.methodName(); } else { methodName = validation.type().getMethodName(); } try { Method method = c.getMethod(methodName, Map.class, String.class); if (method == null) { return null; } Class<?> returnType = method.getReturnType(); if (!returnType.isAssignableFrom(WebResult.class)) { return null; } return method; } catch (SecurityException e) { } catch (NoSuchMethodException e) { } return null; } private void injectServletObject(ComponentMethodController controller, HttpServletRequest request, HttpServletResponse response) { Class<? extends ComponentMethodController> clazz = controller.getClass(); try { // HttpServletRequest Method method = clazz.getMethod("setRequest", HttpServletRequest.class); if (method != null) { method.invoke(controller, request); } } catch (Exception e) { } try { // HttpServletResponse Method method = clazz.getMethod("setResponse", HttpServletResponse.class); if (method != null) { method.invoke(controller, response); } } catch (Exception e) { } } /** * ??,??<br> * rquest? ?result? ?controller <br> * 2011.9.12<br> * fixed:???vm,widget????<br> * ??requesthttp???<br> * widget???controller??<br> * forwardrquest?? * * @param controller * @param result * @return * @see ComponentMethodHandlerAdapter#buildModelAndView(HttpServletRequest, HttpServletResponse, Object, * ExtendedModelMap) */ private String getNameSpace(HttpServletRequest request, ComponentMethodController controller, Object result) { // ?requestwidget Object o = request.getAttribute(NAMESPACE_KEY); if (o != null && o instanceof String) { String ns = (String) o; if (ns.trim().length() > 0) { return ns; } } // ??? String ns = null; if (result instanceof View) { String na = ((View) result).getNameSpace(); if (na != null && na.length() != 0) { ns = na; } } if (ns == null) { ns = controller.getNameSpace(); } request.setAttribute(NAMESPACE_KEY, ns); return ns; } private ModelAndView buildModelAndView(HttpServletRequest request, HttpServletResponse response, Object result, ExtendedModelMap model) { if (result instanceof WebResult) { // mime if (result instanceof MimeResult) { return new MimeModelAndView((MimeResult) result); } WebResult webResult = (WebResult) result; // ??,model? if (result instanceof Redirect) { model.clear(); } else { model.addAllAttributes(webResult.getParameters()); if (result instanceof View) { View view = (View) result; if (!view.isUselayout()) { request.setAttribute(SummerVelocityLayoutView.USE_LAYOUT, "false"); } } // forward,request?? else if (result instanceof Forward) { request.removeAttribute(NAMESPACE_KEY); } } return new WebResultModelAndView(webResult.getView()).addAllObjects(model); } else { return new ModelAndView().addAllObjects(model); } } /** * @param request * @param mv * @return */ private String buildViewName(HttpServletRequest request, ModelAndView mv, String nameSpace) { Object o = request.getAttribute(Widget.IS_WIDGET); boolean isWidget = o != null && "true".equals(o.toString()); String viewName = mv.getViewName(); if (viewName == null) { if (isWidget) { viewName = String.valueOf(request.getAttribute(Widget.WIDGET_URI)); } else { UrlPathHelper helper = new UrlPathHelper(); viewName = helper.getLookupPathForRequest(request); } } if (viewName.startsWith(WebResult.REDIRECT_URL_PREFIX)) { return viewName; } if (viewName.startsWith(WebResult.FORWARD_URL_PREFIX)) { return viewName; } // ?vm,?(.xxx) int index = viewName.indexOf("."); if (index != -1) { viewName = viewName.substring(0, index); } // : // /??/view/xxx/yyy/zzz // /??/widget/xxx/yyy/zzz if (nameSpace != null && nameSpace.length() > 0) { nameSpace = "/" + nameSpace; } else { nameSpace = ""; } if (isWidget) { return nameSpace + SummerVelocityLayoutView.DEFAULT_WIDGET_DIRECTORY + viewName; } else { return nameSpace + SummerVelocityLayoutView.DEFAULT_VIEW_DIRECTORY + viewName; } } public long getLastModified(HttpServletRequest request, Object handler) { if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } }