Почему язык моего компонента LocaleResolver игнорируется для сообщений о нарушении проверки? - PullRequest
0 голосов
/ 01 ноября 2019

Я бы хотел управлять языком для сообщений о нарушении ограничения проверки с помощью LocaleResolver bean.

Учитывая

import java.util.Locale;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.FixedLocaleResolver;

@Configuration
public class SpringBootFixedI18nConfiguration implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        return new FixedLocaleResolver(Locale.ENGLISH);
    }
}

и

import javax.validation.constraints.NotNull;

public class SomeRequest {
    @NotNull
    private String someValue;

    public SomeRequest() {
    }

    public SomeRequest(@NotNull String someValue) {
        this.someValue = someValue;
    }
}

и

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SomeController {
    private static final ValidatorFactory VALIDATOR_FACTORY = Validation.buildDefaultValidatorFactory();
    private static final Validator VALIDATOR = VALIDATOR_FACTORY.getValidator();

    @GetMapping("/path")
    public String someMethod(@RequestBody SomeRequest someRequest) {
        Set<ConstraintViolation<SomeRequest>> violations = VALIDATOR.validate(someRequest);
        if(!violations.isEmpty()) {
            return violations.iterator().next().getMessage();
        }
        return "valid request";
    }
}

Простой тест

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
class SomeControllerIT {
    @Autowired
    private MockMvc mockMvc;

    @Test
    void someMethod() throws Exception {
        MvcResult mockMvcResult = mockMvc.perform(get("/path")
                .content("{\"someValue\":null}")
                .contentType(MediaType.APPLICATION_JSON))
                .andReturn();

        assertEquals(200, mockMvcResult.getResponse().getStatus());
        assertEquals("must not be null", mockMvcResult.getResponse().getContentAsString());
    }
}

не проходит, потому что сообщение на немецком языке, который является языком, настроенным для моей Ubuntu 19.10.

Я знаю, что тамдругие механизмы, такие как настройка системных свойств (см., например, Hibernate Validator: язык сообщений о нарушениях ), но это не вариант для меня.

Я использую Spring Boot 2.2.0. ВЫПУСКАТЬ с

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.5.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

1 Ответ

0 голосов
/ 01 ноября 2019

Я не совсем уверен, но путем инициализации Validator вручную с использованием

... VALIDATOR_FACTORY = Validation.buildDefaultValidatorFactory();
... VALIDATOR = VALIDATOR_FACTORY.getValidator();

Компонент LocaleResolver может отсутствовать в инициированном валидаторе. Вы пытались использовать Validator, предоставленный ApplicationContext? Например:

@Autowired
private Validator validator;

@GetMapping("/path")
public String someMethod(@RequestBody SomeRequest someRequest) {
    Set<ConstraintViolation<SomeRequest>> violations = validator.validate(someRequest);
...

Кстати, вы выполняете проверки вручную (без использования @Valid), чтобы иметь возможность обработать результат проверки в методе? Если это ваше намерение, аннотируя параметр SomeRequest с помощью @Valid и добавляя к суффиксам параметров метода BindingResult, результат проверки будет передан в качестве аргумента вместо пропуска метода:

@GetMapping("/path")
public String someMethod(@Valid @RequestBody SomeRequest someRequest, BindingResult result) {
    if(result.hasErrors()) { ... }
}
...