0

这是我的文件。

struts.xml

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

    <!-- restrictToGET to false makes the response to be of JSON type when request if of type POST, PUT, DELETE-->
    <constant name="struts.rest.content.restrictToGET" value="false"/>

    <constant name="struts.convention.action.suffix" value="Controller"/>
    <constant name="struts.convention.action.mapAllMatches" value="true"/>
    <constant name="struts.convention.default.parent.package" value="rest-default"/>
    <constant name="struts.convention.package.locators" value="action"/>

    <constant name="struts.enable.SlashesInActionNames" value="true"/>
    <constant name="struts.mapper.alwaysSelectFullNamespace" value="false"/>
    <constant name="struts.patternMatcher" value="regex"/>
    <constant name="struts.matcher.appendNamedParameters" value="true"/>

    <package name="action" namespace="/" extends="rest-default,json-default">

        <interceptors>
            <interceptor name="json" class="org.apache.struts2.json.JSONInterceptor"/>
            <interceptor-stack name="jsonStack">
                <interceptor-ref name="json"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
        </interceptors>

        <action name="hello" class="com.wildcard.action.HelloController">
            <interceptor-ref name="jsonStack"/>

            <result type="json">
                <param name="root">uid</param>
            </result>
        </action>

        <action name="hello/*" class="com.wildcard.action.HelloController">
            <interceptor-ref name="jsonStack"/>

            <param name="id">{1}</param>

            <result type="json">
                <param name="root">uid</param>
            </result>
        </action>

    </package>

</struts>

HelloController.java

package com.wildcard.action;

import com.opensymphony.xwork2.ModelDriven;
import com.wildcard.model.Hello;
import org.apache.struts2.rest.DefaultHttpHeaders;
import org.apache.struts2.rest.HttpHeaders;

public class HelloController implements ModelDriven<Object> {

    private Hello hello = new Hello();
    private String id;
    private String uid;
    private Object model = new Object();

    public HttpHeaders index() {
        hello.setName("index");
        System.out.println("index() : " + hello);
        System.out.println("index() uid: " + uid);
        return new DefaultHttpHeaders("index");
    }

    public HttpHeaders show() {
        hello.setName("show");
        System.out.println("show() : " + hello);
        System.out.println("show() id: " + id);
        System.out.println("show() uid: " + uid);
        return new DefaultHttpHeaders("show");
    }

    public HttpHeaders create() {
        //hello.setName("create");
        System.out.println("create() : " + hello);
        System.out.println("create() id: " + id);
        System.out.println("create() uid: " + uid);
        return new DefaultHttpHeaders("create");
    }

    public HttpHeaders update() {
        hello.setName("update");
        System.out.println("update() : " + hello);
        System.out.println("update() id: " + id);
        System.out.println("update() uid: " + uid);
        return new DefaultHttpHeaders("update");
    }

    public HttpHeaders destroy() {
        hello.setName("destroy");
        System.out.println("destroy() : " + hello);
        System.out.println("destroy() id: " + id);
        System.out.println("destroy() uid: " + uid);
        return new DefaultHttpHeaders("destroy");
    }


    @Override
    public Object getModel() {
        model = hello;
        return model;
    }

    public void setModel(Object model) {
        this.model = model;
    }

    public Hello getHello() {
        return hello;
    }

    public void setHello(Hello hello) {
        this.hello = hello;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }
}

Hello.java

package com.wildcard.model;

public class Hello {
    private String name;

    public Hello() {
    }

    public Hello(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "name='" + name + '\'' +
                '}';
    }
}

当我发送请求GET[ /hello.json, /hello/{id}.json], POST [ /hello.json], PUT[ /hello/{id}.json], DELETE[ /hello/{id}.json] 时,没有JSON Body,它工作正常。当我添加JSON Body到上述请求时,只有以下内容有效GET,,POST[ /hello.json]。当我添加{id}到 URL 路径时,我收到以下错误。

> HTTP ERROR: 500 Unable to show problem report:
> 
> freemarker.core.InvalidReferenceException: The following has evaluated
> to null or missing:
> 
> ==> rootloc.URI  [in template "org/apache/struts2/dispatcher/error.ftl" at line 84, column  15]
> 
> ---- Tip: It's the step after the last dot that caused this error, not those before it.
> ---- Tip: If the failing expression is known to legally refer to something that's sometimes  null or missing, either specify a default
> value like myOptionalVar!myDefault, or use <#if 
> myOptionalVar??>when-present<#else>when-missing</#if>. (These only
> cover the last step of  the expression; to cover the whole expression,
> use parenthesis:  (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
> ----
> 
> ---- FTL stack trace ("~" means nesting-related):
> - Failed at: ${rootloc.URI}  [in template "org/apache/struts2/dispatcher/error.ftl" at line 84, column 13]
> ----
> 
> Class: freemarker.core.InvalidReferenceException File:
> InvalidReferenceException.java Method: getInstance Line: 134 -
> freemarker/core/InvalidReferenceException.java:134:-1
> RequestURI=/wildcard_sample/hello/2.json
> 
> Powered by Jetty://

Java 堆栈跟踪(针对程序员):

freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
        at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
        at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:481)
        at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:401)
        at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:370)
        at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100)
        at freemarker.core.DollarVariable.accept(DollarVariable.java:63)
        at freemarker.core.Environment.visit(Environment.java:334)
        at freemarker.core.Environment.visit(Environment.java:340)
        at freemarker.core.Environment.visit(Environment.java:340)
        at freemarker.core.Environment.process(Environment.java:313)
        at freemarker.template.Template.process(Template.java:383)
        at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleErrorInDevMode(DefaultDispatcherErrorHandler.java:118)
        at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleError(DefaultDispatcherErrorHandler.java:76)
        at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:923)
        at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:589)
        at org.apache.struts2.dispatcher.ExecuteOperations.executeAction(ExecuteOperations.java:79)
        at org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:141)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
        at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
        at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206)
        at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
        at org.mortbay.jetty.Server.handle(Server.java:324)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
        at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:648)
        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
        at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
        at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)

发送 PUT 请求和 JSON 正文时出现错误屏幕截图

4

1 回答 1

0

其余插件与约定插件一起工作得很好,其中配置是按约定自动添加的。要让约定插件为您的应用程序中的操作创建配置,请使用以下设置

struts.xml

<constant name="struts.convention.action.suffix" value="Controller"/>
    <constant name="struts.convention.action.mapAllMatches" value="true"/>
    <constant name="struts.convention.default.parent.package" value="rest-default"/>
    <constant name="struts.convention.package.locators" value="action"/>

web.xml:struts2过滤器的参数

<init-param>
            <param-name>actionPackages</param-name>
            <param-value>com.wildcard.action</param-value>
 </init-param>
于 2022-02-10T15:44:27.677 回答