如何将 URL 中的路径参数映射到 Struts 2 中的操作

How to map a path parameters in URL to the action in Struts 2

提问人:Alireza Fattahi 提问时间:3/17/2023 最后编辑:Alireza Fattahi 更新时间:4/5/2023 访问量:413

问:

我们在 Tomcat 9 上使用 Struts 6.2,并将所有扩展映射到操作,例如正确映射到操作。.actionsave-user.action

Web 应用程序需要处理此路径参数(路径变量),例如:.如您所见,参数是通过 URL 路径发送的。调用方不是浏览器。save-user.action/name/joe/age/20

有什么方法可以配置 Struts 来处理此 URL 并将其映射到正确的操作?

java 重写 struts2 friendly-url 操作映射

评论

0赞 Roman C 3/17/2023
您在配置此 url 时遇到问题还是什么?您最初是在 url 中使用反斜杠还是拼写错误?
0赞 Alireza Fattahi 3/18/2023
亲爱的@RomanC不,URL 中没有错别字。需要映射到操作的 URL 是“my.action/param1/value1”,这些斜杠在操作后使支柱不映射到操作
0赞 Roman C 3/18/2023
在这个问题中,不清楚您是如何将操作映射到 URL 的。
0赞 Alireza Fattahi 3/19/2023
我们正在使用 convention-plugin,似乎我们应该在 Struts 过滤器之前获取 URL。将其更改为有效的 URL,然后让 Struts 完成其余的工作。但我不知道怎么做。我试图在拦截器中执行此操作,但没有执行任何拦截器/my.action/param1/value1/my.action?param1=value1callinf my.action/param1/value1
0赞 Dave Newton 3/19/2023
那将是可怕的。您可能需要一个手动执行映射和转换的包罗万象的操作,尽管您可以构建一个拦截器来执行此操作并将假参数放入参数中。

答:

1赞 Roman C 3/20/2023 #1

我们正在使用 convention-plugin,似乎我们应该在 Struts 过滤器之前获取 URL。将其更改为 Valid,然后让 Struts 完成其余工作。/my.action/param1/value1url/my.action?param1=value1

自己做起来并不容易,幸运的是,有一个解决方案可以在 struts 过滤器前面使用 urlrewrite 过滤器。请参阅为什么 URL 重写在 Struts 2 中不起作用

如果将 Tuckey URL 重写筛选器放在 Web 应用程序部署描述符中的 Struts2 筛选器之前,则可以重写任何 URL。使用本指南:Tuckey URLRewrite How-To


然后,添加一个规则来重写 URL,如下所示:

<rule match-type="regex">  
  <from>/my.action/param1/(\w+)</from>
  <to>/my.action?param1=$1</to>
</rule>

评论

0赞 Alireza Fattahi 4/5/2023
如果配置 struts 和 url wrtie 有问题,请参阅 stackoverflow.com/questions/75920856/...
0赞 Alireza Fattahi 4/3/2023 #2

我更喜欢@RomanC解决方案,因为它不需要代码:)

如果您想自己开发它,这里是另一种解决方案。

这个想法是使用和更改并使 url 成为有效的 struts 操作。同时实现以生成有效的查询字符串HttpServletRequestWrappergetRequestURIgetServletPathgetParameterMap

@WebFilter(filterName = "UrlToActionMapperFilter")
public class UrlToActionMapperFilter implements Filter {

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    ChangedURIRequestWarpper warpperdRequest = new ChangedURIRequestWarpper(httpRequest);
    chain.doFilter(warpperdRequest, response);

}

public class ChangedURIRequestWarpper extends HttpServletRequestWrapper {

    private final Logger LOG = LoggerFactory.getLogger(ChangedURIRequestWarpper.class);
    private static final String CALLBACKURI = "foo/bar.action";
    private static final String URL_PARAMETERS_REGEX = "(\\w+\\/\\w+)";
    private final Pattern URL_PARAMETERS_PATTERN = Pattern.compile(URL_PARAMETERS_REGEX);

    public ChangedURIRequestWarpper(HttpServletRequest request) {       
        // So that other request method behave just like before
        super(request);
    }

    /**
     * read the parameters from url which is defined as /param1/value1/param2/value2
     * and set them to parameter map
     *  
     */
    @Override
    public Map<String, String[]> getParameterMap() {
        LOG.debug("get the parameters from {}, and set them in parameters map", super.getRequestURI());
        Map<String, String[]> parameters = new HashMap<>();

        //The queryString is /param1/value1/param2/value2
        String queryString = StringUtils.substringAfter(super.getRequestURI(), CALLBACKURI);

        Matcher matcher = URL_PARAMETERS_PATTERN.matcher(queryString);

        while (matcher.find()) {
            String[] keyValue = matcher.group(1).split("/");
            LOG.debug("Set {} in parameters map " , (Object)keyValue);          
            parameters.put( keyValue[0], new String[] {  keyValue[1] });
        }

        return parameters;
    }
    
    /**
     * struts use getRequestURI and getServletPath to determine if it should handle request ot not
     * As this url is fixed we can hardcode it.
     */
    @Override
    public String getRequestURI() {
        return "/"+CALLBACKURI;
    }

    @Override
    public String getServletPath() {
        return "/"+CALLBACKURI;
    }


}

}

在:web.xml

<filter-mapping>
    <filter-name>UrlToActionMapperFilter</filter-name>
    <!-- if you want to change it remember to change ChangedURIRequestWarpper  -->
    <url-pattern>/foo/bar.action/*</url-pattern>
</filter-mapping>