我们有以下问题。当我们使用ExceptionHandler
创建全局@ControllerAdvice
时,每次将Exception
传递给控制器并让Spring Boot执行转换时,我们就开始关注Long
。
"Failed to convert value of type 'java.lang.String' to required type 'com.example.controlleradvice.model.Location'; nested exception is java.lang.IllegalStateException:"
如果没有全局ExceptionHandler
,它就可以正常工作,我们也不会理解为什么。
全球ExceptionHandler
:
@ControllerAdvice
@RequiredArgsConstructor
public class GlobalControllerAdvice {
private final UserService userService;
private final IndexService indexService;
@ExceptionHandler({Exception.class})
public ModelAndView globalException(final Exception ex, final HttpServletRequest request) {
// userService.getActiveUser().ifPresent(System.out::print);
return new ModelAndView("index")
.addObject("viewModel", indexService.getIndexViewModelWithErrorMessage(ex));
}
MvcConfig:
@Configuration
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
private static final String[] DEFAULT_STATIC_RESOURCES = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/"
};
@Getter
private static Path documentPath;
@Getter
private static Path originalImagePath;
@Getter
private static Path resourceImagePath;
@Getter
private static Path temporaryPath;
@Getter
private static String documentWebUrl;
@Getter
private static String imageWebUrl;
@Getter
private static String imageOriginalUrl;
@Autowired
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
@PostConstruct
public void init() {
requestMappingHandlerAdapter.setIgnoreDefaultModelOnRedirect(true);
}
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler(getDocumentWebUrl() + "/**")
.addResourceLocations("file:" + getDocumentPath() + "/")
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new GzipResourceResolver())
.addResolver(new PathResourceResolver());
registry.addResourceHandler(getImageWebUrl() + "/**")
.addResourceLocations("file:" + getResourceImagePath() + "/")
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new GzipResourceResolver())
.addResolver(new PathResourceResolver());
registry.addResourceHandler(getImageOriginalUrl() + "/**")
.addResourceLocations("file:" + getOriginalImagePath() + "/")
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new GzipResourceResolver())
.addResolver(new PathResourceResolver());
registry.addResourceHandler("/**")
.addResourceLocations(DEFAULT_STATIC_RESOURCES)
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new GzipResourceResolver())
.addResolver(new PathResourceResolver());
}
}
SecurityConfig:
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final SecurityUserService securityUserService;
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/fonts/**", "/scripts/**", "/styles/**",
"/css/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll()
.and().csrf().ignoringAntMatchers("/**");
http.sessionManagement()
.maximumSessions(Integer.MAX_VALUE)
.maxSessionsPreventsLogin(false)
.expiredUrl("/login")
.sessionRegistry(sessionRegistry());
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(securityUserService);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<>(new HttpSessionEventPublisher());
}
}
路线有缺陷的控制器:
@Controller
@RequiredArgsConstructor
@RequestMapping("show")
public class ShowController {
private final IndexService indexService;
@GetMapping
public String showWithId(final @RequestParam Location location, final Model model) {
model.addAttribute("viewModel", indexService.getIndexViewModel(location));
return "index";
}
}
UserService:
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Transactional(readOnly = true)
public Optional<User> getActiveUser() {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
return Optional.empty();
}
return userRepository.findByUsername(authentication.getName());
}
}
为了让我们更难理解潜在的机制,我们找到了5种不同的方法来绕过问题,而不了解问题本身。
我们已经构建了一个Spring Boot Example来重现问题并将其添加到gitlab中。这是发生错误的master branch。 而且这里有一个Branch with the MvcConfig moved到另一个目录。
非常感谢有关真正问题的任何提示!