[Web] Spring MVC 작성 실습

입력을 받을 수 있는 input상자 2개와 버튼 하나를 띄우는 브라우저를 만들고 사용자가 입력한 뒤 버튼을 누르면 입력 받은 2 수를 더해 출력하는 브라우저를 만들자.

1. Maven 프로젝트를 만들고 각종 설정을 해준다. 

2. DispatcherServlet을 FrontController로 사용하기 위해 꼭 설정을 해두어야 한다.
방법은 여러가지가 있지만 아래 두개가 가장 보편적이다. 
 - web.xml 파일에 설정
 - org.springframework.web.WebApplicationInitializer 인터페이스를 구현해서 사용 
    -> 단점 : WebApplicationInitializer 구현체를 찾아 인스턴스를 만들고 해당 인스턴스의 onStartup메소드를 호출하여 초기화 하기때문에 구동 시간이 오래걸린다. 


3. Configuration 클래스 만들기 

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "kr.or.connect.mvcexam.controller" })
//base package 꼭 지정 해주기
public class WebMvcContextConfiguration extends WebMvcConfigurerAdapter {
    @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);
    }
    // 모든 요청이 들어오기 때문에 이렇게 시작하는 요청들은 root 디렉토리 아래의 뒤에 지정해둔 로케이션에서 찾아서 알맞게 사용하라고 알려주는
    // 부분
    // 이부분이 없다면 controller가 가진 requestMapping 부분에 있는 곳에서만 찾으려고 하기 때문에 오류 발생
 
    // default servlet handler를 사용하게 한다
    // WAS의 default Servlet에게 해당 일을 넘기고 default servlet이 static 정보들 읽어서 동작하게함
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
 
    @Override
    public void addViewControllers(final ViewControllerRegistry registry) {
        System.out.println("addViewControllers가 호출됩니다");
        registry.addViewController("/").setViewName("main");
    }
 
    // 여기서 설정된 형태로 view를 찾게된다 - /WEB-INF/views/main.jsp 에서 찾게됨
    @Bean
    public InternalResourceViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
 
}
cs

@Configuration 
: Configuration , Bean annotation 코드를 이용하여 스프링 컨테이너에 새로운 bean 객체를 제공할 수 있다.

@EnableWebMvc
: DispatcherServlet의 RequestMappingHandlerMapping, RequestMappingHandlerAdapter, ExceptionHandlerExceptionResolver, MessageConverter등 Web에 필요한 빈들을 대부분 자동으로 설정해준다. 기본 설정 이외의 설정이 필요하다면, WebMvcConfigurerAdapter를 상속받도록 Java config class를 작성한 후, 필요한 메소드를 오버라이딩 하도록 한다.
(xml 설정의 <mvc:annotation-driven/>과 동일)

@ComponentScan
: Controller, Service, Repository, Component 어노테이션이 붙은 클래스를 찾아 스프링 컨테이너가 관리하게 된다
DefaultAnnotationHandlerMapping(-> DispatcherServlet이 기본으로 등록하는 기본 핸들러 맵핑 객체) 과 RequestMappingHandlerMapping(-> 명시적 설정이 필요) 구현체는 다른 핸들러 매핑보다 훨씬 더 정교한 작업을 수행한다. 이 두개의 구현체는 어노테이션을 사용해 매핑 관계를 찾는 매우 강력한 기능을 가지고 있다. 이들 구현체는 스프링 컨테이너, 즉 ApplicationContext에 있는 요청 처리 bean에서 RequestMapping 어노테이션을 클래스나 메소드에서 찾아 HandlerMapping 객체를 생성하게 된다.
HandlerMapping은 서버로 들어온 요청을 어느 핸들러로 전달할지 결정하는 역할을 수행한다.

@WebMvcConfigurerAdapter
: @EnableWebMvc를 사용하면 기본적인 설정이 모두 자동으로 되지만, 기본 설정 이외의 설정이 필요할 경우 해당 클래스를 상속 받은 후 메소드를 오버라이딩 하여 구현

@Controller
: Controller(Handler)클래스 작성에 사용. 매핑을 위해 @RequestMapping annotaton을 클래스나 메소드에서 사용한다.

@RequestMapping
: Http 요청과 이를 다루기 위한 Controller의 메소드를 연결하는 어노테이션.
- 연결하는 방법
 1. http method와 연결
@RequestMapping(value="/users", method=RequestMethod.POST)
 2. http 특정 헤더와 연결
@RequestMapping(method=RequestMethod.GET, headers="content-type=application/json")
 3. http 파라미터와 연결
@RequestMapping(method=RequestMethod.GET, params="type=raw")
 4.Content-Type Header와 연결
@RequestMapping(method=RequestMethod.GET, consumes="application/json")
 5. Accept Header와 연결
@RequestMapping(method=RequestMethod.GET, produces="application/json")

4. web.xml 설정
<?xml version="1.0" encoding="UTF-8"?>
 
<web-app>
  <display-name>Archetype Created Web Application</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>
cs

xml spring 설정과 Java config spring 설정을 읽어들이도록 DispatcherServlet을 설정한다. 

설정이 끝나면 이클립스를 메이븐 프로젝트 업데이트 / 톰캣 서버 삭제 후 재실행 / 이클립스 재실행 등 변경사항이 적용되도록 해주자.


5. 설정이 끝났으면 예제를 하나씩 수행한다.

1) 설정이 잘 되었는지 확인하는 main.jsp 작성 
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>main page~~~!!</h1>
</body>
</html>
cs

작성 후 서버를 실행해 '/' 으로 들어가면 main 페이지가 출력된다.

2) http://localhost:8080/mvcexam/plusform 요청을 보내면 2개의 입력창과 버튼이 있는 화면을 출력하고 버튼을 클릭하면 .../plus url로 2개의 입력값이 POST 방식으로 서버에 전달되고 서버는 두 값을 더한 값을 JSP에서 출력한다.

- plusForm.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="post" action="plus">  
value1 : <input type="text" name="value1"><br>
value2 : <input type="text" name="value2"><br>
<input type="submit" value="확인">  
</form>  
</body>
</html>
cs

- 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>
cs

- PlusController
@Controller
public class PlusController {
    @GetMapping(path = "/plusform")
    public String plusform() {
        return "plusForm";
    }
 
    @PostMapping(path = "/plus")
    public String plus(@RequestParam(name = "value1", required = trueint value1,
            @RequestParam(name = "value2", required = trueint value2, ModelMap modelMap) {
        int result = value1 + value2;
 
        // key - value 형태
        modelMap.addAttribute("value1", value1);
        modelMap.addAttribute("value2", value2);
        modelMap.addAttribute("result", result);
        return "plusResult";
    }
}
cs

3) http://localhost:8080/mvcexam/userform 으로 요청을 보내면 이름, email, 나이를 물어보는 폼이 출력. 값을 입력하고 확인 버튼을 누르면 post 방식으로 /regist에 정보를 전달하게 되고 regist는 입력받은 결과를 콘솔 화면에 출력

- 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>
cs

-regist.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>
<h2>등록되었습니다. </h2>
</body>
</html>
cs

- UserController.java
@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";
    }
}
 
cs

user 정보를 관리의 용이성을 위해 하나의 클래스 객체로 정의한다
- User.java
package kr.or.connect.mvcexam.dto;
 
public class User {
    private String name;
    private String email;
    private int age;
 
    @Override
    public String toString() {
        return "User [name=" + name + ", email=" + email + ", age=" + 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;
    }
}
 
cs

4) http://localhost:8080/mvcexam/goods/{id} 로 요청을 보내면 서버는 HttpServletRequest를 이용해서 /regist에서 등록되었습니다. 라고 알려주는 페이지를 띄우고, 사용자가 입력한 id 와 사용자의 브라우저 정보, 사용자가 요청한 path 정보를 출력한다. 

-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>
cs


- GoodsController.java
@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";
    }
cs





No comments:

Powered by Blogger.