从Struts版本2.1.8.1升级到2.3.16.3后,某些控制器的映射存在问题。升级之前所有设备都在工作,但是现在60个以上的控制器中有3个出现了下一个错误:


  错误[ActionComponent]无法执行操作://vendor-tree!index
  没有为名称空间/和操作名称vendor-tree!index映射的操作。 -[未知位置]


此操作必须在/vendor-tree!index中而不是在//vendor-tree!index中,但是我不明白为什么Struts只在错误的位置寻找这3个Controller。
我在每次请求时都将其称为所有这些控制器

 <#escape x as x?html>
    <@s.action name="vendor-tree!index" executeResult="true" />
 </#escape>



  <constant name="struts.enable.DynamicMethodInvocation" value="true" />它没有任何改变
  
  Struts2: method attribute in <s:submit> button doesn't work是另一种情况,无法解决此情况


struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <constant name="struts.ui.theme" value="xhtml"/>
    <constant name="struts.locale" value="bg_BG"/>
    <constant name="struts.ui.templateDir" value="template" />
    <constant name="struts.custom.i18n.resources" value="global, ajax, help, xhtml" />
    <constant name="struts.devMode" value="false" />
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <constant name="struts.action.extension" value="html,xhtml,,xml,json" />

    <bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="mymapper" class="stemo.ActionMapper.HierarchicalRestActionMapper"/>
    <constant name="struts.mapper.class" value="mymapper"/>

    <!--
     enable the NamedVariablePatternMatcher to enable {variables} in the action namespace
    -->
    <bean type="com.opensymphony.xwork2.util.PatternMatcher" name="namedVariablePatternMatcher"
          class="com.opensymphony.xwork2.util.NamedVariablePatternMatcher"/>
    <constant name="struts.patternMatcher" value="namedVariablePatternMatcher"/>
    <!--
    <constant name="struts.convention.action.checkImplementsAction" value="false"/>
    <constant name="struts.convention.action.checkAnnotation" value="false"/>
    <constant name="struts.convention.action.defaultMethodName" value="index"/>
    -->

    <constant name="struts.convention.action.suffix" value="Controller"/>
    <constant name="struts.convention.action.mapAllMatches" value="true"/>
    <constant name="struts.convention.default.parent.package" value="controllers"/>
    <constant name="struts.convention.result.path" value="/"/>

    <!-- constant name="struts.convention.package.locators.basePackage" value="stemo"/ -->
    <constant name="struts.convention.package.locators" value="controllers"/>

    <!--  Overwrite Convention -->


    <package name="controllers" extends="struts-default" namespace="/" >
        <interceptors>
            <interceptor name="storeMessages" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
            <!--interceptor name="messMessage" class="stemo.ActionMapper.RedirectMessageInterceptor"/ -->
            <interceptor name="cachingHeadersInterceptor" class="stemo.ActionMapper.CachingHeadersInterceptor"/>
            <interceptor name="myCookie" class="stemo.ActionMapper.CookiesInterceptor"/>
            <interceptor name="myLogger" class="stemo.ActionMapper.LoggerInterceptor"/>
            <interceptor-stack name="myStack">
                 <!-- interceptor-ref name="messMessage"/ -->
                <interceptor-ref name="storeMessages" >
                    <param name="operationMode">AUTOMATIC</param>
                </interceptor-ref>
                 <interceptor-ref name="myCookie"/>
                <interceptor-ref name="myLogger"/>
                <interceptor-ref name="defaultStack" />
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="myStack"/>
    </package>

    <!-- for JBoss -->
    <constant name="struts.convention.exclude.parentClassLoader" value="true" />
    <constant name="struts.convention.action.fileProtocols" value="jar,vfsfile,vfszip" />
    <constant name="struts.convention.classLoader.excludeParent" value="false" />


    <!-- for Struts version 2.3.18+ -->
    <constant name="struts.multipart.parser" value="jakarta-stream" />
    <constant name="struts.multipart.maxSize" value="50242880" />

    <!--
    <constant name="struts.freemarker.manager.classname" value="org.apache.struts2.views.freemarker.FreemarkerManager" />

     -->
    <constant name="struts.freemarker.manager.classname" value="customFreemarkerManager"/>
    <constant name="struts.freemarker.mru.max.strong.size" value="250" />
    <constant name="struts.freemarker.templatesCache.updateDelay" value="1800" />


    <package name="json" extends="json-default">
        <action name="brand-ajax" class="stemo.json.BrandAjaxController">
            <result type="json">
                <param name="root">model</param>
                <param name="excludeProperties">LHarakt, Harakt</param>
            </result>
        </action>

        <action name="vendor-ajax" class="stemo.json.VendorAjaxController">
            <result type="json">
                <param name="root">model</param>
                <param name="excludeProperties">LHarakt, Harakt</param>
            </result>
        </action>
    </package>
</struts>


问题控制者

package stemo.controllers;

import com.opensymphony.xwork2.ModelDriven;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.rest.DefaultHttpHeaders;
import org.apache.struts2.rest.HttpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import stemo.hibernate.ObjectUtils;
import stemo.hibernate.model.DAO.VendorDAO;
import stemo.hibernate.model.entity.Vendor;
import stemo.hibernate.model.filters.*;

import java.util.List;
import java.util.Map;


@Results({
        @Result(name = "success", type = "freemarker",  location = "/vendortree.ftl")
})
public class VendorTreeController implements ModelDriven<Object>, SessionAware
{

    private VendorDAO vendorDAO;
    private List<Vendor> vendors;

    private String sklad_check;
    private String promo_check;
    private String newprice_check;
    private String lowprice_check;
    private String newproduct_check;
    private String oldproduct_check;
    private String withgift_check;
    private String sch_check;

    private FilterManager filters = null;

    private Map<String, Object> sessionMap;


    @Autowired
    public void setVendorDAO(VendorDAO vendorDAO)
    {
        this.vendorDAO = vendorDAO;
    }


    private FilterManager initFilters()
    {
        if (filters != null)
        {
            return filters;
        }
        filters = new FilterManager();
        if (!ObjectUtils.isEmpty(sklad_check))
        {
            StoreFilter f = new StoreFilter();
            filters.addFilter(f);
        }

        if (!ObjectUtils.isEmpty(promo_check))
        {
            PromoFilter f = new PromoFilter();
            filters.addFilter(f);
        }

        if (!ObjectUtils.isEmpty(newproduct_check))
        {
            NewProductFilter f = new NewProductFilter();
            filters.addFilter(f);
        }

        if (!ObjectUtils.isEmpty(withgift_check))
        {
            ProductsWithGift f = new ProductsWithGift();
            filters.addFilter(f);
        }

        if (!ObjectUtils.isEmpty(newprice_check))
        {
            ProductsWithNewPrices f = new ProductsWithNewPrices();
            filters.addFilter(f);
        }

        if (!ObjectUtils.isEmpty(lowprice_check))
        {
            ProductsWithLowerPrices f = new ProductsWithLowerPrices();
            filters.addFilter(f);
        }

        if (!ObjectUtils.isEmpty(oldproduct_check))
        {
            OldProductsFilter f = new OldProductsFilter();
            filters.addFilter(f);
        }

        if (!ObjectUtils.isEmpty(sch_check))
        {
            SecondHandFilter f = new SecondHandFilter();
            filters.addFilter(f);
        }

        return filters;

    }


    public HttpHeaders index()
    {
        sklad_check = (String) sessionMap.get("sklad_check");
        promo_check= (String) sessionMap.get("promo_check");
        newprice_check = (String) sessionMap.get("newprice_check");
        lowprice_check = (String) sessionMap.get("lowprice_check");
        newproduct_check = (String) sessionMap.get("newproduct_check");
        oldproduct_check = (String) sessionMap.get("oldproduct_check");
        withgift_check = (String) sessionMap.get("withgift_check");
        sch_check = (String) sessionMap.get("sch_check");

        FilterManager filters = initFilters();
        vendors = vendorDAO.findAll(filters);
        return new DefaultHttpHeaders("success").disableCaching();
    }


    @Override
    public Object getModel()
    {
        return vendors;
    }

    @Override
    public void setSession(Map<String, Object> stringObjectMap)
    {
        sessionMap = stringObjectMap;
    }
}


工作控制器

package stemo.controllers;

import com.opensymphony.xwork2.ModelDriven;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.rest.DefaultHttpHeaders;
import org.apache.struts2.rest.HttpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import stemo.hibernate.model.DAO.PenaltyDAO;
import stemo.hibernate.model.entity.PenaltyInfo;
import stemo.hibernate.model.entity.User;
import stemo.hibernate.model.entity.date.MonthItem;

import java.util.List;
import java.util.Map;


@Results({
        @Result(name = "success", type = "freemarker", location = "/penalty_details.ftl"),
        @Result(name = "list", type = "freemarker", location = "/penalty_all_details.ftl"),
        @Result(name = "error", type = "redirect", location = "/products")
})
public class PenaltyController implements ModelDriven<Object>, SessionAware
{

    private Map<String, Object> sessionMap;
    private List<PenaltyInfo> penaltyInfo;
    private String date;
    private Double penalty;
    private PenaltyDAO penaltyDAO;


    @Autowired
    public void setPenaltyDAO(PenaltyDAO penaltyDAO)
    {
        this.penaltyDAO = penaltyDAO;
    }


    @Override
    public void setSession(Map<String, Object> stringObjectMap)
    {
        this.sessionMap = stringObjectMap;
    }

    @Override
    public Object getModel()
    {
        return penaltyInfo;
    }

    public String getDate()
    {
        return date;
    }

    public void setDate(String date)
    {
        this.date = date;
    }

    public Double getPenalty()
    {
        return penalty;
    }

//GET

    public HttpHeaders index()
    {
        User user = (User) sessionMap.get("user");
        if ((user != null))
        {

            //months = MonthItem.getMonths(null);
            if (date == null)
            {
                date = MonthItem.getCurrent();
            }
            penaltyInfo = penaltyDAO.getList(user,MonthItem.toDate(date));
            penalty = penaltyDAO.getPenalty(user,MonthItem.toDate(date));
            return new DefaultHttpHeaders("success").disableCaching();
        }
        else
        return new DefaultHttpHeaders("error").disableCaching();
    }

    public HttpHeaders list()
    {
        User user = (User) sessionMap.get("user");
        if ((user != null))
        {
            penaltyInfo = penaltyDAO.getAllList(user);
            penalty = user.getPenalty();
            return new DefaultHttpHeaders("list").disableCaching();
        }
        else
        return new DefaultHttpHeaders("error").disableCaching();
    }

}


自定义映射器为

public class HierarchicalRestActionMapper extends RestActionMapper {

    protected void parseNameAndNamespace(String uri, ActionMapping mapping, ConfigurationManager configManager) {

        Set<String> actions = new HashSet<String>();
        PackageConfig packageConfig;

        Configuration configuration = configManager.getConfiguration();

        // get the current set of action names in our packages of interest
        Map<String, PackageConfig> packageConfigs = configuration.getPackageConfigs();
        for (Map.Entry<String, PackageConfig> packageEntry : packageConfigs.entrySet()) {
            packageConfig = packageEntry.getValue();
            actions.addAll(packageConfig.getActionConfigs().keySet());
        }

        // parse the uri into namespace, action, method and id
        Map<String, String> params = URIActionMethodParser.process(uri, actions);

        if (params != null) {
            // update the mapping
            mapping.setNamespace(params.get("namespace"));
            params.remove("namespace");
            mapping.setName(params.get("action"));
            params.remove("action");
            mapping.setParams((Map) params);
        }
    }
}


你知道为什么吗?

最佳答案

当我在没有输入方法<@s.action name="vendor-tree" executeResult="true"/>的情况下执行动作标签时,Struts会抛出缺少的执行方法错误。我重命名了我的输入法来执行,现在一切正常。

关于java - Struts 2-升级后错误的 Controller 映射,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30558462/

10-13 04:57