基于注解整合Spring4、Jersey2與Groovy(非零配置)打賞

眾所周知,Servlet3.0作為J2EE 6規范一部分,隨J2EE6一起發布,并且Tomcat7已經完全支持,其中就我個人而言,最為關注的就是異步與注解支持,但這么久以來,實際項目中一直不曾使用,近來業余有空,就嘗試了一下Servlet 3.0的注解,但這不是重點,關于Servlet 3.0注解@WebServlet的使用,網上一搜一大把,這里不再贅述。

本文的重點是大部分基于注解來整合Spring4、Jersey2與Groovy實現Restful風格接口,為什么說是大部分呢?因為實踐中發現個小小的問題,Jersey2.0開始,同樣采用新規范,支持Spring加載但目前只支持XML配置形式,畢竟這兩個東西不是同一公司出品,完全融合還需要一定的時間去折騰,這里就不自己造輪子了,畢竟寫幾行XML配置也不是那么的麻煩,當然,如果你有潔癖、如果你愿意基于Spring官方方案實現Restful或者自己實現Jersey2與Spring4的橋接,依然可以保持零配置,這里就不再啰嗦,簡單分享下配置示例。

Servlet3.0規范,支持將servlet,filter,listener等硬編碼到代碼中,以此取代日益繁重的web.xml(雖然spring mvc等同樣可以解決,但使用注解畢竟省去了解析XML的過程),并由javax.servlet.ServletContainerInitializer的實現類負責在容器啟動時進行加載,spring提供了一個實現類org.springframework.web.SpringServletContainerInitializer。該類會調用所有org.springframework.web.WebApplicationInitializer的實現類的onStartup(ServletContext servletContext)方法,將相關的組件注冊到服務器。

spring同時提供了一些WebApplicationInitializer的實現類供我們繼承,以簡化相關的配置,比如:

org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer

注冊Spring DispatcherServlet。

org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer

注冊SpringSecurity。

同時,spring也提供了一些@Configuration的支持類供我們繼承,以簡化相關@Configuration的配置,比如:

org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport

封裝了springmvc相關組件,我們可以通過注冊新的@Bean和@Override相關方法,以實現對各個組件的注冊。

org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter

封裝類Springsecurity相關組件。

Spring4中提供了大量的注解來支持零配置,簡要說明如下:
@Configuration : 類似于spring配置文件,負責注冊bean,對應的提供了@Bean注解。
需要org.springframework.web.context.support.AnnotationConfigWebApplicationContext注冊到容器中。
@ComponentScan : 注解類查找規則定義 <context:component-scan />
@EnableAspectJAutoProxy : 激活Aspect自動代理 <aop:aspectj-autoproxy />
@Import @ImportResource: 關聯其它spring配置 <import resource="" />
@EnableCaching :啟用緩存注解 <cache:annotation-driven />
@EnableTransactionManagement : 啟用注解式事務管理 <tx:annotation-driven />
@EnableWebMvcSecurity : 啟用SpringSecurity安全驗證

前面有提到,這里由于要整合的是Jersey2,默認回去掃描Spring的配置文件applicationContext.xml,所以這里配置文件名稱我們最好也不要修改。關于下載spring、jersey、groovy等jar包的過程,這里直接忽略,建議大家直接去官網下載或者maven等下載。下面簡單介紹下配置。
第一步:加入Groovy支持。
使用過Grails,Groovy的靈活讓我不再想寫繁瑣的java代碼,所以這里順便把Groovy整合進來,在使用普通的Spring+Jersey的同時,使用Groovy編碼,操作很簡單,下載Groovy內嵌式jar包,放入項目即可,當然你還需要一個支持Groovy的IDE,比如:Intellij Idea,這步沒什么好介紹的,只是一開始在直接加入本地Groovy依賴的情況,會出現編譯不通過,移除本地依賴,直接丟個jar包進來就沒問題了,具體原因未深究,有興趣的同學可以研究下分享出來。
第二步:Spring配置,因為Bean的注冊我們依然要采取注解的形式,所以這里默認僅配置一行。

<context:component-scan base-package="me.itq.it.group" />

其中base-package是要掃描注解的最上層包名。
第三步:按照常規方式,在web.xml中配置Spring以及Jersey。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>jersey</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>me.itq.system.init.RestConfig</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

其中,me.itq.system.init.RestConfig類是Jersey2.x+的加載類,內容如下。

/**
 * Rest Resource Config
 * Created by William.Wei on 2015/9/11.
 */
@ApplicationPath("/")
class RestConfig extends ResourceConfig {
    RestConfig() {
        packages('me.itq.it.group.resource')
        register(JacksonFeature.class)
    }
}

其中packages('me.itq.it.group.resource')注冊Jersey要掃描的包,register(JacksonFeature.class)注冊Json支持。到此,我們的配置就完了,是不是很簡單的,另外提一下,上面這個類就是基于Groovy編寫的,代碼上可以盡可能的省略不必要的描述符,個人認為不是什么重要的項目,用下這樣的語言,開發起來要少敲很多次按鍵,當然Groovy還提供了不少Java本身所不具備的特性,不在本文討論范圍,就不多贅述了。

下面看一下簡單的例子:
UserDao.groovy

@Repository
class UserDao implements IUserDao{
    def getUser(){
        def user = "樸人博客"
        "user is ${user}".toString()
    }
}

UserService.groovy

@Service
class UserService implements IUserService {
    @Autowired
    def userDao;
    @Override
    def getUser() {
        return userDao.getUser()
    }
}

TestResource.groovy

@Path('web')
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Component
class TestResource {
    @Autowired
    def userService
    @GET
    def index() {
        def user = userService.getUser()
        def data = [
                test: 'ok',
                user: user
        ]
        return Response.ok(data).build()
    }
}

部署到本地服務器,訪問http://localhost:808,頁面打印內容

{"test":"ok","user":"user is 樸人博客"}

基本整合完畢,當然,如果要實際使用,還需要整合持久層框架、安全框架等,這里不再一一介紹,大家有興趣可以自己嘗試。

下面是文中用到代碼,上傳到了github,方便參考傳送門

基于注解整合Spring4、Jersey2與Groovy(非零配置)
文章《基于注解整合Spring4、Jersey2與Groovy(非零配置)》二維碼
  • 微信打賞
  • 支付寶打賞

已有5條評論

  1. 小丸子

    HI,兄弟,有個問題,我也是jersey2+spring4,但沒用groovy。現在是在REST資源類,即你的:
    @Component
    class TestResource {
    @Autowired
    def userService

    通過注解方式想注入spring的service,我看日志spring也有去初始化這個資源類,但實現在web容器中跑起來,該對象是NULL。但看你介紹來看不會,想具體了解下原因?我個人覺得是否資源類在通過HTTP訪問時還是由WEB容器管理,若需要訪問SPRING的資源,需要通過代碼去獲取,類似如下:
    WebApplicationContext wac = WebApplicationContextUtils
    .getRequiredWebApplicationContext(getServletContext());
    gamePackService = (GamePackService) wac.getBean(“gamePackService”);

    請賜教!!!

    2016-04-10 23:31 回復
    • 樸人博客

      1.X的需要在web.xml里配置spring的包,2.X的直接有個spring的包,引入即可,名字叫Jersey-spring3,之前試時沒找到有提供4的,但測試發現spring3的包在spring4下面同樣適用,另外我把之前的小demo帶jar包放github了,有興趣可以看看。

      2016-04-11 22:34 回復
    • 樸人博客

      jersey-spring3-2.x

      2016-04-11 23:28 回復
    • 樸人博客

      maven倉庫地址http://mvnrepository.com/artifact/org.glassfish.jersey.ext/jersey-spring3

      2016-04-11 23:28 回復

(必填)

(必填)

(可選)

黑龙江22选5开奖