8

Spring と Jersey の両方を使用する Servlet 3.0 Web アプリがあります。@Path現在、web.xml でフィルターとして構成された SpringServlet と、 と の両方で注釈が付けられたリソース クラスを使用してセットアップしています@Component。web.xml スニペットは次のとおりです。

<filter>
    <filter-name>jersey-serlvet</filter-name>
    <filter-class>
        com.sun.jersey.spi.spring.container.servlet.SpringServlet
    </filter-class>
    <init-param>
        <param-name>
            com.sun.jersey.config.property.packages
        </param-name>
        <param-value>com.foo;com.bar</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.config.feature.FilterForwardOn404</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>jersey-serlvet</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

このセットアップは機能しますが、私は本当に注釈のみでこのセットアップを取得したいと思っています-web.xml構成はありません。これに対する私の最初の試みは、上記の SpringServlet 構成を削除し、拡張するクラスを作成することでしたApplication。その一部を次に示します。

@ApplicationPath("/*")
public class MyApplication extends PackagesResourceConfig {

    public MyApplication() {
        super("com.foo;com.bar");

        HashMap<String, Object> settings = new HashMap<String, Object>(1);
        settings.put(ServletContainer.FEATURE_FILTER_FORWARD_ON_404, true);
        this.setPropertiesAndFeatures(settings);
    }
}

これは、JAX-RS リソースが登録されており、それらの URL をヒットできるという点で機能しますが、自動配線されたプロパティを使用しようとすると NullPointerExceptions がスローされます... リソースが現在ロードされていると推測しているため、これは理にかなっていますJersey であり、Spring 管理の Bean ではないため、自動配線はありません。

かなりの検索にもかかわらず、Jersey リソースを Spring Bean としてアノテーションのみでロードする方法が見つかりません。 そのような方法はありますか? リソースが Spring コンテキストを手動でフェッチして DI を呼び出すために、できる限り多くのコードを作成する必要はありません。

Application注釈のみが機能しない場合は、スキャンするパッケージのリストの代わりにロードするクラスを指定できれば、web.xml のフィルター構成を使用できます。そこにあるパッケージ リストを削除して、Applicationクラス インスタンスを指定するだけで十分です。

明らかに、誰かが私に決定的な答えを持っていれば素晴らしいことですが、他にどこを見ることができるか、または試してみるべきことの指針やヒントにも感謝します.

ありがとう、マット

4

6 に答える 6

1

私は理想的な結果を得ることができませんでしたが、ある程度の進歩を遂げることができたので、他の人の助けになる場合に備えてここに投稿します. Spring Servlet を使用してアプリケーション クラスを指定することができたので、web.xml からパッケージ リストを削除しました。

必要な web.xml の変更は、init パラメーターにあります (フィルター マッピングは表示されていませんが、それでも必要です)。

<filter>
    <filter-name>jersey-serlvet</filter-name>
    <filter-class>
        com.sun.jersey.spi.spring.container.servlet.SpringServlet
    </filter-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name> <!-- Specify application class here -->
        <param-value>com.foo.MyApplication</param-value>
    </init-param>
</filter>

そして、アプリケーション クラスで、スーパー コンストラクターの呼び出し方法を少し変更する必要がありました。

public MyApplication() {
    super("com.foo", "com.bar"); // Pass in packages as separate params

    HashMap<String, Object> settings = new HashMap<String, Object>(1);
    settings.put(ServletContainer.FEATURE_FILTER_FORWARD_ON_404, true);
    this.setPropertiesAndFeatures(settings);
}

まだ正確には私が求めていたものではありませんが、少なくともこれにより、Java コードと web.xml からもう少し構成が引き出されます。これは、この詳細を隠そうとしているので重要です。

于 2013-02-19T01:04:47.357 に答える
1

2 つのオプションが思い浮かびます (しゃれた意図はありません)。

  1. おそらくSpringServlet、独自のクラスで拡張し、それに適切なサーブレット 3.0 アノテーションを追加できます。
  2. SpringServletからクラスに切り替えるアプローチに沿って、ApplicationSpring のビルド時またはロード時のバイトコード ウィービングを有効にすることで、自動配線なしの問題を解決できます。これにより、Spring は、Spring によって作成されたオブジェクトだけでなく、どこでもインスタンス化されたオブジェクトを注入できます。「AspectJ を使用して Spring でドメイン オブジェクトに依存性を注入する」を参照してください。
于 2013-02-19T02:05:32.927 に答える
0

これは完全な例です。まず、web.xml を使用しないでください。以下のコードのみを使用してください。

残りのリソース:

@Path("hello")
public class HelloResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public Response hello() {
        String output = "Hello World!";
        return Response.status(200).entity(output).build();
    }
}

Rest アプリケーション (パッケージ名の「core」に注意)

@ApplicationPath("rest")
public class RestApplication extends javax.ws.rs.core.Application {

    public RestApplication() {
    }

    @Override public Set<Class<?>> getClasses() {
        return Set.of(
            HelloResource.class
        );
    }
}

春のウェブ構成。

@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = {
    
})
public class WebConfig implements WebMvcConfigurer {

    private static final Logger logger = LoggerFactory.getLogger(WebConfig.class);

    @Autowired
    private ApplicationContext applicationContext;

    public WebConfig() {
    }
}

春のイニシャライザ

//This @Order is required!!!
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyWebInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        var ctx = new AnnotationConfigWebApplicationContext();
        //spring WebMvcConfigurer
        ctx.register(WebConfig.class);
        ctx.setServletContext(servletContext);

        //Spring servlet
        var servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.setLoadOnStartup(1);
        servlet.addMapping("/");

        // Register Jersey 2.0 servlet
        ServletRegistration.Dynamic jerseyServlet = servletContext.addServlet("jerseyServlet",
            "org.glassfish.jersey.servlet.ServletContainer");
        //note "javax.ws.rs.Application" doesn't have "core"
        jerseyServlet.setInitParameter("javax.ws.rs.Application", RestApplication.class.getName());
        jerseyServlet.addMapping("/rest/*");
        jerseyServlet.setLoadOnStartup(1);
    }
}

そして、たとえばhttp://127.0.0.1:8080/rest/helloで動作する必要があります

于 2020-11-17T13:00:01.597 に答える