jsp, jstl은 리액트나 뷰같은 프론트 프레임워크를 따로 사용한다면 필요하지 않지만
javax.servlet 은 필수적이다.
Spring에서 servlet은 Dispatcher Servlet이 사용되고 Front Controller로써 작동하게 된다.
spring-context : 스프링 bean context 사용을 위해서 필요!
spring-webmvc : spring web mvc 모델을 사용할 예정이여서 추가 !
db 도 사용한다면
spring-tx , dbcp , spring-jdbc등도 필요하지만 , 이번 실습에서는 사용하지 않아 넣지 않았다.
기본적으로 의존성들은 그때 그때 필요에 의하여 더하고 설정을 하면 된다.
eclipse facest , pom.xml에서 target/source jdk 설정 들을 마무리 해주면 Spring 설정의 기반을 닦게 된것이다.
의존성을 다운 받았다고 해서 설정이 끝난것이 아니다.
사용자가 직접 Spring MVC 설정을 건들여야 하는 경우도 존재한다.
Dispatcher Servlet을 설정하는 방법은 3가지가 존재한다.
보통 1,3을 많이 쓰인다고 한다.
maven-archetypes의 WEB-INF의 web.xml에
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="3.1"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
metadata-complete="true">
<display-name>Spring JavaConfig Sample</display-name>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
kr.or.connect.mvcexam.config.WebMvcContextConfiguration
kr.or.connect.mvcexam.config.WebMvcControllerConfiguration
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
servlet은 was에서 쓰일 servlet을 설정하는 xml 태그이고.
init-param으로 지정하면 나중에 servlet-config에서 해당 설정됙 이름으로 value값을 가져오는것이 가능하다.
http://wiki.metawerx.net/wiki/Web.xml.InitParam
여기서는 servlet handler에 정보를 입력하는것으로 기억하자.
contextClass에는 스프링 config 방식을 지원하는 클래스를 입력하고
(AnnotationConfigWebApplicationContext은 어노테이션 방식 스프링 설정을 의미한다.)
contextConfigLocation에는 스프링 설정을 저장한 부분을 패키지 포함해서 놓아두면 된다.
그후 servlet-mapping을 지정하면
servlet 설정은 어느정도 끝이 났다.
무엇을 설정하는가?
MVC와 관련된 설정들.
맨 위에 나온 그림들중
HandlerMapping , HandlerAdapter , ViewResolver에 관련된 설정을 진행한다.
많은 설정을 해야하지만 @EnableWebMvc 어노테이션을 적용시키면 대부분 Spring Web에 필요한 빈들은 자동으로 설정 해준다.
나머지, 추가적인 설정을 해야한다면 spring 5 버전부터 WebMvcConfigurer 가상 객체 상속시켜
오버라이딩 하여 고쳐나가면 된다.
package kr.or.connect.mvcexam.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
public class WebMvcContextConfiguration implements WebMvcConfigurer{
// resource 요청 처리하는 위치를 지정해줌.
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(31556926);
registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
}
// default servlet handler를 사용하게 합니다. 매핑정보가 없을경우 실행
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
// 특정 url에 대한 처리를 지정해줌
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
System.out.println("addViewControllers가 호출됩니다. ");
registry.addViewController("/").setViewName("main");
}
// view name을 찾는 resolver 설정 Prefix,suffix 설정한 부분에서 찾아줌
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(31556926);
registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
}
addResourceHandlers를 오버라이딩, 서비스가 아닌 , resource를 요구하는 요청을 처리하는 핸들러를 등록한다.
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
매핑 정보가 없을 경우, default servlet handler가 실행되도록 설정함 ( 리소스 요청 의 경우 handler mapping 매핑되어 있지 않음으로 필요하다. )
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
System.out.println("addViewControllers가 호출됩니다. ");
registry.addViewController("/").setViewName("main");
}
이 메소드에서 registry에 매핑된 주소가 들어오게 되면, 리턴할뷰 를 지정해준다.
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
getInternalResourceViewResolver
setPrefix , Suffix으로 , view의 위치와 확장자를 정하여 리턴할 수 있도록 해준다.
package kr.or.connect.mvcexam.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages= {"kr.or.connect.mvcexam.controller"})
public class WebMvcControllerConfiguration {
}
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class PlusController {
// String , ModelAndView 2가지 타입으로 넘겨줄 수 있음.
@GetMapping(path="/plusForm")
public String plusform() {
return "plusForm";
}
//@RequestParam : Mapping argument에붙을 수 있음 url/meta?no=1;
//http parameter의 name과 매핑되어서 값을 꺼내옴.
//required 속성으로 필수 여부 지정 가능
//@PathVariable , url PathVariable을 가져옴 url/{id}
// placeholder와 @PathVariable이 같다면 값을 가져옴.
//
@PostMapping(path="/plusForm")
public String plusForm(@RequestParam(name="value1",required=true) int value1,
@RequestParam(name="value2",required=true) int value2,ModelMap modelMap) {
//requestScope에 넣어도 되지만, spring이 제공하는 modelMap에 넣어도 된다. 이게 더 권장
//알아서 requestScope에 넣음
modelMap.addAttribute("value1",value1);
modelMap.addAttribute("value2",value2);
modelMap.addAttribute("value3",value1+value2);
return "plusResult";
}
}
Connection 객체의 setAutoCommit을 false로 지정해야한다.
모든 SQL이 실행후 Connection의 commit()을 호출 하고 나서 connection을 종료시킨다.
Spring Java Config에서 트랜잭션 활성화 하는데 사용.
PlatFormTransactionManager 구현체를 매핑하여 사용하게됨
트랜잭션 매니저를 특정해서 사용하고 싶다면 TransactionManagementConfigurer 를 JavaConfig에서 구현하여 리턴한후 사용해야한다.
아니면 트랜잭션 매니저 객체를 생성할때 @Primary 애노테이션을 지정하여 사용한다.
@Configuration
@EnableTransactionManagement
public class DBConfig implements TransactionManagementConfigurer{
private String drivuerClassName = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://localhost:3306/connectdb?useSSL=false";
private String username = "connectuser";
private String userPassword = "connect123!@#";
@Bean
public DataSource dataSource() {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(drivuerClassName);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(userPassword);
return ds;
}
// 트랜 잭션 매니저 지정
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return transactionManager();
}
//플랫폼 트랜잭션 매니저 지정
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
annotationDrivenTransactionManager() 로 사용할 트랜잭션 매니저를 지정한다.
트랜잭션 매니저를 물론 빈으로 등록되어 있어야 함으로 빈으로 생성한다.
DispatcherServlet이 2개 생성되면 2개의 servlet에는 2개의 독립적인 context가 생성되어 빈을 공용으로 사용할 수 없다.
이러한 문제점은 ContextLoaderListener로 해결할 수 있다.
ContextLoaderListener가 생성하는 Context가 root 컨텍스트고, 2개의 servlet context가 자식 context로써 사용하게 하는것 이다.
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>Spring JavaConfig Sample</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
config.ComponentConfig
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
config.MvcConfig
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>