iBATIS demo jpetstore 对 struts 的灵活应用 。
demo中为了减少application 对struts的依赖性,主要做了以下三方面:
1.BeanAction类,demo中将业务处理从原先继承Action类的处理类中分离出来,将原先分离的Action和Form整合在一起作为bean。demo的struts-config.xml中所有请求转向BeanAction,BeanAction 根据请求路径或struts-config.xml中action元素中parameter属性指定的方法名,利用java反射调用bean中的业务处理方法,哪么如何找到bean?。
2.bean 继承自 BaseBean ,BaseBean 继承自 struts 中的ValidatorActionForm类,BaseBean 对 ValidatorActionForm 中的 reset()和validate()方法进行的重写,生成无参数的 reset()和validate()方法由子类重载,减少子类对struts的依赖。这里的无参数 reset()以及bean中的业务处理方法如何获得 HttpServletRequest等参数哪?
3.ActionContext类, BeanAction类利用java.lang.ThreadLocal类将参数绑定到请求的线程中.ActionContext对这些操作进行了封装,在bean中可以通过ActionContext的静态方法获取请求参数。
在demo的struts-config.xml文件中
<action path="/shop/switchSearchListPage" type="org.apache.struts.beanaction.BeanAction" name="catalogBean" scope="session" parameter="switchProductListPage" validate="false"> <forward name="success" path="/catalog/SearchProducts.jsp"/> </action> <action path="/shop/viewCategory" type="org.apache.struts.beanaction.BeanAction" name="catalogBean" scope="session" validate="false"> <forward name="success" path="/catalog/Category.jsp"/> </action>
public class BeanAction extends Action { private static final String NO_METHOD_CALL = "*"; private static final String SUCCESS_FORWARD = "success"; public final ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String forward = SUCCESS_FORWARD; try { if (!(form instanceof BaseBean)) { if (form != null) { throw new BeanActionException("The form for mapping '" + mapping.getPath() + "' named '" + mapping.getName() + "' was not an instance of BaseBean. BeanAction requires an BaseBean instance."); } else { throw new BeanActionException("The form for mapping '" + mapping.getPath() + "' named '" + mapping.getName() + "' was null. BeanAction requires an BaseBean instance."); } } BaseBean bean = (BaseBean) form; ActionContext.initCurrentContext(request, response); if (bean != null) { // Explicit Method Mapping Method method = null; String methodName = mapping.getParameter(); if (methodName != null && !NO_METHOD_CALL.equals(methodName)) { try { method = bean.getClass().getMethod(methodName, null); synchronized (bean) { forward = bean.getInterceptor().intercept(new ActionInvoker(bean, method)); } } catch (Exception e) { throw new BeanActionException("Error dispatching bean action via method parameter ('" + methodName + "'). Cause: " + e, e); } } // Path Based Method Mapping if (method == null && !NO_METHOD_CALL.equals(methodName)) { methodName = mapping.getPath(); if (methodName.length() > 1) { int slash = methodName.lastIndexOf("/") + 1; methodName = methodName.substring(slash); if (methodName.length() > 0) { try { method = bean.getClass().getMethod(methodName, null); synchronized (bean) { forward = bean.getInterceptor().intercept(new ActionInvoker(bean, method)); } } catch (Exception e) { throw new BeanActionException("Error dispatching bean action via URL pattern ('" + methodName + "'). Cause: " + e, e); } } } } } } catch (Exception e) { forward = "error"; request.setAttribute("BeanActionException", e); } return mapping.findForward(forward); }}
public class ActionContext { private static final ThreadLocal localContext = new ThreadLocal(); private HttpServletRequest request; private HttpServletResponse response; private Map cookieMap; private Map parameterMap; private Map requestMap; private Map sessionMap; private Map applicationMap; public ActionContext() { cookieMap = new HashMap(); parameterMap = new HashMap(); requestMap = new HashMap(); sessionMap = new HashMap(); applicationMap = new HashMap(); } static void initCurrentContext(HttpServletRequest request, HttpServletResponse response) { ActionContext ctx = getActionContext(); ctx.request = request; ctx.response = response; ctx.cookieMap = null; ctx.parameterMap = null; ctx.requestMap = null; ctx.sessionMap = null; ctx.applicationMap = null; } public Map getCookieMap() { if (cookieMap == null) { cookieMap = new CookieMap(request); } return cookieMap; } ············· public HttpServletRequest getRequest() { return request; } public HttpServletResponse getResponse() { return response; } public static ActionContext getActionContext() { ActionContext ctx = (ActionContext) localContext.get(); if (ctx == null) { ctx = new ActionContext(); localContext.set(ctx); } return ctx; }}
public final void reset(ActionMapping mapping, ServletRequest request) { ActionContext.initCurrentContext((HttpServletRequest) request, null); reset(); }