2022-04-05(화)

인터셉터

인터셉터
필터 기능을 수행 ← 기능의 삽입, 삭제가 쉽다
페이지 컨트롤러의 request handler 실행 전후에 인터셉터가 개입

요청 -> Spring Boot -> 인터셉터 ->

사용자 인증, 권한 검사, 파라미터값 검증, 압축해제, 암호해제, 로그 출력

클라이언트가 데이터를 보냈으면 압축 해제 작업이라든가

리턴값 압축, 리턴값을 Client가 요구하는 방식으로 인코딩, 리턴값을 암호화 등

인터셉터 활용

<<인터셉터>> 로그인 여부 검사

add(), update(), delete() -> BoardHandler

<<Front Controller>> DispatcherServlet -> 인터셉터
규칙에 따라 call 한다

afterCompletion 뷰 리졸버 개념을 배우기 전까지는

전처리
후처리

preHandle()
postHandle()

MessageConverter ← 리턴된 자바 객체를 JSON 문자열로 바꿔준다
(jackson의 ObjectMapper를 쓴다)

Deprecated

Interceptor 만들기

<<Interface>> HandlerInterceptor
preHandle()
postHandle()
afterCompletion()

인터페이스 3개 메서드 중에서 관심 있는 건 preHandle() 1개인데 나머지 메서드들도 빈 메서드라도 구현해야 됨

<<abstract>> HandlerInterceptorAdapter
인터페이스 메서드를 미리 구현함
단, 구현 코드는 없음
상속받는 쪽에서 관심 있는 메서드만 오버라이딩 하면 됨!

<<concrete>> MyInterceptor
관심 있는 메서드만 오버라이딩 하면 된다.

Interceptor 만들기 - default 문법 등장

default 메서드로 선언하면 미리 메서드를 구현할 수 있다.
→ Adaptor 클래스의 효용성이 사라짐
→ deprecated로 처리됨

스프링 버전에 따라 달라짐
2015년 전에 구축한 프로젝트는 HandlerInterceptorAdapter를 사용
신규 프로젝트는 HandlerInterceptor 사용

package com.eomcs.mylist.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

// 사용자 인증 여부를 검사하는 인터셉터 
public class AuthInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    System.out.println("preHandle() 호출됨!");
    return HandlerInterceptor.super.preHandle(request, response, handler);
  }

  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      ModelAndView modelAndView) throws Exception {
    System.out.println("postHandle() 호출됨!");
    HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
  }
}

2단계 - 스프링부트에 인터셉터를 등록한다.

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-config-enable

package com.eomcs.mylist.conf;

import org.springframework.context.annotation.Configuration;

@Configuration 
// 다음 클래스는 설정에 관련된 일을 하는 클래스임을 선언한다.
// 스프링 부트는 이 애노테이션이 붙은 클래스에 대해 관련 메서드를 호출하여 내부 설정에 반영한다.
public class MvcConfiguration {

}

스프링 부트는 이 애노테이션이 붙은 클래스에 대해
관련 메서드를 호출하여 내부 설정에 반영한다.

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-config-interceptors

인터셉터를 언제 넣을 거냐

@Configuration 
// 다음 클래스는 설정에 관련된 일을 하는 클래스임을 선언한다.
// 스프링 부트는 이 애노테이션이 붙은 클래스에 대해 관련 메서드를 호출하여 내부 설정에 반영한다.
public class MvcConfiguration implements WebMvcConfigurer {
  // WebMvcConfigurer 인터페이스
  // => 이 규칙에 따라 메서드를 작성하면 그 메서드가 의도한 대로
  // 스프링 부트는 해당 메서드를 호출하여 그 메서드가 요구하는 대로 설정한다.

  // 인터셉터를 추가하고 싶다면 다음 메서드를 규칙에 따라 정의하라!
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    System.out.println("MvcConfiguration.addInterceptors() 호출됨!");
    // 이 메서드가 정의되어 있다면 스프링 부트는 이 메서드를 호출하여
    // 추가할 인터셉터의 정보를 InterceptorRegistry로 받는다.
    registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/**");
  }
}

@Configuration 애노테이션 붙어서 호출되는 거

규칙에 따라 만들면 규칙에 따라서 설정을 수행한다

@Component ← 스프링이 관리해야 될 대상

애노테이션으로 하는 게 아니라 명시적으로 생성

  @RequestMapping("/board/list")
  public Object list() {
    return new ResultMap().setStatus(SUCCESS).setData(boardService.list());
  }

응답 데이터는 규칙이 명확해야 한다

  fetch("/board/list")
    .then(function(response) {
      return response.json();
    })
    .then(function(result) {
    	if (result.status == "fail") {
    		window.alert("서버 요청 오류!");
    		console.log(result.data);
    		return;
    	}
      for (var board of result.data) {
        var tr = document.createElement("tr");
        tr.innerHTML = `<td>${board.no}</td>
        <td><a href="?content=/board/view.html&no=${board.no}">${board.title}</a></td>
        <td>${board.writer.name}</td>
        <td>${board.viewCount}</td>
        <td>${board.createdDate}</td>`;
        tbody.appendChild(tr);
      }
    });

result.data ← 성공했으면 list가 들어 있고 실패했으면 실패 이유가 들어있다

  // 3) 서버에서 데이터 가져오기
  fetch(`/board/get?no=${no}`)
    .then(function(response) {
      return response.json();
    })
    .then(function(result) {
      // 4) 연락처 상세 정보를 화면에 출력한다.
      if (result.status == "fail") {
    	  window.alert("서버 요청 오류!");
    	  console.log(result.data);
    	  return;
      }
      
      var board =result.data;
      
      xNo.value = board.no;
      xTitle.value = board.title;
      xContent.value = board.content;
      xWriter.innerHTML = board.writer.name;
      xViewCount.innerHTML = board.viewCount;
      xCreatedDate.innerHTML = board.createdDate;
    });

http://localhost:8080/board/get?no=14

http://localhost:8080/board/get?no=200

자바스크립트 객체로 바꿀 때까지 기다리면 안 되니까 비동기로 처리됨
리턴값을 기다리게 되면 다른 작업을 못하는 락이 걸림
then 이라는 메서드

로그인 한 상태에서는 나오는데

빈 문자열은 못 바꿈

JSON 문자열 -> 자바스크립트 객체

문자열 자체가 빈 문자열이면 자바스크립트 객체로 못 바꿈

JSON 형식의 문자열이 아니야! 에러남

ResultMap 객체를 JSON 문자열로 바꿔줘야 됨
인터셉트는 자동으로 안 바꿔주기 때문에 수동으로 바꿔줘야 됨

jackson

https://velog.io/@banana/2022-01-24월-11주차-1일

영어로 못 바꾸면 물음표로 뜸

response.setContentType("application/json;charset=UTF-8");

자바 18버전은 내부적으로

이제 한글 안 깨짐

window.alert(result.data);
window 생략 가능

    // 로그인 여부 검사
    HttpSession session = request.getSession();
    Member loginUser = (Member) session.getAttribute("loginUser");
    if  (loginUser == null) {
      // 로그인을 하지 않았으면 오류 메시지를 JSON 형식으로 직접 응답한다.
      ObjectMapper jsonConverter = new ObjectMapper(); 
      String json = jsonConverter.writeValueAsString(new ResultMap()
          .setStatus(ResultMap.FAIL)
          .setData("로그인 하지 않았습니다."));
      response.setContentType("application/json;charset=UTF-8");
      PrintWriter out = response.getWriter();
      out.write(json);
    // 로그인 여부 검사
    HttpSession session = request.getSession();
    Member loginUser = (Member) session.getAttribute("loginUser");
    if  (loginUser == null) {
      // 로그인을 하지 않았으면 오류 메시지를 JSON 형식으로 직접 응답한다.
      response.setContentType("application/json;charset=UTF-8");
      response.getWriter().write(new ObjectMapper().writeValueAsString(new ResultMap()
          .setStatus(ResultMap.FAIL)
          .setData("로그인 하지 않았습니다.")));

      return false; // 페이지 컨트롤러를 실행하지 말고 즉시 응답하라!
    }

저 부분 지우기

좋은 웹페이지 즐겨찾기