2013-02-06 58 views
7

我有一個同時使用Spring和Jersey的Servlet 3.0 web應用程序。我目前已經使用配置爲web.xml中的過濾器的SpringServlet進行設置,並使用@Path@Component對註冊的資源類進行註釋。這裏的web.xml片段:如何使用Spring註釋配置Jersey與Jersey

<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打他們,但他們拋出NullPointerException異常,當他們試圖用自己的自動裝配屬性...這使得因爲我猜測資源現在正在被Jersey加載,而不是Spring管理的bean,因此沒有自動裝配。

儘管有一點點搜索,但我找不到任何將Jersey資源加載爲僅具有註釋的Spring bean的方式。 有沒有這樣的方法?我真的不想爲資源編寫一堆代碼來手動獲取Spring上下文並調用DI,如果我可以幫助的話。

如果只註釋不起作用,那麼我可以在web.xml中使用filter配置,如果我可以指定Application類來加載而不是要掃描的軟件包列表。如果我可以擺脫那裏的軟件包列表並指定一個Application類實例,那麼我會滿足。

很顯然,如果有人對我有明確的答案,但我也會很感激任何我可以看的東西或想要嘗試的東西的提示或提示。

謝謝, 馬特

回答

1

我一直沒能得到我的理想的結果,但我已經能夠取得一些進展,所以它可以幫助別人,我會張貼在這裏的情況。我能夠使用Spring Servlet指定我的應用程序類,從而從web.xml中刪除軟件包列表。

所需的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>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中,這對我來說很重要,因爲我試圖隱藏這個細節。

1

兩個選項可以讓人記住(沒有雙關意圖)。

  1. 也許你可以擴展SpringServlet與你自己的類,並添加適當的servlet 3.0註釋。
  2. 按照您從SpringServlet切換到Application類的方法,您可以通過啓用Spring構建時或加載時字節碼編織來解決無自動佈線問題。這使得Spring能夠注入由任何地方實例化的對象,而不是僅由Spring創建的對象。見"Using AspectJ to dependency inject domain objects with Spring"
1

首先,在一個servlet 3.0容器中,你並不需要web.xml

但隨着澤西2.0,你可以設置一個標誌,掃描整個Web應用程序的註釋資源:

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

<servlet> 
    <servlet-name>jersey</servlet-name> 
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
    <init-param> 
     <param-name>jersey.config.servlet.provider.webapp</param-name> 
     <param-value>true</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

,如果你有這個jar春天將自動啓用:

<dependency> 
     <groupId>org.glassfish.jersey.ext</groupId> 
     <artifactId>jersey-spring3</artifactId> 
     <version>2.3.1</version> 
    </dependency> 
+0

謝謝您的回答,但我使用澤西1,我沒有任何麻煩Jersey資源已加載並正在運行。問題是我希望他們由Spring管理,所以我可以自動裝配。 – Doughnuts

+0

好的,在這種情況下,這不是一個解決方案。但要清楚的是:這確實使Spring自動裝配成爲可能。 – rustyx

2

下面是我的應用程序的一部分,它使用Servlet 3.0,Spring,Jersey 1.8,它沒有web.xml:

public class WebAppInitializer implements WebApplicationInitializer { 

@Override 
public void onStartup(ServletContext servletContext) throws ServletException { 
    final AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); 
    context.setConfigLocation("com.myapp.config"); 

    final FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("characterEncodingFilter", new CharacterEncodingFilter()); 
    characterEncodingFilter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*"); 
    characterEncodingFilter.setInitParameter("encoding", "UTF-8"); 
    characterEncodingFilter.setInitParameter("forceEncoding", "true"); 

    final FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter("springSecurityFilterChain", new DelegatingFilterProxy()); 
    springSecurityFilterChain.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*"); 

    servletContext.addListener(new ContextLoaderListener(context)); 
    servletContext.setInitParameter("spring.profiles.default", "production"); 

    final SpringServlet servlet = new SpringServlet(); 

    final ServletRegistration.Dynamic appServlet = servletContext.addServlet("appServlet", servlet); 
    appServlet.setInitParameter("com.sun.jersey.config.property.packages", "com.myapp.api"); 
    appServlet.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters", "com.myapp.api.SizeLimitFilter"); 
    appServlet.setLoadOnStartup(1); 

    final Set<String> mappingConflicts = appServlet.addMapping("/api/*"); 

    if (!mappingConflicts.isEmpty()) { 
     throw new IllegalStateException("'appServlet' cannot be mapped to '/' under Tomcat versions <= 7.0.14"); 
    } 
} 

}

0

我使用Jersey和我以前製作的使用SpringMVC的項目。我基於Spring's official documentation上的我的代碼。

public class WebAppInitializer implements WebApplicationInitializer { 

@Override 
public void onStartup(ServletContext servletContext) { 
    // Don't create the Listener that Jersey uses to create. 
    // There can only be one linstener 
    servletContext.setInitParameter("contextConfigLocation", "<NONE>"); 
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); 

    // Add app config packages 
    context.setConfigLocation("config.package"); 

    // Add listener to the context 
    servletContext.addListener(new ContextLoaderListener(context)); 

    // Replacing: 
    //  <servlet-name>ServletName</servlet-name> 
    //  <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> 
    //  <init-param> 
    //   <param-name>com.sun.jersey.config.property.packages</param-name> 
    //   <param-value>webservices.packages</param-value> 
    //  </init-param> 
    //  <load-on-startup>1</load-on-startup> 
    AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext(); 

    ServletRegistration.Dynamic appServlet = servletContext.addServlet("ServletName", new DispatcherServlet(dispatcherContext)); 
    appServlet.setInitParameter("com.sun.jersey.config.property.packages", "org.sunnycake.aton.controller"); 
    appServlet.setLoadOnStartup(1); 
    appServlet.addMapping("/RootApp"); 

} 
} 

config.package的配置類是:

// Specifies that there will be bean methods annotated with @Bean tag 
// and will be managed by Spring 
@Configuration 

// Equivalent to context:component-scan base-package="..." in the xml, states 
// where to find the beans controlled by Spring 
@ComponentScan(basePackages = "config.package") 
public class AppConfig { 

    /** 
    * Where will the project views be. 
    * 
    * @return ViewResolver como el XML 
    */ 
    @Bean 
    public ViewResolver viewResolver() { 
     InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); 
     return viewResolver; 
    } 

} 

Hibernate配置

// Specifies that there will be bean methods annotated with @Bean tag 
// and will be managed by Spring 
@Configuration 
// Equivalent to Spring's tx in the xml 
@EnableTransactionManagement 

// Equivalent to context:component-scan base-package="..." in the xml, states 
// where to find the beans controlled by Spring 
@ComponentScan({"config.package"}) 

// Here it can be stated some Spring properties with a properties file 
@PropertySource(value = {"classpath:aplicacion.properties"}) 
public class HibernateConfig { 

    /** 
    * Inyected by Spring based on the .properties file in the 
    * \@PropertySource tag. 
    */ 
    @Autowired 
    private Environment environment; 

    /** 
    * Here it's created a Session Factory, equivalent to the Spring's config file one. 
    * 
    * @return Spring Session factory 
    */ 
    @Bean 
    public LocalSessionFactoryBean sessionFactory() { 
     LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 

     // Uses the datasource 
     sessionFactory.setDataSource(dataSource()); 

     // Indicates where are the POJOs (DTO) 
     sessionFactory.setPackagesToScan(new String[]{"dto.package"}); 
     // Se asignan las propiedades de Hibernate 
     sessionFactory.setHibernateProperties(hibernateProperties()); 

     return sessionFactory; 
    } 

    /** 
    * Propiedades de la base de datos (Según environment) 
    * 
    * @return Nuevo DataSource (Configuración de la base de datos) 
    */ 
    @Bean 
    public DataSource dataSource() { 
     DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
     dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName")); 
     dataSource.setUrl(environment.getRequiredProperty("jdbc.url")); 
     dataSource.setUsername(environment.getRequiredProperty("jdbc.username")); 
     dataSource.setPassword(environment.getRequiredProperty("jdbc.password")); 
     return dataSource; 
    } 

    /** 
    * Hibernate properties 
    * 
    * @return Properties set with the configuration 
    */ 
    private Properties hibernateProperties() { 
     Properties properties = new Properties(); 
     // Dialect (Mysql, postgresql, ...) 
     properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect")); 
     // Show SQL query 
     properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql")); 
     properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql")); 
     return properties; 
    } 

    /** 
    * Inyected by sessionFactory 
    */ 
    @Bean 
    @Autowired 
    public HibernateTransactionManager transactionManager(SessionFactory s) { 
     HibernateTransactionManager txManager = new HibernateTransactionManager(); 
     txManager.setSessionFactory(s); 
     return txManager; 
    } 
}