Cet article vous présente principalement les connaissances liées à l'appel à l'action webwork à travers trois aspects. Les trois aspects sont :
1. Cette partie de la relation de classe-cadre
2.Webwork obtient et emballe les paramètres Web
3.DefaultActionProxyFactory, DefaultActionProxy, DefaultActionInvocation
En cours de route, nous commençons enfin à résumer les principales classes métiers de webwork. Webwork reconditionne les paramètres Web transmis par le client, exécute la classe métier Action et renvoie les résultats de l'exécution. Cette analyse du code source correspond au flux. du framework WebWork dans la figure ci-dessous. La case rouge dans l'image.
1. Cette partie de la relation de classe-cadre
2.Webwork obtient et emballe les paramètres Web
•Chaque framework Web regroupe plus ou moins les paramètres de requête Web pour votre propre commodité, et bien sûr, le travail Web ne fait pas exception.
•Méthode de saisie de Webwork pour chaque demande de réponse :
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException { try { if (encoding != null) { try { request.setCharacterEncoding(encoding); } catch (Exception localException) { } } if (locale != null) { response.setLocale(locale); } if (this.paramsWorkaroundEnabled) { request.getParameter("foo"); } request = wrapRequest(request); //封装 request请求 serviceAction(request, response, getNameSpace(request), getActionName(request), getRequestMap(request), getParameterMap(request), getSessionMap(request), getApplicationMap()); } catch (IOException e) { String message = "Could not wrap servlet request with MultipartRequestWrapper!"; log.error(message, e); sendError(request, response, , new ServletException(message, e)); } }
•Accepter les paramètres de requête et de réponse, et encapsuler les paramètres de requête. Cette encapsulation est principalement destinée au traitement spécial des requêtes multimédias, telles que les demandes de téléchargement de fichiers dans des projets, l'exportation de divers types de fichiers, etc...
•Après avoir enveloppé la requête, la méthode de service appelle la méthode ServletDispatche.serviceAction() et appelle les six méthodes getApplicationMap, getSessionMap, getRequestMap, getParameterMap, getActionName et getNameSpace pour démarrer les préliminaires avant d'appeler la logique métier Action.
•La méthode getNameSpace est utilisée pour obtenir l'espace de noms auquel appartient une action. Par exemple : "/my/MyAction.action" renvoie "/my". L'implémentation spécifique est la suivante :
protected String getNameSpace(HttpServletRequest request){ String servletPath = request.getServletPath(); return getNamespaceFromServletPath(servletPath); } public static String getNamespaceFromServletPath(String servletPath){ servletPath = servletPath.substring(, servletPath.lastIndexOf("/")); return servletPath; }
•getActionName renvoie le nom de l'action demandée. Par exemple : "MyAction.action" renvoie "MyAction". L'implémentation spécifique est la suivante :
protected String getActionName(HttpServletRequest request){ String servletPath = (String)request.getAttribute("javax.servlet.include.servlet_path"); if (servletPath == null) { servletPath = request.getServletPath(); } return getActionName(servletPath); } protected String getActionName(String name){ int beginIdx = name.lastIndexOf("/"); int endIdx = name.lastIndexOf("."); return name.substring(beginIdx == - ? : beginIdx + , endIdx == - ? name.length() : endIdx); }
• La méthode getRequestMap renvoie une Map contenant tous les attributs de la requête. La classe d'implémentation spécifique est RequestMap. Le code spécifique est le suivant :
protected Map getRequestMap(HttpServletRequest request){ return new RequestMap(request); }
•La méthode getParameterMap renvoie une Map contenant tous les paramètres de la requête. Le code spécifique est le suivant :
protected Map getParameterMap(HttpServletRequest request) throws IOException{ return request.getParameterMap(); }
•La méthode getSessionMap renvoie une Map contenant tous les attributs de la session. La classe d'implémentation spécifique est SessionMap. Le code spécifique est le suivant :
protected Map getSessionMap(HttpServletRequest request){ return new SessionMap(request); }
•La méthode getApplicationMap renvoie une Map contenant tous les attributs dans Application. La classe d'implémentation spécifique est ApplicationMap. Le code spécifique est le suivant :
protected Map getApplicationMap(){ return new ApplicationMap(getServletContext()); }
•La raison pour laquelle WebWork encapsule les attributs et paramètres de la requête, les attributs de la session et les attributs de l'application dans une carte est uniquement pour la commodité de sa propre utilisation.
public void serviceAction(HttpServletRequest request, HttpServletResponse response, String namespace, String actionName, Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap) { HashMap extraContext = createContextMap(requestMap, parameterMap, sessionMap, applicationMap, request, response, getServletConfig()); extraContext.put("com.opensymphony.xwork.dispatcher.ServletDispatcher", this); OgnlValueStack stack = (OgnlValueStack) request.getAttribute("webwork.valueStack"); if (stack != null) { extraContext.put("com.opensymphony.xwork.util.OgnlValueStack.ValueStack", new OgnlValueStack(stack)); } try { ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext); request.setAttribute("webwork.valueStack", proxy.getInvocation().getStack()); proxy.execute(); if (stack != null) { request.setAttribute("webwork.valueStack", stack); } } catch (ConfigurationException e) { log.error("Could not find action", e); sendError(request, response, 404, e); } catch (Exception e) { log.error("Could not execute action", e); sendError(request, response, 500, e); } }
•Tout d'abord, ServiceAction appelle createContextMap pour créer le contexte d'action (extraContext). Il encapsule les objets liés à JavaServlet et les place dans des objets extraContext Map.
• Vérifiez ensuite s'il existe une pile de valeurs disponible dans la requête précédente. Si tel est le cas, placez-la dans l'objet extraContext Map pour l'utiliser dans cette requête.
•ActionContext (com.opensymphony.xwork.ActionContext) est le contexte dans lequel Action est exécutée. Le contexte peut être considéré comme un conteneur (en fait, notre conteneur ici n'est qu'une carte. Il stocke les informations dont Action a besoin). à utiliser lors de l'exécution sur l'objet.
• ServletActionContext (com.opensymphony.webwork. ServletActionContext), cette classe hérite directement d'ActionContext, qui fournit un accès direct aux objets liés à JavaServlet.
•La fonction principale d'OgnlValueStack est d'accéder aux propriétés des objets via un langage d'expression.
3.DefaultActionProxyFactory, DefaultActionProxy, DefaultActionInvocation
Les préliminaires sont enfin terminés, et les trois frères appelés par Action sont sur le point de monter sur scène pour effectuer l'opération la plus importante. Il s'agit des trois lignes de code suivantes, qui sont les mêmes que le code de lecture de xwork.xml. avant de demander le saut en Webwork Learning Path (5) Écriture et design très similaires :
ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext); request.setAttribute("webwork.valueStack", proxy.getInvocation().getStack());
proxy.execute(); •通过由前面获得的namespace、actionName、extraContext 创建调用代理 ActonProxy 实例,这里也就是 DefaultActionProxy,之后调用 了 ActionProxy.execute 方法来执行我们逻辑Action.execute。
•ActionProxy是一个接口,ActionProxyFactory则是一个抽象类,默认情况下它们是通过 DefaultActionProxy和DefaultActionProxyFactory来完成操作的。
•在 ActionProxyFactory 中有一个静态变量 factory ,它指向的是一个 DefaultActionProxyFactory 实例,代码如下:
static ActionProxyFactory factory = new DefaultActionProxyFactory(); public static void setFactory(ActionProxyFactory factory){ factory = factory; } public static ActionProxyFactory getFactory(){ return factory; }
• DefaultActionProxyFactory 的 createActionProxy 方法返回了 DefaultActionProxy 实例。
public ActionProxy createActionProxy(String namespace, String actionName, Map extraContext)throws Exception { setupConfigIfActionIsCommand(namespace, actionName); return new DefaultActionProxy(namespace, actionName, extraContext, true); } •DefaultActionProxy的构造函数 protected DefaultActionProxy(String namespace, String actionName, Map extraContext, boolean executeResult) throws Exception{ if (LOG.isDebugEnabled()) { LOG.debug("Creating an DefaultActionProxy for namespace " + namespace + " and action name " + actionName); } this.actionName = actionName; this.namespace = namespace; this.executeResult = executeResult; this.extraContext = extraContext; this.config = ConfigurationManager.getConfiguration().getRuntimeConfiguration().getActionConfig(namespace, actionName); if (this.config == null) { String message; String message; if ((namespace != null) && (namespace.trim().length() > 0)) { message = LocalizedTextUtil.findDefaultText("xwork.exception.missing-package-action", Locale.getDefault(), new String[] { namespace, actionName }); } else { message = LocalizedTextUtil.findDefaultText("xwork.exception.missing-action", Locale.getDefault(), new String[] { actionName }); } throw new ConfigurationException(message); } prepare(); }
•将传入的名称空间、 Action 的名字等参数赋予本地变量,接着通过 ConfigurationManager 获得当前请求的 Action 的配置信息[这里在5中已经描述过]。接着调用自身的 prepare 方法创建一个 ActionInvocation 对象赋予自身变量 invocation。在之后的 execute 方法中通过操纵invocation 来实现我们自己写的Action 的调用。
protected void prepare() throws Exception { this.invocation = ActionProxyFactory.getFactory().createActionInvocation(this, this.extraContext); }
以上所示是针对Webwork中Action 调用 的相关知识,希望对大家有所帮助。