Spring Boot多Rest Controller异常:ViewController无法返回视图
问题分析:独立ViewController无法返回视图的原因
我在独立文件中编写了两个Rest Controller,AuthController代码如下:
@RestController @RequestMapping("/api/auth") public class AuthController { @PostMapping("login") public ResponseEntity<JwtAuthResponeDto> login(@RequestBody LoginDto loginDto){ Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( loginDto.getUsername(), loginDto.getPassword())); SecurityContextHolder.getContext().setAuthentication(authentication); String token = jwtTokenProvider.generateToken(authentication); return new ResponseEntity<>(new JwtAuthResponeDto(token), HttpStatus.OK); } @PostMapping("register") public ResponseEntity<String> register(@RequestBody RegisterDto registerDto) { if (userRepository.existsByUsername(registerDto.getUsername())) { return new ResponseEntity<>("Username is taken!", HttpStatus.BAD_REQUEST); } UserEntity user = new UserEntity(); user.setUsername(registerDto.getUsername()); user.setPassword(passwordEncoder.encode((registerDto.getPassword()))); RoleEntity role = roleRepository.findByName("role_user").get(); user.setRoles(Collections.singletonList(role)); userRepository.save(user); return new ResponseEntity<>("User registered success!", HttpStatus.OK); }}
ViewController代码如下:
@RestController @RequestMapping("/views") public class ViewController { @GetMapping("login") public ModelAndView login(){ return new ModelAndView("login"); } }
问题现象
当前ViewController无法返回login视图,但将该@GetMapping方法移至AuthController中则可正常运行。访问/views/login时浏览器无内容,终端仅输出以下日志:
2023-06-12 13:20:59.994 INFO 10516 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2023-06-12 13:20:59.995 INFO 10516 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2023-06-12 13:21:00.003 INFO 10516 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 3 ms
原因解析
核心问题出在ViewController使用的@RestController注解上:
- @RestController是@Controller和@ResponseBody的复合注解,它会强制将控制器中所有方法的返回值默认序列化为JSON/XML格式的响应体,而不是将返回值解析为视图名称去查找对应的页面模板。
- 当把返回ModelAndView的方法移到AuthController时,Spring MVC对ModelAndView对象有特殊处理逻辑:即使控制器标注了@RestController,ModelAndView作为视图容器对象,不会被@ResponseBody序列化,而是正常触发视图解析流程,所以能渲染login视图。
- 但在独立的ViewController中,@RestController的@ResponseBody规则完全生效,Spring会尝试把ModelAndView对象序列化为JSON(但该对象的序列化结果可能是空结构或浏览器无法解析的内容),导致浏览器没有显示预期的视图页面。
解决方法
将ViewController上的@RestController替换为@Controller注解:
@Controller @RequestMapping("/views") public class ViewController { @GetMapping("login") public ModelAndView login(){ return new ModelAndView("login"); } }
这样Spring MVC会正确识别方法返回的ModelAndView为视图请求,进而查找并渲染login模板页面。
内容的提问来源于stack exchange,提问作者el merrre
相关产品推荐
相关产品推荐

