当前位置: 首页 > 知识库问答 >
问题:

用于JAX-RSbean验证的自定义异常映射

汪丁雷
2023-03-14

我正在使用ApacheCXF、Spring和JAX-RS构建一个REST web服务,当输入JSON验证失败时,我需要在其中发送自定义异常。

我没有使用业务逻辑,而是尝试使用CXF、JAX-RS的现成bean验证功能。

Bean验证工作正常,但是,它总是抛出500个异常,这是不太有用的。根据留档,它是org.apache.cxf.jaxrs.validation.ValidationExceptionMapper的预期行为。

我试图扩展异常映射器,以便我可以抛出不同的错误消息,但这个自定义映射器没有被调用。

下面是我的代码设置-

    <!-- Spring Framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.1.4.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.1.4.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.1.4.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.1.4.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.1.4.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>3.2.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>3.2.7.RELEASE</version>
    </dependency>

    <!-- CXF -->

    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-core</artifactId>
        <version>3.0.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxrs</artifactId>
        <version>3.0.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-bundle-jaxrs</artifactId>
        <version>2.7.5</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-jaxrs</artifactId>
        <version>1.9.3</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-xc</artifactId>
        <version>1.9.3</version>
    </dependency>

    <!-- Hibernate validation -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.1.3.Final</version>
    </dependency>
    <!-- JSR 303 Validation framework -->
    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-bean-validation</artifactId>
        <version>2.19</version>
    </dependency>
<jaxrs:server address="/" id="iamService">
        <jaxrs:serviceBeans>
            <bean class="com.XXXXXX.iam.service.core.endpoint.impl.IAMIdentityServiceImpl" />
        </jaxrs:serviceBeans>
            <jaxrs:inInterceptors>
        <ref bean="validationInInterceptor" />
    </jaxrs:inInterceptors>
    <jaxrs:outInterceptors>
        <ref bean="validationOutInterceptor" />
        <ref bean="exceptionMapperOutInterceptor" />
    </jaxrs:outInterceptors>
        <jaxrs:extensionMappings>
            <entry key="json" value="application/json" />
        </jaxrs:extensionMappings>
        <jaxrs:providers>
            <ref bean='jsonProvider' />
            <ref bean="ampfExceptionMapper"/>
        </jaxrs:providers>
    </jaxrs:server>

<bean id="ampfExceptionMapper" class="com.xxxxxxx.iam.service.core.interceptor.AmpfValidationExceptionMapper"/>
<bean id="exceptionMapperOutInterceptor" class="org.apache.cxf.jaxrs.interceptor.JAXRSOutExceptionMapperInterceptor"/>

<bean id="validationProvider" class="org.apache.cxf.validation.BeanValidationProvider" />

<bean id="validationInInterceptor" class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor">
    <property name="provider" ref="validationProvider" />

</bean>


<bean id="validationOutInterceptor" class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationOutInterceptor">
    <property name="provider" ref="validationProvider" />
</bean> 
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class AmpfValidationExceptionMapper implements ExceptionMapper<ConstraintViolationException>{



    @Override
    public Response toResponse(ConstraintViolationException exception) {
        System.out.println("Executing Ameriprise Service exception mapping");

        UniqueIDValidationResponse response = new UniqueIDValidationResponse();
        response.setResponse("Invalid request");
        return Response.ok(response).build();
    }


}

公共类UniqueIDValidationRequest{

/*@Autowired
private Validator validator;*/

@XmlAttribute(name = "ssoId")
@NotBlank
@NotEmpty
@Length(max=20,min=5)
protected String ssoId;

@NotEmpty
@NotBlank
@XmlAttribute(name = "epHashId")
protected String epHashId;

共有2个答案

阎成天
2023-03-14

我解决了一个异常映射器:

    import org.apache.cxf.validation.ResponseConstraintViolationException;
import org.slf4j.LoggerFactory;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import java.util.Iterator;

/**
 * Created by Hyun Woo Son on 1/9/18
 **/
@Provider
public class ValidationExceptionMapperCustom implements ExceptionMapper<ValidationException> {


    private static org.slf4j.Logger logger = LoggerFactory.getLogger(ValidationExceptionMapperCustom.class);


        public Response toResponse(ValidationException exception) {
            Response.Status errorStatus = Response.Status.INTERNAL_SERVER_ERROR;
            ResponseVo responseVo = new ResponseVo();
            if (exception instanceof ConstraintViolationException) {
                ConstraintViolationException constraint = (ConstraintViolationException)exception;
                Iterator i$ = constraint.getConstraintViolations().iterator();

                StringBuilder errorMsg = new StringBuilder(RestExcepcionEnum.PARAMETROS_EXCEPCION.getValue());
                errorMsg.append("\n");

                while(i$.hasNext()) {
                    ConstraintViolation<?> violation = (ConstraintViolation)i$.next();
                    logger.info("error {}",violation.getRootBeanClass().getSimpleName() + "." + violation.getPropertyPath() + ": " + violation.getMessage());
                    errorMsg.append("La propiedad : "+violation.getPropertyPath() + " con error:  " + violation.getMessage() );
                    errorMsg.append("\n");
                }

                if (!(constraint instanceof ResponseConstraintViolationException)) {
                    errorStatus = Response.Status.BAD_REQUEST;
                }
                responseVo.setMensaje(errorMsg.toString());
            }
            else{
                responseVo.setMensaje("Error inesperado: "+exception.getMessage());
                logger.debug("Error de validacion {}",exception.getMessage(),exception);
            }
            return Response.status(errorStatus).entity(responseVo).build();
        }


}

并将其添加到Application类:

富凯旋
2023-03-14

这个问题现在已经解决了。我要做的是创建一个自定义拦截器。这将捕获bean验证时发生的错误,并添加实际的bean验证错误。请检查下面的InInterceptor代码--

@Provider
public class IamServInInterceptor extends
BeanValidationInInterceptor implements ContainerRequestFilter{

private static Logger logger = LoggerFactory.getLogger(IamServInInterceptor.class);

public IamServInInterceptor() {
    logger.debug("IamServInInterceptor default consturctor called");
}

public IamServInInterceptor(String phase) {
    super(phase);
    logger.debug("IamServInInterceptor phase : " + phase);
}

@Override
public void filter(ContainerRequestContext arg0) throws IOException {
    // TODO Auto-generated method stub
    logger.debug("IamServInInterceptor filter is called");
    InterceptorChain chain = PhaseInterceptorChain.getCurrentMessage()
            .getInterceptorChain();
    chain.add(this);
}

protected Object getServiceObject(Message message) {
    logger.debug("IamServInInterceptor getServiceObject called");
    return ValidationUtils.getResourceInstance(message);
}

protected void handleValidation(Message message, Object resourceInstance,
        Method method, List<Object> arguments){
    try {
        logger.debug("IamServInInterceptor handleValidation called");
        super.handleValidation(message, resourceInstance, method, arguments);
    } catch (ConstraintViolationException ex) { 
        logger.debug("IamServInInterceptor handleValidation has some exception");
        UniqueIDValidationResponse response = new UniqueIDValidationResponse();
        response.setResponse("INPUT_VALIDATION_FAILED");
        ConstraintViolationException constraintException = (ConstraintViolationException)ex;
        Set<ConstraintViolation<?>> constraint= 
                constraintException.getConstraintViolations();
        Iterator<ConstraintViolation<?>> iterator = constraint.iterator();
        while(iterator.hasNext()){
            ConstraintViolation<?> error = iterator.next();
            logger.debug("Error : " + error.toString());
            response.getMessage().add(error.getMessage());
        }
        ex.printStackTrace();
        message.getExchange().put(Response.class, Response.ok(response).build());
    }
}

}

 类似资料:
  • Spring靴2.0.3。发布,javax。验证2.0.1。最后一个选项被使用。 我需要验证进入控制器的请求: 这叫做服务: 将对象保存到MongoRepository方法

  • 问题内容: 我已经读过我可以创建一个实现,将抛出的应用程序异常映射到对象。 我创建了一个简单的示例,如果在保留对象时电话长度大于20个字符,则会引发异常。我期望将异常映射到HTTP 400(错误请求)响应;但是,我收到HTTP 500(内部服务器错误),但有以下异常: 我想念什么?任何意见是极大的赞赏。 异常映射器: 异常类: 实体类: 服务: 问题答案: InvalidDataException

  • 表单验证发生在数据验证之后。如果你需要定制化这个过程,有几个不同的地方可以修改,每个地方的目的不一样。表单处理过程中要运行三种类别的验证方法。它们通常在你调用表单的is_valid() 方法时执行。还有其它方法可以触发验证过程(访问errors 属性或直接调用full_clean() ),但是通用情况下不需要。 一般情况下,如果处理的数据有问题,每个类别的验证方法都会引发ValidationErr

  • 我使用了的方法将错误消息添加到自定义路径,但不推荐使用此方法。但是,当我使用新方法时,我会得到一个。 是不是我缺少了一些依赖? 下面是错误消息的片段: 下面是使用Hibernate validator Version4.3.1-Final进行跨字段验证的验证器片段

  • 问题内容: 我有一个使用Jersey构建的REST服务。 我希望能够根据发送到服务器的MIME设置我的自定义异常编写器的MIME。当接收到json和接收到xml 时返回。 现在我进行了硬编码,但这使XML客户端陷入了黑暗。 我可以利用什么上下文来获取当前请求? 谢谢! 根据答案更新 对于对完整解决方案感兴趣的其他人: 连同 其中ErrorResponseConverter是自定义JAXB POJO

  • 我想在spring验证器中创建基于条件的验证。我有一个UserDTO类,因为有两个DTO类带有注释。 如果我传递isPrimary,那么它应该只验证primaryDTO bean,而忽略secondoryDTO验证。 请引导。 谢谢