CDI应用二 CDI与JAX-RS集成

<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(function(){
	$('#username').blur(function(){
		$.post('service/examuser/exists.json',{"username":$(this).val()},function(data){
			if(data==’true’){
				alert('已经存在');
			}
		});
	});
});
</script>
在实际开发过程中总会有ajax验证数据的需求。AJAX服务器端可以用各种技术实现,jspservletJAX-RS都行,但是最好用的还是JAX-RSJAX-RSAJAX返回JSON相当方便,另外取请求数据的时候也相当地方便。

Ajax代码的添加相当简单,加点js就可以了。


这是一个简单的验证,只是alert了一下。

服务层自然是使用JPA技术:

@ApplicationScoped
@Named
public class UserExistService {
 
	@PersistenceContext 
	private EntityManager em;
	public boolean exists(String username){
		CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
		CriteriaQuery<ExamUser> query = criteriaBuilder.createQuery(ExamUser.class);
		Root<ExamUser> root = query.from(ExamUser.class);
		query.where(criteriaBuilder.equal(root.get("username"), username));
		TypedQuery<ExamUser> typedQuery = em.createQuery(query);
		return !typedQuery.getResultList().isEmpty();
	}
}

CriteriaBuilder是JPA构建安全查询的一个类。它用来创建查询类,用来创建约束条件。

criteriaBuilder.createQuery(ExamUser.class);就是用来创建查询类的,这个查询类可以转换为TypedQuery。criteriaBuilder.equal就是用来创建约束条件的。

Root<ExamUser>其实相当于SQL from后面的东西,可以认为是对表的抽象。

Query用来添加查询条件,并通过TypedQuery提交给实体管理器。

这仅仅是做了一个服务,还需要做一个rest资源类。因为MVC思想,负责路由的rest资源类就不直接注入EntityManager,而是直接注入刚才写好的service

REST环境的搭建就是写一个类继承自Application 。因为rest服务不能拦截所有的URL,这样会影响到servlet,所以在注解中需要配置一个前缀。

@ApplicationPath("/service")
public class ExamApplication extends Application {
}

REST服务器是支持子资源的。所谓的子资源就是根资源通过URL路由选择子资源类来处理请求。

先介绍下根资源类。这个类它具有两种角色,因为加了@Path注解,所以成为了一个REST资源类。

@RequestScoped
@Path("/examuser")
public class ExamUserResource {
	@Context
	private ResourceContext resourceContext;
 
	@Path("/")
	public ExistingResource exist() {
		return resourceContext.getResource(ExistingResource.class);
	}
}

REST是有上下文的,CDI也有自己的上下文,如果仅仅是这样加注解,两个上下文是隔开的,也就是两个容器是隔开的。自然不能在资源类里取到CDI的对象。而CDI上下文里的资源类对象,浏览器也根本访问不到。

这个时候就需要配置了。

web.xml中配置以下这一项内容就可以了。

<context-param>
	<param-name>resteasy.injector.factory</param-name>
	<param-value>org.jboss.resteasy.cdi.CdiInjectorFactory</param-value>
</context-param>

因为wildfly服务器使用了resteasy-cdi插件,这个插件会读取

Resteasy.injector.factory的配置,然后就可以将两个上下文进行融合,也就是将REST的上下文并入CDI上下文中,让CDI对象来充当REST资源类。

@ContextREST的注解,注入的是REST的资源上下文,通过这个资源上下文找到其余的rest资源,作为子资源进行返回,exist就是一个简单的路由方法。

@RequestScoped
public class ExistingResource {
 
	@Inject
	private UserExistService userExistService;
	@POST
	@Path("/exists.json")
	@Produces("text/plain")
	public String exist(@FormParam("username") String username){
		return userExistService.exists(username)+"";
	}
}

ExistingResource 是一个子资源类,与根资源类不同的是,子资源类不需要加@Path注解,因为它是通过根资源类的路由来指定URL的。所以看起来就是个CDI对象,但是还是加了REST的注解的,比如@POST@Path("/exists.json")@Produces("text/plain")

Text/plain注解是指定返回的MIME类型的。@POST注解是限定了只接收POST请求。

至此,整个就做完了。这个小功能涉及的技术比较多,有REST,CDI,JPARESTEASY-CDI

展开阅读全文

没有更多推荐了,返回首页