是否有内置功能来验证某些JAX-RS变量上下文?

时间:2013-12-31 09:24:18

标签: java java-ee jboss jax-rs java-ee-6

我正在使用一个处理@Path( "/{site}/group" )的类和另一个处理@Path( "/{site}/user" )的类。我在上下文中有一个返回状态{site}的无效404对象的异常处理程序,但是为了验证{site},我需要在我使用它的每个方法上重复代码。我从数据库中获取site并检查是否null(然后抛出异常)。

JAX-RS中是否有任何内置功能可以帮助我在方法执行之前测试{site}上下文,然后我可以从这个混乱中做出一些干嘛?如果不是这种情况下最好的方法是什么?

编辑:
(非功能性剪辑表达我的问题)

在班级使用@Path( "/{site}/user" )

然后一个方法:

@GET
public void getUser( String site ) throws ... {
  Site site = findSiteFromDatabase( site );
  if ( site == null ) throw new InvalidException( "Invalid site" );

  ...
}

这种方法的问题在于我必须在我创建的每种方法中测试对象的有效性 这将是一个非常方便的实用程序,允许我加载一次上下文对象(使用相同的方法考虑多个类)。

编辑2:

我的root资源是EJB,我需要这个来从数据库加载Site对象(使用JPA和东西)

我使用了EJB拦截器。这种方法的问题在于我必须始终使用固定参数@PathParam( "site" ) String siteSite site创建一个方法(第二个参数是不参考数据库两次)。

    @AroundInvoke
    public Object initSite( InvocationContext context ) throws Exception {
        String siteName = context.getParameters()[ 0 ].toString();
        SiteEntity siteEntity = siteDAO.findSiteByPath( siteName );
        if ( siteEntity == null ) {
            throw new APINotFoundException( "The site you are accessing does not exist" );
        }

        Object[] params = new Object[]{ siteName, siteEntity };
        context.setParameters( params );

        return context.proceed();
    }

    @GET
    @Path( "/user" )
    public UserData getUser(
        @PathParam( "site" ) String site,
        SiteEntity site
    ) {
        return ...
    }

欢迎任何不要求我建立固定签名的方法。

编辑3: 我上面的解决方案没有奏效。 EJB拦截器无法遵守我的ExceptionMapper声明(它总是返回状态500)。我几乎放弃了,有没有人遇到同样的问题?

3 个答案:

答案 0 :(得分:0)

据我所知,JEE中没有这样的默认行为。这就是我如何解决这个问题。

  1. 将您的其余端点网址调整为: (您需要这样做,因为<url-pattern>标记的常规exprssion的使用非常有限!)

    @Path( "/user/{site}")

    @Path( "/group/{site}")

  2. 创建用户和组请求过滤器......喜欢: (Just pseudo source !!!)

    public class UserFilter implements Filter { 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
    
        HttpServletRequest req = null;
        boolean valid = false;
        PrintWriter out = null;
    
        if (request instanceof HttpServletRequest) {
    
            req = (HttpServletRequest) request;
            // TODO extract site info from url ...
            // TODO perform check ...
            // valid = ...
        }
    
        if (valid) {
            chain.doFilter(request, response);
        } else {
    
            response.setContentType("text/html");
            out = response.getWriter();
            out.println("<html><head><title>Your specific response</title></head><body>");
            out.println("<h2>Sorry, Unknown URL!</h2>");
    
            out.println("</body></html>");
            out.close();
        }
    }
    
    @Override
    public void destroy() {
    
    }
    

    }

  3. 在web.xml中添加过滤器:

    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        version="2.5">
        ...
        <filter>
            <filter-name>User validation fiter</filter-name>
            <filter-class>path.to.your.UserFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>User validation fiter</filter-name>
            <url-pattern>/services/user/*</url-pattern>
        </filter-mapping>
    
        <filter>
            <filter-name>Group validation fiter</filter-name>
            <filter-class>path.to.your.GroupFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>Group validation fiter</filter-name>
            <url-pattern>/services/group/*</url-pattern>
        </filter-mapping>
        ...
    </web-app>
    

答案 1 :(得分:0)

我可以看到两个选项:

BeanParm(需要JAX-RS 2.0,可以在JBoss 7中升级JAX-RS):

public SiteBean{

   @PathParam
   private String site;

   public Site getSite() throws WebApplicationException{
       Site s = findSiteFromDatabase( site );
       if ( s == null ) throw new WebApplicationExcepiton();
       // you can customize the Responce in the WebApplicationException
   }
}

在请求网站的每种方法中,您需要执行以下操作:

@GET
public void getUser( @BeanParam SiteBean site ){
      Site s = site.getSite();
}

其他选项是使用sub-resources

@Path("{site}")
public SiteResource{

    private Site site;

    public SiteResource(@PathParam String site) throws new WebApplicationExcepiton{
         this.site = = findSiteFromDatabase( site );
         if ( s == null ) throw new WebApplicationExcepiton();
       // you can customize the Responce in the WebApplicationException
    }

    @Path("user")
    public UserResource user(){
         return new UserResource(site);
    }

    ... // same for other sub resource.
}

用户资源:

public UserResource{
    private Site site;

    public UserResource(Site site){
        this.site = site;
    }

    @GET
    public void getUser{
       ...
    }

    ...
}

最后一个应该适用于JAX-RS 1.1。

答案 2 :(得分:0)

为什么不从findSiteFromDatabase( site )方法中抛出异常而不是返回null值? (顺便说一下,JPA与Query#getSingleResult()的行为类似:http://docs.oracle.com/javaee/6/api/javax/persistence/Query.html#getSingleResult%28%29)。

然后,您可以使用JAX-RS ExceptionMapper将异常转换为具有正确返回代码和正文的JSON / XML / HTML响应,具体取决于您的需要。