Java 用@Configuration和@Controller注释了一个类。需要重构方面的帮助吗

Java 用@Configuration和@Controller注释了一个类。需要重构方面的帮助吗,java,spring,spring-boot,thymeleaf,Java,Spring,Spring Boot,Thymeleaf,下面是我的类,其中我必须同时使用@Configuration和@Controller,因为整个应用程序中应该只有一个Thymeleaf实例,否则我会得到例外。我的其他类是用@RequestScope注释的,因此我不能使用单例范围的bean。所以我混合了配置和控制器来获得结果,但我觉得这是一个糟糕的做法。如果有人能帮助我重构代码并消除这种不好的做法,我将不胜感激 更新 我使用的是spring boot 1.5.14。我使用以下方法处理模板,并将处理后的模板保持为字符串 @Controller @C

下面是我的类,其中我必须同时使用
@Configuration
@Controller
,因为整个应用程序中应该只有一个
Thymeleaf
实例,否则我会得到例外。我的其他类是用
@RequestScope
注释的,因此我不能使用单例范围的bean。所以我混合了配置和控制器来获得结果,但我觉得这是一个糟糕的做法。如果有人能帮助我重构代码并消除这种不好的做法,我将不胜感激

更新

我使用的是
spring boot 1.5.14
。我使用以下方法处理模板,并将处理后的模板保持为字符串

@Controller
@Configuration
@EnableWebMvc
@ApplicationScope
public class MyThymeleafConfig {

    @GetMapping("/view-template")
    @ResponseBody
    public void viewTemplates() {

        Context context = new Context();
        context.setVariable("mydata", "this is it");

        String html = templateEngine().process("templates/view-to-process.html", context);
        System.out.println(html);
    }


    /*

    configuration for thymeleaf and template processing

    */

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(thymeleafTemplateResolver());
        return templateEngine;
    }

    @Bean
    public SpringResourceTemplateResolver thymeleafTemplateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setPrefix("classpath:");
        templateResolver.setSuffix(".html");
        templateResolver.setCacheable(false);
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }

    @Bean
    public ThymeleafViewResolver thymeleafViewResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        return viewResolver;
    }
}
要为静态资源提供服务,请使用以下配置:

@Configuration
@EnableWebMvc
public class StaticResourceConfig implements WebMvcConfigurer {

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

我还提到了我不能接受下面提到的答案的原因,因为我的其他类都有请求范围

更新

我还有其他与
@RequestScope
相关的类,如下所示:

@RequestScope
@Controller
public class SecondController {

    @GetMapping("/viewPage")
    public String viewPage(Model model) {
        model.addAttribute("mydata", "sjfbsdf");
        model.addAttribute("somedata", "sjdfksfjhshgdfbskdfj");
        return "templates/view-to-process.html";
    }
}

假设您使用的是SpringBoot,因为标签中有它,所以不需要任何配置就可以使用Thymeleaf

只要拥有,您就可以:

@GetMapping("/view-template")
public String viewTemplates(Model model) {
    model.addAttribute("mydata", "this is it")
    return "view-to-process";
}
它应该会起作用


顺便说一句,是的,在同一个类中有
@Configuration
@Controller
是您永远不需要的。

这两个注释用于不同的对象,因此最好不要在同一个类中使用它们。因为它违背了原则。

如果您看到注释(Spring 5)的源代码,您有:

控制器 配置
@Target(ElementType.TYPE)
@保留(RetentionPolicy.RUNTIME)
@记录
@组成部分
公共@接口配置{
/**
*显式指定关联的Springbean定义的名称
*使用此配置类。如果未指定(常见情况),
*将自动生成一个bean名称。
*自定义名称仅适用于通过
*组件扫描或直接提供给{@link AnnotationConfigApplicationContext}。
*如果配置类注册为传统的XMLBean定义,
*bean元素的名称/id将优先。
*@返回建议的组件名称(如果有)(否则为空字符串)
*@请参阅org.springframework.beans.factory.support.DefaultBeannamGenerator
*/
@别名(注释=组件.class)
字符串值()默认为“”;
}
您注意到它们是相同的(它们都包括更通用的
@组件
注释)。因此,看到这一事实,将两者同时使用是没有意义的。另一件更重要的事情是,spring正试图为这些注释提供一种标签意义,以描述其用途

配置
用于将必要的部分连接到应用程序,以便在启动阶段正常运行

控制器
用于定义作为外部世界接口的类,即:其他参与者如何使用您的应用程序


正如您所看到的,将这两个组件一起使用没有什么意义。

看看Spring引导文档

还有这篇文章

看看Spring引导指南(您不需要@Bean配置)

用两个词来分隔
1. <代码>配置
配置

2.
TemplateController
使用
viewTemplates()
和另一个端点

要重构它们,将
@Bean
方法分离到一个单独的
@Configuration
类非常简单:

@Configuration
// @Controller  is redundant as we have @Configuration
// @EnableWebMvc is also redundant since you already annotate it in other class
// @ApplicationScope is also redundant since you do not need to create bean of MyThymeleafConfig anymore
public class MyThymeleafConfig {
    /*

    configuration for thymeleaf and template processing

    */

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(thymeleafTemplateResolver());
        return templateEngine;
    }

    @Bean
    public SpringResourceTemplateResolver thymeleafTemplateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setPrefix("classpath:");
        templateResolver.setSuffix(".html");
        templateResolver.setCacheable(false);
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }

    @Bean
    public ThymeleafViewResolver thymeleafViewResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        return viewResolver;
    }
}
@Configuration
类返回相同的bean实例,而不管您调用bean方法多少次

现在在控制器中:

@Controller
public class MyThymeleafConfig {

    @Autowired
    private SpringTemplateEngine templateEngine;

    @GetMapping("/view-template")
    @ResponseBody
    public void viewTemplates() {

        Context context = new Context();
        context.setVariable("mydata", "this is it");

        String html = templateEngine.process("templates/view-to-process.html", context);
        System.out.println(html);
    }
}

但老实说,我不知道为什么您必须手动与TemplateEngine/SpringTemplateEngine交互,因为springteleaf将自动为您处理带有给定变量的模板。(如@sedooe示例)

不要将请求映射放在配置类中,这违反了关注点分离的原则。您可以采用如下方法

所有应用程序范围的bean都是在类路径根目录中的
application
类中设置的<由于
应用程序
类具有应用范围,因此,code>应用程序
类是拥有thymeleaf静态资源配置的最佳场所

@SpringBootApplication
@EnableWebMvc
public class Application{

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public ViewResolver viewResolver() {
       ThymeleafViewResolver resolver = new ThymeleafViewResolver();
       resolver.setTemplateEngine(templateEngine());
       resolver.setCharacterEncoding("UTF-8");
       resolver.setCache(false);
       return resolver;
    }

   @Bean
   public TemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setEnableSpringELCompiler(true);
        templateEngine.addDialect(new LayoutDialect());
        templateEngine.addDialect(new Java8TimeDialect());
        templateEngine.setTemplateResolver(templateResolver());
        return templateEngine;
   }

   private ITemplateResolver templateResolver() {
       SpringResourceTemplateResolver resolver = new 
            SpringResourceTemplateResolver();
       resolver.setApplicationContext(applicationContext);
       resolver.setPrefix("classpath:/templates/");
       resolver.setTemplateMode(TemplateMode.HTML);
       return resolver;
   }
}
如果将静态资源放在类路径中名为staticpublic的文件夹中,springboot会将其标识为静态资源的位置。然后您不需要重写
addResourceHandlers
方法。如果确实想这样做,可以在应用程序类扩展
WebMVCConfigureAdapter
中这样做。您不需要单独的类来配置静态资源路径


不要将请求映射放在配置类中,将它们放在单独的控制器类中,如:

@Controller
public class MyController {
   @GetMapping("/view-template")
   @ResponseBody
   public void viewTemplates() {
         Context context = new Context();
         context.setVariable("mydata", "this is it");

         String html = templateEngine().process("templates/view-to-process.html", context);
         System.out.println(html);
    }
}

当然,springboot允许您以自己喜欢的方式进行操作,但您最好坚持一种通用方法。

就个人而言,我不会这样做,因为我希望尽可能将关注点分开。为这个单控制器方法创建一个类,(可能是ViewController),按照您想要的方式定义它的范围,并在其中添加您的RequestMapping。因此,您已经将配置与控制器分离,但这在这里是不可能的,因为在整个应用程序中只能有一个thymeleaf实例。请帮助我重构代码。我还将悬赏给重构上述代码的人,让其余的控制器用request作用域进行注释。有些人也请用requestb作用域bean尝试你各自的答案。我在等着赏金。谢谢你抽出时间。其实我忘了
@SpringBootApplication
@EnableWebMvc
public class Application{

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public ViewResolver viewResolver() {
       ThymeleafViewResolver resolver = new ThymeleafViewResolver();
       resolver.setTemplateEngine(templateEngine());
       resolver.setCharacterEncoding("UTF-8");
       resolver.setCache(false);
       return resolver;
    }

   @Bean
   public TemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setEnableSpringELCompiler(true);
        templateEngine.addDialect(new LayoutDialect());
        templateEngine.addDialect(new Java8TimeDialect());
        templateEngine.setTemplateResolver(templateResolver());
        return templateEngine;
   }

   private ITemplateResolver templateResolver() {
       SpringResourceTemplateResolver resolver = new 
            SpringResourceTemplateResolver();
       resolver.setApplicationContext(applicationContext);
       resolver.setPrefix("classpath:/templates/");
       resolver.setTemplateMode(TemplateMode.HTML);
       return resolver;
   }
}
@Controller
public class MyController {
   @GetMapping("/view-template")
   @ResponseBody
   public void viewTemplates() {
         Context context = new Context();
         context.setVariable("mydata", "this is it");

         String html = templateEngine().process("templates/view-to-process.html", context);
         System.out.println(html);
    }
}