- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Spring Boot、Spring Data REST、Spring HATEOAS、Hibernate、Spring Validation 创建一个应用程序。
我创建了我自己的验证来支持 SpEL 跟随 this guide .
所以我有我的验证器:
public class SpELClassValidator implements ConstraintValidator<ValidateClassExpression, Object> {
private Logger log = LogManager.getLogger();
private ValidateClassExpression annotation;
private ExpressionParser parser = new SpelExpressionParser();
public void initialize(ValidateClassExpression constraintAnnotation) {
annotation = constraintAnnotation;
parser.parseExpression(constraintAnnotation.value());
}
public boolean isValid(Object value, ConstraintValidatorContext context) {
try {
StandardEvaluationContext spelContext = new StandardEvaluationContext(value);
return (Boolean) parser.parseExpression(annotation.value()).getValue(spelContext);
} catch (Exception e) {
log.error("", e);
return false;
}
}
}
@Target({ java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { SpELClassValidator.class })
@Documented
@Repeatable(ValidateClassExpressions.class)
public @interface ValidateClassExpression {
String message() default "{expression.validation.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String value();
}
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:/i18n/messages");
// messageSource.setDefaultEncoding("UTF-8");
// set to true only for debugging
messageSource.setUseCodeAsDefaultMessage(false);
messageSource.setCacheSeconds((int) TimeUnit.HOURS.toSeconds(1));
messageSource.setFallbackToSystemLocale(false);
return messageSource;
}
/**
* Enable Spring bean validation
* https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation
*
* @return
*/
@Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
factoryBean.setValidationMessageSource(messageSource());
return factoryBean;
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
@Configuration
public class RestConfig extends RepositoryRestConfigurerAdapter {
@Autowired
private Validator validator;
public static final DateTimeFormatter ISO_FIXED_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
.withZone(ZoneId.of("Z"));
@Bean
public RootResourceProcessor rootResourceProcessor() {
return new RootResourceProcessor();
}
@Override
public void configureExceptionHandlerExceptionResolver(ExceptionHandlerExceptionResolver exceptionResolver) {
}
@Override
public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", validator);
validatingListener.addValidator("beforeSave", validator);
super.configureValidatingRepositoryEventListener(validatingListener);
}
}
@Entity
// Validate the number of seats if the bus is a minibus
@ValidateClassExpression(value = "#this.isMiniBus() == true ? #this.getSeats()<=17 : true", message = "{Expression.licenseplate.validminibus}")
public class LicensePlate extends AbstractEntity {
private static final long serialVersionUID = -6871697166535810224L;
@NotEmpty
@ColumnTransformer(read = "UPPER(licensePlate)", write = "UPPER(?)")
@Column(nullable = false, unique = true)
private String licensePlate;
// The engine euro level (3,4,5,6)
@Range(min = 0, max = 6)
@NotNull
@Column(nullable = false, columnDefinition = "INTEGER default 0")
private int engineEuroLevel = 0;
@NotNull(message = "{NotNull.licenseplate.enginetype}")
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private EngineType engineType = EngineType.DIESEL;
// If the bus has the particulate filter
@NotNull(message = "{NotNull.licenseplate.particulatefilter}")
@Column(nullable = false, columnDefinition = "BOOLEAN default false")
private boolean particulateFilter = false;
// Number of seats
@NotNull
@Range(min = 1, max = 99)
@Column(nullable = false, columnDefinition = "INTEGER default 50")
private int seats = 50;
// If the vehicle is a minibus
@NotNull
@Column(nullable = false, columnDefinition = "BOOLEAN default false")
private boolean miniBus = false;
@NotNull(message = "{NotNull.licenseplate.country}")
// The country of the vehicle
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private Country country;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Note> notes = new ArrayList<>();
public LicensePlate() {
}
public String getLicensePlate() {
return licensePlate;
}
public void setLicensePlate(String licensePlate) {
this.licensePlate = licensePlate;
}
public int getEngineEuroLevel() {
return engineEuroLevel;
}
public void setEngineEuroLevel(int engineEuroLevel) {
this.engineEuroLevel = engineEuroLevel;
}
public int getSeats() {
return seats;
}
public void setSeats(int seats) {
this.seats = seats;
}
public boolean isMiniBus() {
return miniBus;
}
public void setMiniBus(boolean miniBus) {
this.miniBus = miniBus;
}
public EngineType getEngineType() {
return engineType;
}
public void setEngineType(EngineType engineType) {
this.engineType = engineType;
}
public boolean isParticulateFilter() {
return particulateFilter;
}
public void setParticulateFilter(boolean particulateFilter) {
this.particulateFilter = particulateFilter;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
@Override
public String toString() {
return "LicensePlate [licensePlate=" + licensePlate + ", engineEuroLevel=" + engineEuroLevel + ", engineType="
+ engineType + ", particulateFilter=" + particulateFilter + ", seats=" + seats + ", miniBus=" + miniBus
+ "]";
}
public List<Note> getNotes() {
return notes;
}
public void setNotes(List<Note> notes) {
this.notes = notes;
}
}
@RestControllerAdvice
public class ApplicationExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
throw new RuntimeException(ex);
}
@Override
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
throw new RuntimeException(ex);
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
throw new RuntimeException(ex);
}
}
@Transactional
@RepositoryRestResource(excerptProjection = LicensePlateProjection.class)
@PreAuthorize("isAuthenticated()")
public interface LicensePlateRepository
extends PagingAndSortingRepository<LicensePlate, Long>, RevisionRepository<LicensePlate, Long, Integer> {
public LicensePlate findByLicensePlate(String licencePlate);
{"licensePlate":"asdfg","engineEuroLevel":"4","particulateFilter":true,"seats":18,"miniBus":true,"country":"http://localhost:8080/api/v1/countries/1"}
{
"errors": []
}
@Test
@WithMockUser(roles = "ADMIN")
public void validateMinibusWithMoreThan17SeatsFails() {
assertEquals(1, countryRepository.count());
LicensePlate plate = new LicensePlate();
plate.setLicensePlate("AA123BB");
plate.setEngineEuroLevel(3);
plate.setMiniBus(true);
plate.setSeats(18);
plate.setCountry(countryRepository.findFirstByOrderByIdAsc());
Set<ConstraintViolation<LicensePlate>> constraintViolations = validator.validate(plate);
assertEquals(1, constraintViolations.size());
ConstraintViolation<LicensePlate> constraintViolation = constraintViolations.iterator().next();
assertEquals("I veicoli di tipo minibus possono avere al massimo 17 posti (16 passeggeri più il conducente).",
constraintViolation.getMessage());
}
org.springframework.data.rest.core.RepositoryConstraintViolationException
;在构造函数中,我看到我的错误是正确的,我可以看到错误消息和正确的结构:
org.springframework.data.rest.core.ValidationErrors: 1 errors
Error in object 'LicensePlate': codes [ValidateClassExpression.LicensePlate,ValidateClassExpression]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [LicensePlate.,]; arguments []; default message [],org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute@520b6a25]; default message [I veicoli di tipo minibus possono avere al massimo 17 posti (16 passeggeri più il conducente).]
最佳答案
我认为 Spring MVC 不知道在哪里显示错误消息,因为违反类级约束的约束不指示任何特定属性。
高压 @ScriptAssert
提供 reportOn()用于指定要报告错误的属性的属性。
对于您的自定义约束,您可以通过使用通过 ConstraintValidatorContext
公开的 API 创建自定义约束违规和属性路径来执行相同的操作。 .
关于spring - Spring Data REST 中带有验证错误的空消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46670224/
我已经为使用 JGroups 编写了简单的测试。有两个像这样的简单应用程序 import org.jgroups.*; import org.jgroups.conf.ConfiguratorFact
我有一个通过 ajax 检索的 json 编码数据集。我尝试检索的一些数据点将返回 null 或空。 但是,我不希望将那些 null 或空值显示给最终用户,或传递给其他函数。 我现在正在做的是检查
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Why does one often see “null != variable” instead of “
嗨在我们公司,他们遵循与空值进行比较的严格规则。当我编码 if(variable!=null) 在代码审查中,我收到了对此的评论,将其更改为 if(null!=variable)。上面的代码对性能有影
我正在尝试使用 native Cordova QR 扫描仪插件编译项目,但是我不断收到此错误。据我了解,这是代码编写方式的问题,它向构造函数发送了错误的值,或者根本就没有找到构造函数。那么我该如何解决
我在装有 Java 1.8 的 Windows 10 上使用 Apache Nutch 1.14。我已按照 https://wiki.apache.org/nutch/NutchTutorial 中提
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: what is “=null” and “ IS NULL” Is there any difference bet
Three-EyedRaven 内网渗透初期,我们都希望可以豪无遗漏的尽最大可能打开目标内网攻击面,故,设计该工具的初衷是解决某些工具内网探测速率慢、运行卡死、服务爆破误报率高以及socks流
我想在Scala中像在Java中那样做: public void recv(String from) { recv(from, null); } public void recv(String
我正在尝试从一组图像补丁中创建一个密码本。我已将图像(Caltech 101)分成20 X 20图像块。我想为每个补丁创建一个SIFT描述符。但是对于某些图像补丁,它不返回任何描述符/关键点。我尝试使
我在验证器类中自动连接的两个服务有问题。这些服务工作正常,因为在我的 Controller 中是自动连接的。我有一个 applicationContext.xml 文件和 MyApp-servlet.
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 已关闭10 年前。 问题必须表现出对要解决的问题的最低程度的了解。告诉我们您尝试过做什么,为什么不起作用,以
大家好,我正在对数据库进行正常的选择,但是 mysql_num_rowsis 为空,我不知道为什么,我有 7 行选择。 如果您发现问题,请告诉我。 真的谢谢。 代码如下: function get_b
我想以以下格式创建一个字符串:id[]=%@&stringdata[]=%@&id[]=%@&stringdata[]=%@&id[]=%@&stringdata[]=%@&等,在for循环中,我得到
我正在尝试使用以下代码将URL转换为字符串: NSURL *urlOfOpenedFile = _service.myURLRequest.URL; NSString *fileThatWasOpen
我正在尝试将NSNumber传递到正在工作的UInt32中。然后,我试图将UInt32填充到NSData对象中。但是,这在这里变得有些时髦... 当我尝试将NSData对象中的内容写成它返回的字符串(
我正在进行身份验证并收到空 cookie。我想存储这个 cookie,但服务器没有返回给我 cookie。但响应代码是 200 ok。 httpConn.setRequestProperty(
我认为 Button bTutorial1 = (Button) findViewById(R.layout.tutorial1); bTutorial1.setOnClickListener
我的 Controller 中有这样的东西: model.attribute("hiringManagerMap",hiringManagerMap); 我正在访问此 hiringManagerMap
我想知道如何以正确的方式清空列表。在 div 中有一个列表然后清空 div 或列表更好吗? 我知道这是一个蹩脚的问题,但请帮助我理解这个 empty() 函数:) 案例)如果我运行这个脚本会发生什么:
我是一名优秀的程序员,十分优秀!