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

Spring Boot-控件建议异常处理程序不触发放置和补丁请求

邴俊友
2023-03-14

使用最新版本的SpringBoot(1.1.3. RELEASE),我正在尝试一个非常简单的rest应用程序。我有一个异常处理程序来处理由错误输入引起的验证错误。如果我发出POST请求,异常处理程序会触发。但是,如果我有补丁或放置请求,它不会触发。可能会发生什么?

异常处理程序类

@ControllerAdvice
public class DataValidationExceptionHandler {
    @ExceptionHandler(value = {ConstraintViolationException.class})
    public ResponseEntity handleBadInput(ConstraintViolationException ex) {
        return new ResponseEntity(HttpStatus.BAD_REQUEST);
    }
}

主要应用类

@Configuration
@ComponentScan
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableTransactionManagement
@EnableAutoConfiguration
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

域类

@Entity
public class Company {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Size(min=2, max=100)
    @NotBlank
    private String name;
    @URL
    private String website;

   //Not including getters and setters...
}

repository类

@RepositoryRestResource(collectionResourceRel = "companies", path = "companies")
public interface CompanyRepository extends PagingAndSortingRepository<Company, Long> {
}

此POST请求已正确处理。网站应该是URL,在这个请求中不是,因此,它正确地生成了一个验证错误,并由异常处理程序处理:curl-H“Content Type:application/json”-X POST-i-d{“name”:“comp1”,“website”:“www.comp1.com”}http://localhost:8080/companies

此PUT请求不由异常处理程序处理,尽管它生成与post请求相同的constraintviolationexception-<代码>curl-H“Content Type:application/json”-X PUT-i-d{“name”:“comp1”,“website”:“www.comp1.com”}http://localhost:8080/companies/1

到底是怎么回事?

使现代化对于POST请求,由于ExceptionHandler正在接管,因此不会生成堆栈跟踪。对于PUT请求,这里是转储的堆栈跟踪

javax.validation.ConstraintViolationException: Validation failed for classes [com.mycompany.domain.Company] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='must be a valid URL', propertyPath=website, rootBeanClass=class com.mycompany.domain.Company, messageTemplate='{org.hibernate.validator.constraints.URL.message}'}
]
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:160)
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreUpdate(BeanValidationEventListener.java:103)
    at org.hibernate.action.internal.EntityUpdateAction.preUpdate(EntityUpdateAction.java:257)
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:134)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)

更新2-为了解决问题,我还添加了一个catch-all异常处理程序。对于PUT请求,这个catch all可以处理异常,而不是我所期望的异常(javax.validation.ConstraintViolationException的处理程序)。在调试器中查看异常是什么时,调试器会显示这个组织。springframework。交易TransactionSystemException:无法提交JPA事务;嵌套的异常是javax。坚持不懈回滚异常:提交事务时出错

@ControllerAdvice
public class SystemExceptionHandler {
    @ExceptionHandler(value = {Exception.class})
    public ResponseEntity handleBadInput(Exception ex) {
        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

因此,看起来Spring正在将javax.validation.ConstraintViolationException的异常包装到另一个异常中。为了查看包装的异常是否得到正确处理,我还添加了这个处理程序

@ControllerAdvice
public class TransactionExceptionHandler {
    @ExceptionHandler(value = {TransactionSystemException.class})
    public ResponseEntity handleTxException(TransactionSystemException ex) {
        Throwable t = ex.getCause();
        if(t instanceof ConstraintViolationException){
           return new ResponseEntity(HttpStatus.BAD_REQUEST);    
        }else {
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

但问题是,即使是TransactionSystemException的处理程序。类无法处理该异常。这只是个例外。类是处理程序正在处理的。神秘的

更新3——我现在一筹莫展。异常处理程序只是没有被正确调用。我的下一个测试是看看数据库约束违规是否得到正确处理。在非常简单的公司模型中,数据库设置了公司名称的唯一约束。因此,如果发生违规,引发的异常org.springframework.dao.DataIntegrityViolationException。既不会触发包罗万象的Exception.class处理程序,也不会触发为org.springframework.dao.DataIntegrityViolationException编写的特定处理程序。Boot的json输出是这样的。什么??

{
  "cause" : {
    "cause" : {
      "cause" : {
        "cause" : null,
        "message" : "Duplicate entry 'comp1' for key 'chk_comp_name_unique'"
      },
      "message" : "Duplicate entry 'comp1' for key 'chk_comp_name_unique'"
    },
    "message" : "could not execute statement"
  },
  "message" : "could not execute statement; SQL [n/a]; constraint [chk_comp_name_unique]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"
}

共有1个答案

曹君墨
2023-03-14

看起来这将在下一版本的Spring Data Rest中修复。jira票

我在github存储库中看到了代码更改,因此SDR 2.3 RC1(Fowler)将提供修复程序。

 类似资料:
  • 问题内容: 我对AngularJs完全陌生。我正在尝试使用Angularjs向Django Deliciouspie API发送PATCH请求。我的代码是 但是,当我尝试使用此代码发送请求时,出现了一个错误消息,即http.patch不是函数。告诉我如何配置ng- app和服务以使用AngularJs发送PATCH请求。我读过PATCH请求在$ resource中可用,所以我也对$ resourc

  • 我有spring boot命令行应用程序,我希望以这样的方式处理应用程序错误,即允许我通过退出代码将它们传播给用户,再加上错误日志中一些合理的错误消息(而不仅仅是无意义的stacktrace)。我在文档中发现应用程序异常应该实现ExitCodeGenerator,因此我遵循了这个建议。但是我应该在公共void run(string...args)方法中捕获这个异常还是spring boot将为我处

  • 我有一个使用Spring Boot的Rest控制器 我的特例课 我的全局异常处理程序注释使用@Controlller建议 当我直接在控制器内部使用异常处理程序代码时,它似乎可以工作,但在用@controller Advice注释的类中使用异常处理程序时,根本不会调用它,我会得到默认的500内部服务器错误。我附上了我的项目目录结构的图片。我很努力,但无法解决这个问题 我的项目目录strcuure

  • 我有一个带post请求的控制器。我试图用一个简单的NotNull注释验证POJO。我正在使用ControllerAdvice来处理异常。 所以我尝试使用它,但当我启动应用程序时,我得到了以下信息: 因此,我想为BindException创建自己的处理程序,但当我为BindException类创建ExceptionHandler时,spring应用程序不会启动。如果我注释掉handleBindExc

  • 1.1 异常处理的基本使用 try: <语句块1> except: <语句块2> try 捕获异常 except 发生异常时执行 try: <语句块1> except <异常类型名字>: <语句块2> except <异常类型名字> 发生对应异常时才会执行 1.2 异常处理的高级使用 try: <语句块1> except

  • 我在spring boot 1.5.3中有rest api应用程序,我使用安全性登录并通过令牌对我的api验证每个请求。我想添加我的自定义异常与未经授权的异常时,用户没有找到由令牌。类添加了异常,但每个响应都有500个代码,但我想要401个响应代码。Belowe是我的密码。 StateLessAuthenticationFilter StateLessLoginFilter MyOwnExcept