[spring] handler 폴더, api 메소드 만들기, POST맨 사용방법

5 분 소요

서블릿 Filter

  • 톰캣의 Filter (web.xml)
  • Sevlet이 실행되기 전에 먼저 실행됨
  • 권한이 있으면 요청을 수락하고, 권한이 없으면 요청을 거부 할수 있게 해줌
  • 인증 및 권한에 따라 Servlet 을 실행 및 거부 할수 있게 해줌, 일종의 수문장 역할 (if 문 같이)

  • web.xml 을 수정해서 필터 설정을 하거나, 어노테이션을 이용해서 필터 설정을 할수 있음

스프링 Intercept

  • 스프링 자체에서 실행하는 기능
  • 스프링 컨테이너가 들고 있는 Filter (Intercept)
  • 클라이언트의 요청이 Controller로 가기 전에 중간에 요청을 가로채서 검사하는 모듈
  • 예를 들어 클라이언트의 요청이 들어왔는데, 로그인을 하지 않아 Session이 생성되지 않았다면 Interceptor가 체크를 하고 로그인 페이지로 돌려보내주게 됨
  • HandlerInterceptorAdapter 상속해서 구현



handler/PillFilter.java

package kr.co.test.study.handler;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
public class PillFilter implements Filter {
/*
스프링 필터 (Filter)
-	HTTP 요청과 응답을 변경할 수 있는 재사용가능한 코드

- 	여러 개의 필터가 모여 하나의 체인(chain; 또는 사슬)을 형성할 수도 있다. 클라이언트 - 필터1 - 필터2 - 필터3 - 자원

-	애플리케이션의 HTTP 요청 및 응답을 가로채는 데 사용되는 개체. 필터를 사용하여 두 인스턴스에서 두 가지 작업을 수행 할 수 있다.
	client의 요청을 가로채어 작업을 수행할 수 있다.
	response 되기 전에 가로채어 작업을 수행할 수 있다.
	Request/Response의 처리를 chain 하는 것에 대한 이해를 요구

 */
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		/*
		doFilter()
		- 서블릿에 요청 및 응답이 오면 블록 안에있는 코드 실행
		- 필터체인으로 연결하여 준다. 체인의 경우 순서를 지정할 수 있다. 체인의 가장 마지막에는 클라이언트가 요청한 최종 자원이 위치한다.
		1. request 파리미터를 이용하여 요청의 필터 작업 수행, reponse 파라미터를 이용하여 응답의 필터 작업 수행
        2. 체인의 다음 필터 처리
		 */




		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;
		res.addHeader("Access-Control-Allow-Origin", "*");
		/** addHeader(name, value)
		 * 주어진 이름과 정수 값으로 응답 헤더를 설정합니다. 헤더가 이미 설정된 경우 새 값이 이전 값을 덮어씁니다.
		 * <code>containsHeader</code> 메소드는 값을 설정하기 전에 헤더의 존재 여부를 테스트하는 데 사용할 수 있습니다.
		 *
		 * @param name - 헤더의 이름
		 * @param 값 - 할당된 정수 값
		 * @see #containsHeader
		 * @see #addIntHeader
		 *
		 *
		 *  Access-Control-Allow-Origin : *
		 *
		 */


		res.setHeader("Access-Control-Allow-Origin", "*");
		/** setHeader(name, value)
		 * 주어진 이름과 값으로 응답 헤더를 추가합니다. 이 방법을 사용하면 응답 헤더가 여러 값을 가질 수 있습니다.
		 *
		 * @param name 헤더의 이름
		 * @param 값 추가 헤더 값 옥텟 문자열을 포함하는 경우 RFC 2047에 따라 인코딩해야 합니다.
		 * (http://www.ietf.org/rfc/rfc2047.txt)
		 * @see #setHeader
		 *
		 */


		res.setHeader("Access-Control-Max-Age", "3600");
		// Access-Control-Max-Age : 3600

//		res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, PATCH, HEAD");
		res.setHeader("Access-Control-Allow-Methods", "*");
		res.setHeader("Access-Control-Allow-Headers", "*");
//		res.setHeader("Access-Control-Allow-Headers", "origin, x-requested-with, content-type, multipart, multipart/form-data, accept, token, version, locale");

		log.info("Logging Request  {} : {}", req.getMethod(), req.getRequestURI());

		chain.doFilter(request, response);
		// 3. chaing.doFilter() 요청을 필터링 안하고 다음 Filter에게 넘긴다.
        // 다음 필터에게 requset 및 response 를 넘기고, 그 Filter가 실행된 다음에 다시 돌아와서 밑에줄 코드 실행

		log.info("Logging Response :{}", res.getContentType());
	}


	@Override
	public void destroy() {}
	//필터가 웹 콘테이너에서 삭제될 때 호출


	@Override
	public void init(FilterConfig fc) throws ServletException {}
	//필터를 웹 콘테이너에 생성 후 초기화할 때 호출

}



handler/FrontApiInterCepter.java

package kr.co.test.study.handler;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
public class FrontApiInterceptor extends HandlerInterceptorAdapter {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		/*
		* 컨트롤러(즉 RequestMapping이 선언된 메서드 진입) 실행 직전에 동작.
		* 반환 값이 true일 경우 정상적으로 진행이 되고, false일 경우 실행이 멈춥니다.(컨트롤러 진입을 하지 않음)
		* 전달인자 중 Object handler는 핸들러 매핑이 찾은 컨트롤러 클래스 객체입니다.
		* */



		log.info("FrontInterceptor > preHandle");
		// TODO 사용 token 체크기능 필요?
		if (StringUtils.equals(request.getMethod(), "OPTIONS")) {
			log.debug("if request options method is options, return true");

			return true;
		}
		// 받은 request 에 사용된 HTTP 메서드의 이름이 "OPTIONS"이면 Log 띄움

		/*
		* StringUtils.equlas(parm1, parm2)
		* parm1과 parm2 가 같으면 true 리턴
		* */

		/**
		 * request.getMethod()
		 * 이 요청에 사용된 HTTP 메서드의 이름을 반환합니다(예: GET, POST 또는 PUT). CGI 변수 REQUEST_METHOD의 값과 동일합니다.
		 *
		 * @return a <code>String</code> 이 요청에 사용된 메서드의 이름을 지정합니다.
		 */


		/**
		 * request.getPathInfo()
		 * 클라이언트가 이 요청을 할 때 보낸 URL과 관련된 추가 경로 정보를 반환합니다. 추가 경로 정보는 서블릿 경로를 따르지만 쿼리 문자열 앞에 있으며 "/" 문자로 시작합니다.
		 * <p>
		 * 이 메서드는 추가 경로 정보가 없는 경우 <code>null</code>을 반환합니다.
		 * <p>
		 * CGI 변수 PATH_INFO의 값과 동일합니다.
		 *
		 * @return a <code>String</code>, 웹 컨테이너에 의해 디코딩되며, 요청 URL의 쿼리 문자열 앞에 있지만 서블릿 경로 뒤에 오는 추가 경로 정보를 지정합니다. 또는 URL에 추가 경로 정보가 없는 경우 <code>null</code>
		 */



		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
		log.info("FrontInterceptor > postHandle");
	}
	/*
	* 컨트롤러 진입 후 view가 랜더링 되기 전 수행이 된다.
	* 전달인자의 modelAndView을 통해 화면 단에 들어가는 데이터 등의 조작이 가능하다.
	* */



	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception arg3)
			throws Exception {
		log.info("FrontInterceptor > afterCompletion");
	}
}
/*
* 컨트롤러 진입 후 view가 정상적으로 랜더링 된 후 제일 마지막에 실행이 되는 메서드
* */



api/controller/back/BackBoardController.java

package kr.co.test.study.api.controller.back;

import io.swagger.annotations.*;
import kr.co.test.study.api.model.common.MailAddrVo;
import kr.co.test.study.api.model.common.PaginationVo;
import kr.co.test.study.api.model.common.RspCode;
import kr.co.test.study.api.model.common.SearchVo;
import kr.co.test.study.api.model.study.BoardVo;
import kr.co.test.study.api.model.study.ManagerVo;
import kr.co.test.study.api.service.BoardService;
import kr.co.test.study.api.util.FileUtil;
import kr.co.test.study.api.util.RestApi;
import kr.co.test.study.settings.ProductConstants;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.method.P;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/*
@RestController - 컨트롤러 클래스에 @RestController를 붙이면, 컨트롤러 클래스 하위 메서드에 @ResponseBody 어노테이션을 붙이지 않아도 문자열과 JSON 등을 전송할 수 있다.
@Controller와 달리 @RestController는 컨트롤러 클래스의 각 메서드마다 @ResponseBody를 추가할 필요가 없어졌다.

Spring 4.3부터 Spring MVC 컨트롤러 메소드를 위해 새로운 어노테이션 5개가 추가됨
@RequestMapping(value="/getList", method = { RequestMethod.POST} -> @PostMapping("/getList") 으로 짧게 줄여쓸수 있음
@api - 클래스를 swagger 리소스 대상으로 표시

 */
@RestController
@RequestMapping("/api/back/board")
@Api(tags = "관리자 문의 게시판")
public class BackBoardController {

    @GetMapping("/welcome")
    public String welcome(){
        return "The server is running well -lee hoogy";
    }
}



rest API 서버 만들기

(1). 컨트롤러 클래스 만들기

예제)

package seok.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import seok.model.Todo;

import java.util.concurrent.atomic.AtomicInteger;

@RestController
@RequestMapping(value = "/todo")
public class TodoController {
    private final AtomicInteger counter = new AtomicInteger();

    @RequestMapping("/todo")
    public Todo todo(){
        return new Todo(counter.incrementAndGet(), "코딩하기");
    }

	//AtomicInteger는 Atomic(더 이상 쪼개질 수 없는 성질)을 의미하며, 단순히 Integer 타입으로 선언한다면 서로 다른 Thread 에서 하나의 변수에 대해 값을 쓰거나 읽기 때문에 문제가 발생할 수 있지만, AtomicInteger를 쓰므로 Thread-safe 하게 처리가 가능하다.


	//POST 메서드 생성
	@PostMapping("/todo")
	public Todo registryTodo(@RequestParam(value="todoTitle") String todoTitle){
    	return new Todo(counter.incrementAndGet(), todoTitle);
	}

	//RESPONSE 메서드 생성
	@PostMapping("/todo/response")
	public ResponseEntity<Todo> postRegistryTodo(@RequestParam String todoTitle){
    	return new ResponseEntity<>
		(new Todo(counter.incrementAndGet(), todoTitle), HttpStatus.CREATED);
	}

}


(2). 모델 클래스 만들기

  • 데이터를 담을 수 있는 클래스 (주고받을 자료구조 클래스, 객체)

예제)

package seok.model;

public class Todo {
    private int id;
    private String title;

    public Todo(int id, String title) {
        this.id = id;
        this.title = title;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}




POST맨 사용방법

  • workspace 만든 후 start somting new -> get/post 할수 있는 창 뜸
  • http 메소드 선택후 send -> 응답 확인

  • POST (insert, update) 확인하는 방법은 POST카테고리 선택 -> Body -> raw 체크 -> 카테고리 JSON 선택
{
	"key1" : "value1",
	"key2" : "value2"
}

형식으로 작성후 send

태그: ,

카테고리:

업데이트: