众所周知,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,方便参考传送门