Spring Boot、Thymeleaf 和 @Controller

5

我正在尝试使用Spring Boot,并遇到了一些困惑。我的应用程序中有两个@Controller,但第二个似乎无法正确处理REST调用,反而被Thymeleaf接管了请求。

基本上,我的情况是这样的:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
     public static void main(String[] args) throws Throwable {
            SpringApplication.run(Application.class, args);
     }
}

那么

@Configuration
@EnableWebMvcSecurity
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    Environment env;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .antMatchers("/", "/home").permitAll()
          .antMatchers("/webjars/**").permitAll()
          .antMatchers("/console/**").permitAll()
          .antMatchers("/resources/**").permitAll()
          .anyRequest().authenticated();
        http.formLogin().loginPage("/login").permitAll().and().logout()
                .permitAll();
        http.csrf().disable(); // for angularjs ease
        http.headers().frameOptions().disable(); //for H2 web console
    }
}

并且

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }

    @Override
      public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/public/**").addResourceLocations("classpath:/public/");
        registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/");
      }

}

同时还有两个控制器。这一个正常工作,所以它可以接收来自简单的AngularJS客户端的调用并做出响应:

@Controller
@RequestMapping("/foo")
public class MyController {

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    @PreAuthorize("hasRole('ROLE_FOO')")
    public String getFoo() {
        return "foooooo";
    }
}

这是出问题的控制器,没有响应:

@Controller
@RequestMapping("/sick/1")
public class SickController {

    @Autowired
    SickRepository sickRepository;

    @RequestMapping(method = RequestMethod.GET)
    public Sick getSickById() {
        return sickRepository.findOne(1);
    }

}

显然后面我会将其更改为从URL作为路径变量来提取ID,但是出于调试目的,我回到了硬编码。

日志在我的请求到达/sick/1之前没有显示任何内容。此时我得到了以下结果:

org.thymeleaf.exceptions.TemplateInputException: Error resolving template "sick/1", template might not exist or might not be accessible by any of the configured Template Resolvers
    at org.thymeleaf.TemplateRepository.getTemplate(TemplateRepository.java:245)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1104)

但是为什么它会被发送到模板引擎而不是我的控制器...?
1个回答

17
您可能忘记在getSickById控制器方法上添加@ResponseBody注释。
您还可以将@Controller注释替换为@RestController,Spring将对该控制器中的所有控制器方法应用@ResponseBody。

好的,我现在明白了。所以我的控制器方法返回了一些东西,Spring 希望进一步解析为视图,对吗?而那个注释告诉它不要这样做,只需返回方法输出的任何内容即可。 - jabal
4
@jabal 是的,没错。ResponseBody注解告诉Spring将您方法的返回值写入响应中,而不是将其解析为视图。我建议您查看这篇文章http://www.javacodegeeks.com/2013/07/spring-mvc-requestbody-and-responsebody-demystified.html或Spring文档以获取更多详细信息。背后还有更多的逻辑。例如,当您使用ResponseBody时,Spring将返回值转换为JSON或XML等格式,并使用HttpMessageConverters进行转换等等... - Bohuslav Burghardt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接