ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [2-ch6 스프링] MVC의 Controller 어노테이션 (@RequestMapping, @requestParam, Model, 반환타입)
    Back-End/Spring Legacy 2022. 8. 16. 12:04

     

    스프링 MVC Controller 특징

     

    스프링 MVC를 이용하는 경우 작성되는 Controller는 아래와 같은 특징이 있다.

     

    - HttpServletRequest, HttpServletResponse를 거의 사용할 필요 없이 필요한 기능 구현
    - 다양한 타입의 파리미터 처리, 다양한 타입의 리턴 타입 사용 가능
    - GET, POST 방식 등 전송 방식에 대한 처리를 어노테이션으로 가능
    - 상속/ 인터페이스 방식 대신 어노테이션만으로도 필요한 설정 가능 

     

     



    @Controller

     

     

    프로젝트 내 org.zerock.controller 패키지 폴더에 SampleController라는 이름의 클래스를 작성한다. 

     

     

     

    @Controller
    @RequestMapping("/sample/*")
    @Log4j2
    public class SampleController {
    	
    	@RequestMapping("")
    	public void basic() {
    		log.info("basic.....");
    	}
    	
    	//get,post방식
    	@RequestMapping(value = "/basic",  method= {RequestMethod.GET, RequestMethod.POST})
    	public void basicGet() {
    		log.info("basic get.....");
    	}
        }

     

     

    SampleController 클래스 선언부에 @Controller라는 스프링 MVC에서 사용하는 어노테이션을 적용하고 있다. 작성된 SampleController클래스는 자동으로 스프링 객체(Bean)으로 등록 되는데 servlet-context.xml에 그 이유가 있다. 

     

     

    <context:component-scan base-package="org.zerock.controller" />

     

     

     

    이미 servlet-context.xml에 <context:component-scan>이라는 태그를 이용해서 지정된 패키지를 조사(스캔)하도록 설정되어 있다. 해당 패키지에 선언된 클래스들을 조사하면서 스프링 객체 설정에 사용되는 어노테이션들을 가진 클래스들을 파악하고 필요하다면 이를 객체로 생성해 관리하게 된다. 

     

     

     

    만약 SampleController 클래스가 스프링에서 관리되면, 화면상에는 클래스 옆에 작게 's' 모양의 아이콘이 추가된다. 

     

     


     

     

     @RequestMapping

     

    클래스의 선언부에는 @Controller와 함께 @RequestMapping을 많이 사용한다. 

     

    @RequestMapping은 현재 클래스의 모든 메서드들의 기본적인 URL 경로가 된다. 예를 들어, SampleController 클래스를 

    @RequestMapping("/sample/*") 이라는 경로로 지정했다면 /sample/aaa , /sample/bbb 와 같은 URL 모두 SampleController 에서 처리하게 된다. @RequestMapping은 클래스의 선언과 메서드 선언에 모두 사용할 수 있다. 

     

     

    @Controller 어노테이션은 추가적인 속성을 지정할 수 없지만, @RequestMapping은 몇 가지 속성을 추가할 수 있다. 이 중 가장 많이 사용하는 속성이 method 속성이다.  method= {RequestMethod.GET, RequestMethod.POST} 같이 흔히 GET 방식, POST 방식을 구분해서 사용할 수 있다. 

     

     

    스프링 4.3부터는 @GetMapping, @PostMapping이 등장해 축약형 표현이 가능하다. 

     

    //get,post방식
    @RequestMapping(value = "/basic",  method= {RequestMethod.GET, RequestMethod.POST})
    public void basicGet() {
        log.info("basic get.....");
    }
    
    //get방식으로만
    @GetMapping("/basicOnlyGet")
    public void basicGet2() {
        log.info("basic get only get....");
    }

     

    @RequestMapping은 GET,POST 방식 모두를 지원해야 하는 경우 배열로 처리해서 지정할 수 있다. 일반적으로 GET,POST 방식을 주로 사용하지만 요즘은 PUT, DELETE와 같은 방식도 많이 사용하고 있다. 

     

     


     

    Controller의 파라미터 수집

     

    Controller를 작성할 때 가장 편리한 기능은 파라미터가 자동으로 수집되는 기능이다. 이 기능을 이용하면 매번 request.getParameter()를 이용하는 불편함은 없앨 수 있다. 예제를 만들어보자.

     

    org.zerock.domain이라는 패키지를 작성하고 SampleDTO라는 클래스를 작성한다. 

     

     

    package org.zerock.domain;
    
    import lombok.Data;
    
    @Data
    //만약 롬북을 사용하지 않았다면 get/set 등 메서드를 각각 만들어줘야 했다. 
    public class SampleDTO {
    	private String name;
    	private int age;
    }

     

     

    SampleDTO 클래스는 Lombok @Data  어노테이션을 이용해서 처리한다. @Data를 이용하게 되면 getter/setter, equals(), toString() 등 메서드를 자동으로 생성하기 때문에 편리하다. 

     

    SampleController의 메서드가 SampleDTO를 파라미터로 사용하게 되면 자동으로 setter 메서드가 동작하면서 파라미터를 수집하게 된다. 

     

     

    //파라미터 값 받아서 출력 get방식이기에 url에 값 입력 가능
    	@GetMapping("/ex01")
    	public String ex01(SampleDTO dto) {
    		log.info(""+dto);
    		return "ex01";
    	}

     

     

    localhost:7070/sample/ex01?name=AAA&age=10 을 입력한 후의 log를 살펴보면 다음과 같다. 

    2번은 URL에 파라미터값을 입력하지 않았을 때 name에는 null age에는 0이 저장되는 걸 확인할 수 있고 3번에서는 제대로 값을 넣었을 때 처리된 값을 확인할 수 있다. 

     

     

     

     

    파라미터 수집과 변환 - @RequestParam

     

    Controller가 파라미터를 수집하는 방식은 파라미터 타입에 따라 자동으로 변환하는 방식을 말한다.  예를들어 SampleDTO에는 int 타입으로 선언된 age가 자동으로 숫자로 변환되는 것을 볼 수 있다. 만일) 기본 자료형이나 문자열 등을 이용한다면 파라미터의 타입만을 맞게 선언해주는 방식을 사용할 수 있다. 

     

    //파라미터의 타입 선언, 파라미터로 사용된 변수의 이름과 전달되는 파라미터의 이름이 다른 경우 유용
    @GetMapping("/ex02")
    public String ex02(@RequestParam("name") String name, @RequestParam("age") int age) {
        log.info("name : " +name);
        log.info("age : " +age);
        return "ex02";
    }

     

    ex02() 메서드는 파라미터에 @RequestParam 어노테이션을 사용해서 작성되었는데, 파라미터로 사용된 변수의 이름과 전달되는 파라미터의 이름이 다른 경우 유용하게 사용된다. 위의 코드에서는 String name 이라는 파라미터 값들을 내가 @RequestParam("name")을 통해 name이라고 부르겠다는 의미이다. 

     

     

     

    리스트, 배열 처리

     

    동일한 이름의 파라미터가 여러 개 전달되는 경우 ArrayList<> 등을 이용해서 처리가 가능하다. 

     

    //동일한 이름의 파라미터가 여러 개 전달되는 경우
    @GetMapping("/ex02List")
    public String ex02List(@RequestParam("ids")ArrayList<String> ids) {
        log.info("ids : " +ids);
        return "ex02List";
    }

     

    스프링은 파라미터의 타입을 보고 객체를 생성하므로 파라미터의 타입은 List<>와 같이 인터페이스 타입이 아닌 실제적인 클래스 타입으로 지정한다. 위 코드의 경우 'ids'라는 이름의 파라미터가 여러 개 전달되더라도 ArrayList<String>이 생성되어 자동으로 수집된다. 배열 또한 ArrayList<>대신 String [ ] 라고 파라미터의 타입을 지정해주면 자동으로 객체 생성되는 것. 

     

     

     

    객체 리스트

     

    만약 전달하는 데이터가 SampleDTO와 같이 객체 타입이고 여러 개를 처리해야 한다면 약간의 작업을 통해 한 번에 처리할 수 있다. 일단) SampleDTO의 리스트를 포함하는 SampleDTOList 클래스를 설계한다. 

     

    package org.zerock.domain;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import lombok.Data;
    
    @Data
    public class SampleDTOList {
    	
    	private List<SampleDTO> list;
    	
    	public SampleDTOList() {
    		list = new ArrayList<>();
    	}
    }

     

    SampleController에는 SampleDTOList 타입을 파라미터로 사용하는 메서드를 작성한다. 

     

    //객체 리스트
    @GetMapping("/ex02Bean")
    public String ex02Bean(SampleDTOList list) {
        log.info("list dots: " + list);
        return "ex02Bean";
    }

     

    파라미터는 '[인덱스]'와 같은 형식으로 전달해서 처리할 수 있다. 

    프로젝트 경로/sample/ex02Bean?list[0].name=aaa&list[2].age=11 이런식으로 입력하면 되는데 톰켓은 버전에 따라 특수문자를 허용하지 않기 때문에 '['는 '%5B'로 ']'는 '%5D'로 변경한다. 

     

     

     

     

    @DateTimeFormat

     

    원하는 형식으로 날짜를 변환하기 위해서 @InitBinder를 사용할 수 있지만 주로 @DateTimeFormat이 많이 사용된다. 새로운  클래스 TodoDTO를 만들어서 아래와 같이 dueDate값의 pattern을 지정해준다. 

     

    package org.zerock.domain;
    
    import java.util.Date;
    
    import org.springframework.format.annotation.DateTimeFormat;
    
    import lombok.Data;
    
    @Data
    public class TodoDTO {
    	
    	private String title;
    	@DateTimeFormat(pattern ="yyyy/MM/dd")
    	private Date dueDate;
    }

     

     

    그 후 SampleController에 TodoDTO 반환형을 가지는 todo 파라미터를 매개변수로 받아서 호출한다.

     

    @GetMapping("/ex03")
    public String ex03(TodoDTO todo) {
        log.info("todo: " + todo);
        return "ex03";
    }

     

    아래와 같이 2020/08/15 URL을 지정해둔 패턴과 똑같게 입력했을 때 dueDate의 로그 형식을 확인해보면 날짜 타입으로 변환된 걸 알 수 있다. 

     

     

     

     

    ★ Model이라는 데이터 전달자

     

    중요한 부분이니 제대로 이해하고 넘어가야한다. Contoller의 메서드를 작성할 때 특별하게 Model이라는 타입을 파라미터로 지정할 수 있다. Model 객체는 JSP에 컨트롤러에서 생성된 데이터를 담아서 전달하는 역할을 하는 존재이다. JSP와 같은 뷰(VIEW)로 전달해야 하는 데이터를 담아서 보낼 수 있다는 말인데, 메서드의 파라미터에 Model 타입이 지정된 경우 스프링은 특별하게 Model 타입의 객체를 만들어 메서드에 주입하게 된다. Model은 모델 2 방식에서 사용하는 request.setAttribute()와 유사한 역할을 한다. 

     

     

     

    < Servlet에서 모델2 방식으로 데이터를 전달하는 방식>

    request.setAttribute("serverTime", new java.util.Date());
    RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/home.jsp);
    dispatcher.forward(request,response);

     

     

    <스프링 MVC에서 Model을 이용한 데이터 전달>

    public String home(Model model){
    mode.addAttribute("serverTime", new java.util.Date());
    return "home";
    }

     

     

    메서드의 파라미터를 Model 타입으로 선언하게 되면 자동으로 스프링 MVC에 Model 타입 객체를 만들어 주기 때문에 개발자의 입장에서는 필요한 데이터를 담아 주는 작업만으로 모든 작업이 완료된다. Model을 사용해야 하는 경우 Controller에 전달된 데이터를 이용해 추가적인 데이터를 가져와야 하는 상황이다.

     

    예를들어 )

    - 리스트 페이지 번호를 파라미터로 전달받고, 실제 데이터를 View로 전달해야 하는 경우 

    - 파라미터들에 대한 처리 후 결과를 전달해야 하는 경우 

     

     

     

    @ModelAttribute 어노테이션

     

    웹 페이지의 구조는 Request에 전달된 데이터를 가지고 필요하다면 추가적인 데이터를 생성해 화면으로 전달하는 방식으로 동작한다. Model의 경우는 파라미터로 전달된 데이터는 존재하지 않으며 화면에서 필요한 데이터를 전달하기 위해 사용한다. 예를들어 페이지 번호는 파라미터로 전달되지만, 결과 데이터를 전달하려면 Model에 담아서 전달한다. 

     

    스프링 MVC의 Controller는 기본적으로 Java Beans 규칙에 맞는 객체는 다시 화면으로 객체를 전달한다. 좁은 의미에서 Java Beans의 규칙은 단순히 생성자가 없거나 빈 생성자를 가져야 하며, getter/setter를 가진 클래스의 객체들을 의미한다. 앞의 예제에서 파라미터로 사용된 SampleDTO의 경우는 Java Bean의 규칙에 맞기 때문에 자동으로 다시 화면까지 전달된다. 전달될 때에는 클래스명의 앞글자는 소문자로 처리된다. 반면 기본 자료형의 경우 파라미터로 선언하더라도 화면까지는 전달되지 않는다. 

     

    @GetMaaping("/ex04")
    public String ex04(SampleDTO dto, int page) {
    		log.info("dto: " + dto);
    		log.info("page: " + page);
    		
    		return "/sample/ex04";
    	}

     

     

    위의 ex04는 SampleDTO 타입과 int 타입의 데이터를 파라미터로 사용한다. 결과를 확인하기 위해서 '/WEB-INF/views' 폴더 아래 sample 폴더를 생성하고 리턴값에서 사용한 'ex04'에 해당하는 ex04.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>
    
    <h2>SAMPLEDTO   ${sampleDTO }</h2>
    <h2>PAGE ${page }</h2>
    
    </body>
    </html>

     

     

    서버를 실행하고 'http://localhost:8080/sample/ex04?name=aaa&age=11&page=9'와 같이 호출한다고 했을 때 화면에 SampleDTO만이 전달되고 int 타입의 page는 전달되지 않았다. 그럼 jsp 즉) 사용자 화면에 값을 출력하려면 어떻게 해야할까? 

     

     

    바로 @ModelAttribute를 사용해야한다. 이는 강제로 전달받은 파라미터를 Model에 담아서 전달하도록 할 때 필요한 어노테이션이다. @ModelAttribute가 걸린 파라미터는 타입에 관계없이 무조건 Model에 담아서 전달되므로, 파라미터로 전달된 데이터를 다시 화면에서 사용해야할 경우 유용하게 사용된다. 

     

     

    //모델에 담는 데이터는 -> 파라미터가 아니라 다른 곳(service, DB ,, )에서 발생한 데이터를 담는 용기
    //@ModelAttribute jsp에서 사용할 key값을 지정해준다 생각하면 되겠다. 
    // ex) @ModelAttribute("slist") SampleDTOList list 이렇게 파라미터로 지정되어 있다고 하면
    // SampleDTOList의 list라는 값들을 나는 slist라고 부를래 이런 의미 
    public String ex04(SampleDTO dto, @ModelAttribute("page") int page) {
        log.info("dto: " + dto);
        log.info("page: " + page);
    
        return "/sample/ex04";
    }

     

     

     

    따라서 @ModelAttribute("page")를 붙여주면 화면까지 파라미터가 전달되므로 브러우저를 통해 호출했을 때 출력되는 것을 확인할 수 있다. jsp에서 ${page} 이렇게 el 표현식으로 사용.

     

     

     

    ex04 출력 값

     

     

     

     

    Controller의 리턴 타입

     

    스프링 MVC의 구조가 기존의 상속과 인터페이스에서 어노테이션을 사용하는 방식으로 변한 이후에 가장 큰 변화 중 하나는 리턴타입이 자유로워 졌다는 점이다. 

     

     

    1. void 타입

     

    메서드 리턴 타입을 void로 지정하는 경우 일반적인 경우에는 해당 URL의 경로를 그대로 jsp 파일의 이름으로 사용하게 된다. 

    @GetMapping("/ex05")
    public void ex05() {
        log.info("/ex05........." );
    }

     

    위의 경우 /sample/ex05를 호출하면 /WEB-INF/views/sample/ex05.jsp 를 찾는다.

     

     

    2. String 타입

     

    void 타입과 더불어 가장 많이 사용하는 것은 String 타입이다. String 타입은 상황에 따라 다른 화면을 보여줄 필요가 있을 경우 유용하게 사용된다. (if ~ else 와 같은 처리가 필요한 상황) 일반적으로 String 타입은 현재 프로젝트의 경우 JSP 파일의 이름을 의미한다. 프로젝트 생성 시 기본으로 만들어진 HomeController의 코드를 보면 String 반환 타입으로 사용하는 것을 볼 수 있다. 

     

    @RequestMapping(value = "/", method = RequestMethod.GET)
    	public String home(Locale locale, Model model) {
    		log.info("Log4j2.......................");
    		log.info("Welcome home! The client locale is {}.", locale);
    		
    		Date date = new Date();
    		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
    		
    		String formattedDate = dateFormat.format(date);
    		
    		model.addAttribute("serverTime", formattedDate );
    		
    		return "home";
    	}

     

    home() 메서드는 'home'이라는 문자열을 리턴했기 때문에 경로는 'WEB-INF/views/home.jsp' 경로가 된다. String 타입에는 다음과 같은 키워드를 붙여서 사용할 수도 있다. 

     

    redirect : 리다이렉트 방식으로 처리하는 경우
    forward : 포워드 방식으로 처리하는 경우 

     

     

    redirect와 forward에 대한 설명을 간략하게 해보자면 

     

     

    스프링에선 주로 redirect를 사용한다. redirect는 한 번만 사용하고 다음에는 사용되지 않는 데이터를 전달하기 위해서 사용한다. 즉) 2번의 호출이 일어나는 것을 알 수 있는데 위의 사진을 봤을 때 123번에 전화했을 때 1번 호출, 근데 여기가 아니다? redirect로 124번을 설정해뒀다하면 124번 호출하는데 1번 총 2번이 되는 것. 

     

     

     

    객체 타입

     

    Controller의 메서드 리턴 타입을 VO(Value Object)나 DTO(Data Transfer Object) 타입 등 복합적 데이터가 들어간 객체 타입으로 지정할 수 있는데 이는 주로 JSON 데이터를 만들어 내는 용도로 사용한다. 

     

    JSON을 사용하기 위해선 pom.xml에 아래와 같은 라이브러리를 추가해줘야한다.

     

    <!-- json 추가 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.13.3</version>
    </dependency>

     

     

    그다음 SampleController에 아래와 같은 메서드를 생성한다.

     

    //json
    @GetMapping("/ex06")
    public @ResponseBody SampleDTO ex06() {
        log.info("/ex06........." );
        SampleDTO dto =  new SampleDTO();
        dto.setAge(10);
        dto.setName("홍길동");
    
        return dto;
    }

     

     

     

    실행해 봤을 때 스프링 MVC는 자동으로 브라우저에 JSON 타입으로 객체를 변환해서 전달하게 된다. 개발자 도구 (F12)를 통해 살펴보면 전송하는 MIME 타입이 'application/json'으로 처리되는 것을 알 수 있다. 

     

     

     

     

    ResponseEntity 타입

     

     

    Web을 다루다 보면 HTTP 프로토콜의 헤더를 다루는 경우도 종종 있다. 스프링 MVC 사상은 HttpServletRequest나 HttpServletResponse를 직접 핸들링하지 않아도 이런 작업이 가능하도록 작성되었기 때문에 이러한 처리를 위해 ResponseEntity를 통해서 원하는 헤더 정보나 데이터를 전달할 수 있다.  

     

     

    	//ResponseEntity 타입
    	@GetMapping("/ex07")
    	public ResponseEntity<String> ex07(){
    		log.info("/ex07........." );
    		
    		//{"name" : "홍길동"}
    		String msg = "{\" name\" : \"홍길동\"}";
    		
    		HttpHeaders headers = new HttpHeaders();
    		headers.add("Content-Type", "application/json;charset=UTF-8");
    		
    		return new ResponseEntity<>(msg, headers, HttpStatus.OK);
    	}

     

     

    ResponseEntity는 HttpHeaders 객체를 같이 전달할 수 있고, 이를 통해 원하는 HTTP 헤더 메시지를 가공하는 것이 가능하다. ex07()의 경우 브라우저에는 JSON 타입이라는 헤더 메시지와 200 OK라는 상태 코드를 전송한다. 

     

     

     

     

     


    Controller의 Exception 처리

     

    Controller를 작성할 때 예외 상황을 고려하려면 처리해야 하는 작업이 엄청 늘어날 수 밖에 없다. 그래서 스프링 MVC에서는 이러한 작업을 아래와 같이 처리할 수 있다.

     

    - @ExceptionHandler와 @ControllerAdvice를 이용한 처리
    - @ResponseEntity를 이용하는 예외 메시지 구성

     

     

    1. @ControllerAdvice

     

    @ControllerAdvice는 뒤에서 따로 포스팅 하겠지만 AOP를 이용하는 방식이다. 간단히 말하면 핵심 로직은 아니지만 프로그램에서 필요한 '공통적인 관심사는 분리'하자는 개념이다. Controller를 작성할 때는 메서드의 모든 예외사항을 전부 핸들링해야 한다면 중복적이고 많은 양의 코드를 작성해야 하지만, AOP 방식을 이용하면 공통적인 예외사항에 대해서는 별도로 @ControllerAdvice를 이용해서 분리하는 방식이다.

     

    org.zerock.exception이라는 패키지 생성하고 여기에 CommonExceptionAdvice 클래스를 생성한다 .

     

    package org.zerock.exception;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.servlet.NoHandlerFoundException;
    
    import lombok.extern.log4j.Log4j2;
    
    @ControllerAdvice
    @Log4j2
    public class CommonExceptionAdvice {
    	
    	//내가 처리하고 싶은 exception을 지정한다.
    	@ExceptionHandler(Exception.class)
    	public String exception(Exception ex, Model model) {
    		log.error("Exception ... "+ex.getMessage());
    		model.addAttribute("exception", ex);
    		log.error(model);
    		return "error_page";
    	}
    	}

     

    CommonExceptionAdvice 클래스에는 @ControllerAdvice라는 어노테이션과 @ExceptionHandler라는 어노테이션을 사용하고 있다. @ControllerAdvice는 해당 객체가 스프링의 컨트롤러에서 발생하는 예외를 처리하는 존재임을 명시하는 용도로 사용하고, @ExceptionHandler 어노테이션의 속성으로는 Exception 클래스 타입을 지정할 수 있다. 위의 예제에서는 Exception.class를 지정하였으므로 모든 예외에 대한 처리가 except()만을 이용해서 처리할 수 있다. 만일 특정 타입의 예외를 다루고 싶다면 Exception.class 대신 구체적인 예외 클래스를 지정해야한다. 

     

    또한) jsp 화면에서도 구체적인 메시지를 보고 싶다면 Model을 이용해 전달하는 것이 좋다.

     

    그 전에 먼저 해야될 것이 바로 org.zerock.exception 패키지는 servlet-context.xml에서 인식하지 않기 때문에 <component-scan>을 이용해서 해당 패키지의 내용을 조사해야한다.

     

    <context:component-scan base-package="org.zerock.exception" />

     

     

     

    CommonExceptionAdvice 클래스의 except()의 리턴값은 문자열로 jsp 파일 경로가 된다. jsp는 error_page이므로 /WEB-INF/views 폴더에 작성한다.

     

     

     

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ page session="false" import="java.util.*"%>
    <!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>
    
      <h4><c:out value="${exception.getMessage()}"></c:out></h4>
    
      <ul>
       <c:forEach items="${exception.getStackTrace() }" var="stack">
         <li><c:out value="${stack}"></c:out></li>
       </c:forEach>
      </ul>
    
    </body>
    </html>

     

    예외 메시지가 정상적으로 출력되는지 확인하기 위해서 고의로 숫자나 날짜 등의 파라미터 값을 변환에 문제 있게 만들어 호출해 볼 수 있다. 

     

     

     

     

    반응형

    댓글

Designed by Tistory.