<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>kr.or.connect</groupId>
<artifactId>daoexam</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>daoexam</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.5.RELEASE</spring.version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- basic data source -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
- web.xml 파일에 설정
- javax.servlet.ServletContainerInitializer 사용
- 서블릿 3.0 스펙 이상에서 web.xml 파일을 대신해서 사용할 수 잇다
- org.springframework.web.WebApplicationInitializer 인터페이스를 구현해서 사용
<?xml version="1.0" encoding = "UTF-8"?>
<web-app>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:WebMVCContextConfig.xml</param-value>
<init-param>
</servlet>
</web-app>
@Configuration
- org.springframework.context.annotation의 Configuration 애노테이션과 Bean 애노테이션 코드를 이용하여 스프링 컨테이너에 새로운 빈 객체를 제공할 수 있다.
@EnableWebMvc
- DispatcherServlet의 RequestMappingHandlerMapping, RequestMappingHandlerAdapter, ExceptionHandlerExceptionResolver, MessageConverter 등 Web에 필요한 빈들을 대부분 자동으로 설정해준다.
- xml로 설정의 <mvc:annotation-driven/> 와 동일하다.
- 기본 설정 이외의 설정이 필요하다면 WebMvcConfigurerAdapter 를 상속받도록 Java config class를 작성한 후, 필요한 메소드를 오버라이딩 하도록 한다.
@ComponentScan
- ComponentScan애노테이션을 이용하면 Controller, Service, Repository, Component애노테이션이 붙은 클래스를 찾아 스프링 컨테이너가 관리하게 된다.
- DefaultAnnotationHandlerMapping과 RequestMappingHandlerMapping구현체는 다른 핸드러 매핑보다 훨씬 더 정교한 작업을 수행한다. 이 두 개의 구현체는 애노테이션을 사용해 매핑 관계를 찾는 매우 강력한 기능을 가지고 있다. 이들 구현체는 스프링 컨테이너 즉 애플리케이션 컨텍스트에 있는 요청 처리 빈에서 RequestMapping애노테이션을 클래스나 메소드에서 찾아 HandlerMapping객체를 생성하게 된다.
- HandlerMapping은 서버로 들어온 요청을 어느 핸들러로 전달할지 결정하는 역할을 수행한다.
- DefaultAnnotationHandlerMapping은 DispatcherServlet이 기본으로 등록하는 기본 핸들러 맵핑 객체이고, RequestMappingHandlerMapping은 더 강력하고 유연하지만 사용하려면 명시적으로 설정해야 한다.
WebMvcConfigurerAdapter
- org.springframework.web.servlet.config.annotation. WebMvcConfigurerAdapter
- @EnableWebMvc 를 이용하면 기본적인 설정이 모두 자동으로 되지만, 기본 설정 이외의 설정이 필요할 경우 해당 클래스를 상속 받은 후, 메소드를 오버라이딩 하여 구현한다.
@RequestMapping
@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); }
기본적으로 모든 요청을 한 DispatcherServlet이 받지만, css, img 와 같은 요청들은 어디로 보낼지 결정하는 것이다.
@Override public void addViewControllers(final ViewControllerRegistry registry) { System.out.println("addViewControllers가 호출됩니다"); registry.addViewController("/").setViewName("main"); }
특정 url에 대한 처리를 controller 클래스를 맵핑하지 않고 처리할 수 있게 해주는 것이다.
//view name (위에서 'main')은 ViewResolver라는 객체를 이용해서 찾는다. //getInternalResourceViewResolver()에서 설정된 형태로 뷰를 사용하게 된다. @Bean public InternalResourceViewResolver getInternalResourceViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); ///WEB-INF/views/main.jsp resolver.setPrefix("/WEB-INF/views/");//main 앞쪽 resolver.setSuffix(".jsp"); //main 뒷 쪽 return resolver; }
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>Spring JavaConfig Sample</display-name>
<servlet>
<servlet-name>mvc</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</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
plusForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <form method = "post" action = "plus"> value 1: <input type = "text" name = "value1"><br> value 2: <input type = "text" name = "value2"><br> <input type="submit" value="확인"> </form> </body> </html>
"/plus" URL로 요청이 들어오면 입력 값을 두개 받고, post 방식으로 보낸다.
plusResult.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> ${value1} 더하기 ${value2} (은/는) ${result} 입니다. </body> </html>
결과값을 보여주는 창이다
PlusController.java
package kr.or.connect.mvcexam.controller;
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.springframe ork.web.bind.annotation.RequestParam;
@Controller
public class PlusController {
@GetMapping(path="/plusform") //Get방식으로 들어온다. URL은 /plusform
public String plusform() { //"plusForm.jsp"의 이름이다.
return "plusForm"; //WebMvcContextConfiguration에서 getInternalResourceViewResolver()함수가 경로와 파일 양식을 붙인다.
}
@PostMapping(path="/plus") //"value1"이라는 이름으로 넘어온 값을 value1 변수로 받는다. modelMap은 Spring이 제공하는 객체다. 알아서 request scope에 맵핑 시켜준다.
public String plus(@RequestParam(name = "value1", required = true) int value1,
@RequestParam(name = "value2", required = true) int value2, ModelMap modelMap) {
int result = value1 + value2;
modelMap.addAttribute("value1", value1);
modelMap.addAttribute("value2", value2);
modelMap.addAttribute("result", result);
return "plusResult";
}
}
userForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method = "post" action = "regist">
name : <input type = "text" name = name"><br>
email : <input type = "text" name = "email"><br>
age : <input type = "text" name = "age"><br>
<input type = "submit" value = "확인">
</form>
</body>
</html>
User
package kr.or.connect.mvcexam.dto;
public class User {
private String name;
private String email;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", email=" + email + ", age=" + age + "]";
}
}
UserController.java
package kr.or.connect.mvcexam.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import kr.or.connect.mvcexam.dto.User;
@Controller
public class UserController {
@RequestMapping(path = "/userform", method = RequestMethod.GET)
public String userform() {
return "userForm";
}
@RequestMapping(path = "/regist", method = RequestMethod.POST)
public String regist(@ModelAttribute User user) {
System.out.println("사용자가 입력한 user 정보입니다. 해당 정보를 이용하는 코드가 와야합니다.");
System.out.println(user);
return "regist";
}
}
goodsById.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
id: ${id } <br>
user_agent: ${userAgent }<br>
path: ${path }<br>
</body>
</html>
GoodsController.java
package kr.or.connect.mvcexam.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
@Controller
public class GoodsController {
@GetMapping("/goods/{id}")
public String getGoodsById(@PathVariable(name="id") int id,
@RequestHeader(value="User-Agent", defaultValue="myBrowser") String userAgent,
HttpServletRequest request,
ModelMap model
) {
String path = request.getServletPath();
System.out.println("id : " + id);
System.out.println("user_agent : " + userAgent);
System.out.println("path : " + path);
model.addAttribute("id", id);
model.addAttribute("userAgent", userAgent);
model.addAttribute("path", path);
return "goodsById";
}
}