[SPRING] @Configuration 및 @Controller 클래스를 주석 처리했습니다. 리팩토링에 도움이 필요하다.
SPRING@Configuration 및 @Controller 클래스를 주석 처리했습니다. 리팩토링에 도움이 필요하다.
아래는 @Configuration과 @Controller를 모두 사용해야하는 클래스입니다. Thymeleaf 인스턴스가 하나 뿐이므로 전체 애플리케이션에서 예외가 발생합니다. 다른 클래스에는 @RequestScope 주석이 달려 있으므로 singleton scoped 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/");
}
}
최신 정보
또한 다른 클래스에 요청 범위가 있으므로 아래 답변을 받아 들일 수없는 이유를 언급했습니다.
최신 정보
아래 @RequestScopelike 클래스가 있습니다.
@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";
}
}
해결법
-
==============================
1.Spring Boot를 사용하고 있다고 가정 할 때, 태그를 가지고 있기 때문에, Thymeleaf를 사용하기 위해 어떤 설정도 필요하지 않습니다.
Spring Boot를 사용하고 있다고 가정 할 때, 태그를 가지고 있기 때문에, Thymeleaf를 사용하기 위해 어떤 설정도 필요하지 않습니다.
이 의존성을 갖춤으로써 다음을 수행 할 수 있습니다.
@GetMapping("/view-template") public String viewTemplates(Model model) { model.addAttribute("mydata", "this is it") return "view-to-process"; }
그리고 그것은 효과가있다.
그건 그렇고, 같은 클래스에 @Configuration과 @Controller를 갖는 것이 결코 필요하지 않은 것입니다.
-
==============================
2.주석 (Spring 5)의 소스 코드를 보았다면 :
주석 (Spring 5)의 소스 코드를 보았다면 :
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { /** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any (or empty String otherwise) */ @AliasFor(annotation = Component.class) String value() default ""; }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { /** * Explicitly specify the name of the Spring bean definition associated * with this Configuration class. If left unspecified (the common case), * a bean name will be automatically generated. * <p>The custom name applies only if the Configuration class is picked up via * component scanning or supplied directly to a {@link AnnotationConfigApplicationContext}. * If the Configuration class is registered as a traditional XML bean definition, * the name/id of the bean element will take precedence. * @return the suggested component name, if any (or empty String otherwise) * @see org.springframework.beans.factory.support.DefaultBeanNameGenerator */ @AliasFor(annotation = Component.class) String value() default ""; }
당신은 그것들이 동일하다는 것을 알게된다 (둘 다 더 일반적인 @Component 어노테이션을 포함한다). 따라서이 사실을 봄으로써 둘 다 사용하는 것은 의미가 없습니다. 더 중요한 것은, 스프링이 사용법을 설명해야하는 이러한 주석의 의미를 나타내는 태그를 제공하려고한다는 것입니다.
구성은 시작 단계에서 제대로 작동하기 위해 응용 프로그램에 필요한 부분을 연결하는 데 사용됩니다.
Controller는 외부 세계에 대한 인터페이스 역할을하는 클래스를 정의하는 데 사용됩니다. 즉, 다른 액터가 응용 프로그램을 어떻게 사용할 수 있습니까?
보시다시피, 그것들을 함께 사용하는 것은 거의 의미가 없습니다.
-
==============================
3.스프링 부트 문서의 일반적인 레이아웃을 살펴보십시오.
스프링 부트 문서의 일반적인 레이아웃을 살펴보십시오.
또한이 기사 SOLID 프로그래밍 원리
Spring Boot Thymeleaf (@Bean 설정이 필요 없습니다)
두 단어로 분리해야합니다. 1. MyThymeleafConfig 구성 2. viewTemplates () 및 다른 끝점이있는 TemplateController
-
==============================
4.리팩토링하기 위해 @Bean 메서드를 별도의 @Configuration 클래스로 분리하는 것이 쉽고 간단합니다.
리팩토링하기 위해 @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 클래스는 빈 메소드를 호출 한 횟수와 상관없이 동일한 빈 인스턴스를 리턴한다.
이제 컨트롤러에서 :
@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); } }
그러나 솔직히, 나는 왜 Spring-thymeleaf가 주어진 변수로 템플릿을 자동으로 처리하기 때문에 TemplateEngine / SpringTemplateEngine과 수동으로 상호 작용해야하는지 모른다. (@sedooe 예와 같이)
-
==============================
5.구성 클래스 내에 요청 매핑을 두지 마십시오. 관심사 분리 원칙을 위반합니다. 아래처럼 접근 할 수 있습니다.
구성 클래스 내에 요청 매핑을 두지 마십시오. 관심사 분리 원칙을 위반합니다. 아래처럼 접근 할 수 있습니다.
모든 응용 프로그램 광역 bean은 클래스 경로의 루트에있는 Application 클래스에 설정됩니다. Application 클래스는 응용 프로그램 범위를 가지고 있기 때문에 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; } }
staticpath를 classpath에 static 또는 public 폴더에 넣으면 springboot가이를 정적 리소스의 위치로 식별합니다. 그런 다음 addResourceHandlers 메소드를 재정의 할 필요가 없습니다. 정말하고 싶다면 WebMvcConfigurerAdapter를 확장하는 Application 클래스에서 수행 할 수 있습니다. 정적 리소스 경로를 구성하기 위해 별도의 클래스가 필요하지 않습니다.
요청 매핑을 구성 클래스 내에 두지 말고 별도의 컨트롤러 클래스에 넣습니다.
@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는 당신이 당신이 좋아하는 방법으로 그것을 할 수 있지만, 당신은 더 나은 일반적인 접근 방식에 충실해야합니다.
-
==============================
6.이 두 주석은 다른 것들을위한 것이므로 동일한 클래스에서 사용하지 않는 것이 좋습니다. 그것은 Separation of Concerns 교장에 반대하기 때문입니다.
이 두 주석은 다른 것들을위한 것이므로 동일한 클래스에서 사용하지 않는 것이 좋습니다. 그것은 Separation of Concerns 교장에 반대하기 때문입니다.
from https://stackoverflow.com/questions/51636312/annotated-a-class-with-configuration-and-controller-need-help-in-refactoring by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring 3.1 환경 설정 : 환경이 주입되지 않음 (0) | 2019.05.07 |
---|---|
[SPRING] 스프링 데이터 jpa와 querydsl로 왼쪽 결합 (0) | 2019.05.07 |
[SPRING] Spring MVC 테스트의 빈 예외 바디 (0) | 2019.05.06 |
[SPRING] spring-boot를 사용할 때 spring-boot 명령 줄 속성을 사용할 수 있습니까? (0) | 2019.05.06 |
[SPRING] SpEL에서 어떻게 값을 벗어나나요? (0) | 2019.05.06 |