WebServer/Spring

[Spring] 스프링 MVC의 Controller

gangintheremark 2023. 9. 17. 19:10
728x90

스프링 MVC의 Controller는 다음과 같은 특징이 있다.

  • 다양한 타입의 파라미터 처리, 다양한 타입의 리턴 타입 사용 가능
  • GET/POST 전송 방식을 어노테이션으로 처리 가능

@RequestMapping

@RequestMapping사용자가 요청한 URL 정보를 이용하여 실제 처리되는 메서드를 선택할 수 있다.

URL 패턴

@Controller
public class TestController {

    // 💡 매핑값 하나
    // http://localhost:8090/app/xxx
    @RequestMapping(value = "/xxx")
    public String xxx() {

        return "main";
    }

    // 💡 매핑값 두 개
    // http://localhost:8090/app/xxx2
    // http://localhost:8090/app/xxx3
    @RequestMapping({"/xxx2","/xxx3"})
    public String xxx2() {

        return "main";
    }

    // 💡 특정값으로 시작
    // http://localhost:8090/app/yyy
    // http://localhost:8090/app/yyyABC
    // http://localhost:8090/app/yyy/xxx (X)
    @RequestMapping(value = "/yyy*")
    public String yyy() {

        return "main";
    }

    // 💡 특정 경로 하나 (없거나 하나)
    // http://localhost:8090/app/zzz/
    // http://localhost:8090/app/zzz/aaa
    // http://localhost:8090/app/zzz/aaa/ccc (X)
    @RequestMapping(value = "/xxx/*")
    public String zzz() {

        return "main";
    }

    // 💡 특정 경로 여러개
    // http://localhost:8090/app/kkk/
    // http://localhost:8090/app/kkk/aaa
    // http://localhost:8090/app/kkk/aaa/ccc
    @RequestMapping(value = "/kkk/**")
    public String kkk() {

        return "main";
    }

    // 💡 경로 중간에 패턴지정
    // http://localhost:8090/app/eee/임의값/fff
    @RequestMapping(value="/eee/**/fff")
    public String eee() {

        return "main";
    }
}

 

HTTP 요청 메서드

  • @GetMapping("/ ")
  • @PostMapping("/ ")
@Controller
public class TestController {
    // GET 방식
    @GetMapping("/loginForm")
    public String loginForm() {
        System.out.println("loginForm");
        return "loginForm";
    }

    // POST 방식
    @PostMapping("/login")
    public String login() {
        System.out.println("login");
        return "main";
    }
}

 

root경로에 대한 처리

중복되는 형태의 요청 매핑값

💡 예시
@RequestMapping(value="/member/add")
@RequestMapping(value="/member/del")
@Controller
@RequestMapping("/member")
public class TestController {

    // http://localhost:8090/app/member/add
    @RequestMapping(value="/add")
    public String add(){
        System.out.println("TestController.add");
        return "main";
    }

    // http://localhost:8090/app/member/del
    @RequestMapping(value="/del")
    public String del(){
        System.out.println("TestController.del");
        return "main";
    }
}

다양한 타입의 파라미터 처리

Controller파라미터가 자동으로 수집되는 기능이 있다. 따라서 매번 request.getParameter()를 이용하는 불편함을 없앨 수 있다.

 

Lombok의 @Data 어노테이션 처리된 LoginDTO 클래스가 있다고 가정하자. TestController의 메서드가 LoginDTO를 파라미터로 사용하게 되면 자동으로 setter 메서드가 동작하면서 파라미터를 수집한다.

    @GetMapping("/login")
    public String login(LoginDTO dto) {
        System.out.println(dto);
        return "main";
    }

Controller가 파라미터를 수집하는 방식은 파라미터 타입에 따라 자동으로 변환하는 방식을 이용한다. 이 때, @RequestParam 어노테이션을 사용하면 메서드의 파라미터 영역에 임의의 타입이나 이름을 지정할 수 있다.

 

@RequestParam : HTTP의 요청 파라미터를 매핑하며 요청 파라미터는 필수사항 ➜ 값이 없을 시, 예외발생

  • required=false : 값이 없을 시, 예외 대신 null 값으로 설정 가능
  • defaultValue="값" : 값이 없을 시, null 값 대신에 기본값으로 설정 가능
    @GetMapping("/login")
    public String login(@RequestParam(value="userid", required=false, defaultValue = "OO") String id, 
                        @RequestParam("passwd") String pw) {
        System.out.println(id + " " + pw);    
        return "main";
    }

    // 요청 파라미터명과 저장할 변수명이 일치
    @GetMapping("/login")
    public String login(@RequestParam  String userid, @RequestParam String passwd) {
        System.out.println(userid + " " + passwd);    
        return "main";
    }

    @GetMapping("/login")
    public String login(@RequestParam Map<String, String> m) {

        return "main";
    }

 

Model 타입의 파라미터

Controller의 메서드는 Model 타입을 파라미터로 지정할 수 있다. Model객체는 JSP에 컨트롤러에서 생성된 데이터를 담아 전달하는 역할이다. 이를 이용해 뷰(View)로 전달해야하는 데이터를 담아 보낸다.

    @RequestMapping("/xxx")
    public String xxx(Model m) {
          // m.addAttribute("key", "value");
            m.addAttribute("userid", "홍길동");
        return "hello";
    }
💡 JSP에서 Model값을 가져올 때는 ${"key값"}

 

@ModelAttribute

스프링 MVC의 Controller는 기본적으로 Java Beans 규칙에 맞는 객체는 다시 화면으로 객체를 전달한다. DTO 같은 경우는 Java Beans 규칙에 맞기 때문에 자동으로 다시 화면까지 전달된다. 전달될 때에는 클래스명의 앞글자는 소문자로 처리된다.

    @GetMapping("/login")
    public String login(LoginDTO dto, int page) {

        return "main";
    }
<!-- main.jsp 일부 -->
<h2> login정보: ${loginDTO} </h2>
<h2> Page : ${page} </h2>

이때, LoginDTO는 화면으로 전달되지만 기본 자료형의 경우는 파라미터로 선언하더라도 기본적으로 화면까지 전달되지 않는다. 이러한 파라미터를 Model에 담아 전달한다

 

@ModelAttribute는 파라미터 타입에 관계없이 무조건 Model에 담아 전달되므로, 파라미터로 전달된 데이터를 다시 화면에서 사용해야할 경우 유용하게 사용한다.

    @GetMapping("/login")
    public String login(LoginDTO dto, @ModelAttribute("page") int page) {

        return "main";
    }

LoginDTO는 사용자 입력값 저장용도 및 모델로도 사용이 가능하다.

    @GetMapping("/login")
    public String login(@ModelAttribute("key") LoginDTO dto, @ModelAttribute("page") int page) {
        dto.setUserid("gang");
        dto.setPasswd("1234");
        return "main";
    }

 

scope

3 개의 scope에 모델을 저장할 수 있다.

  • request scope: Model 이용
  • session scope : HttpSession 이용
  • application scope : ServletContext 이용
@Controller
public class TestController {

    ServletContext application;

    public void setServletContext(ServletContext servletContext) {
        this.application = servletContext;
    }

    @RequestMapping("/xxx")
    public String xxx(Model m, HttpSession session) {

        // request scope에 저장
        m.addAttribute("key", "value");

        // session scope에 저장
        session.setAttribute("key", "value");

        // application scope에 저장
        application.setAttribute("key", "value");

        return "main";
    }
}

다양한 타입의 리턴 타입

  • String : 이동하려는 JSP 파일이름을 반환하기 위해 사용
  • void : 호출하는 URL과 동일한 이름의 JSP 의미
  • VO DTO : 주로 JSON 타입의 데이터를 만들어서 반환
  • Model ModelAndView : Model로 데이터를 반환하거나 화면까지 같이 지정하는 경우 사용
@Controller
public class TestController {

    // 💡 리턴타입: String

    // view 정보O , model 정보X
    @RequestMapping("/aaa")
    public String fun() {
        System.out.println("aaa 요청");
        return "hello";
    }

    // 💡 리턴타입: String, 파라미터: Model, Map, @ModelAttribute(key) ...

    // view 정보O , model 정보O
    @RequestMapping("/bbb")
    public String fun(Model m) {
        System.out.println("bbb 요청");
        m.addAttribute("userid", "옥지");
        return "hello";
    }

    // 💡 리턴타입: ModelAndView

    // view 정보O , model 정보O
    @RequestMapping("/ccc")
    public ModelAndView fun() {
        System.out.println("ccc 요청");
        ModelAndView mav = new ModelAndView();
        mav.setViewName("hello"); // view 정보
        mav.addObject("userid", "홍길동"); // model 정보
        return mav;
    }

    // 💡 리턴타입: DTO

    // view 정보X , model 정보O
    // 요청매핑값으로 view처리 ➜ ddd.jsp
    @RequestMapping("/ddd")
    public @ModelAttribute("key") LoginDTO fun() {
    // @ModelAttribute("")에서 key 값을 주지않으면 클래스명(loginDTO)가 키 값이 된다.
        System.out.println("ddd 요청");
        LoginDTO dto = new LoginDTO("gang", "1234");
        return dto;
    }

    // 💡 리턴타입: ArrayList<LoginDTO>

    // view 정보X , model 정보O
    // 요청매핑값으로 view처리 ➜ eee.jsp
    @RequestMapping("/eee")
    public @ModelAttribute("key") ArrayList<LoginDTO> fun() {
        System.out.println("eee 요청");

        ArrayList<LoginDTO> list = new ArrayList<LoginDTO>();
        list.add(new LoginDTO("gang", "1234"));
        list.add(new LoginDTO("remark", "5678"));

        return list;
    }

    // 💡 리턴타입 :void
    // view 정보X model 정보X
    // 요청매핑값으로 view처리 ➜ fff.jsp
    @RequestMapping("/fff")
    public void fun() {
        System.out.println("fff 요청");
    }

}

+ POST 방식의 한글처리 

CharacterEncodingFilter API를 적용한다

<!-- web.xml -->

    	<filter>
		<filter-name>filter</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>filter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

 

728x90