영한킴: spring MVC 팁 및 부연설명

이 포스트는 강의 내용 중 알게 된 것이나 필자에게 필요한 부분을 입력한 내용을 기술했습니다


프로젝트 오픈

  • spring boot 프로젝트를 열 때는 build.gradle을 open 한다

HttpServlet

  • HttpServletRequest, HttpServletResponse는 interfaece 이다. 톰캣이나 제티 등 WAS들은 이 표준 서블릿 스펙을 구현한다. service등 메서드를 통해 구현체를 확인할 수 있다.

http 관련

  • http 헤더에 셋팅

response.setContentType("text/plain")
response.setCharacterEncoding("utf-8")

  • http 메세지 바디에 문자열 셋팅

response.getWriter().write("...")

  • request.getParamter()는 GET/POST 2가지 모두 지원한다
    동명의 파라미터가 복수개일때는 .getParameterValues() 를 사용하면 된다.

Lombok Setting (플러그인에서 설치 후)

  • Lombok Setting (플러그인에서 설치 후)
    ctrl+alt+S (Settings) > Build, Execution, Deployment > Compiler > Annotaion Processors > Enable Annotaion processing 체크

with non-zero …

  • 오류관련: WebServlet에 name 인자가 중복되었을 경우 굉장히 비 직관적은 로그가 뜬다
    finished with non-zero exit value 1
    찾느라 애먹었다.. 구글링으로도, 해외글에서도 찾아볼 수 없었다.. 꼭 검색 뿐만 아니라.. 이쯤에서 잘못되지 않았을까 하고 직관적인 의심도 할 줄 알아야겠다.. 길게 코딩하지 말고 코딩 중간중간 흐름이 끊겨도 결과를 확인하는 습관을 들이자..

캐시된 것 표시

  • 캐시된 것은 개발자도구에서 Status가 회색 글씨로 나온다 !
    image
    다시 새로 고침하면
    정상 표시 된다.
    image
    이렇게 되면서 현재의 갱신된 자원이 보임
    상세하게 보면 아래와 같다.
    image
    image

Forward & Redirect

  • forward: 호출이 서버 내부에서 일어남
    redirect: 클라이언트가 호출하게 함
    forward는 서버 내부에서 이전 request, reponse을 갖고 내부에서 재호출을 한다. 그렇기에 브라우저 url은 그대로 이다 . 이런 이유로 클라이언트는 전혀 인지하지 못한다.
    redirect는 말 그대로 클라이언트가 재호출을 하기 때문에 url이 바뀐다. 새로운 요청이 들어오는 것이므로 이전 request, reponse은 없고 새로 만들어진다.
    클라이언트가 Status 값 302를 보고 Redirect가 일어났단 것을 알 수 있다

코드를 개선할 때는

  • 코드를 개선하다 보면.. 구조나 디테일을 개선하고 싶을때가 만드시 생긴다고 한다
    이때 조급함을 참아야 한다고 한다. 같은 레벨의 것을 먼저 개선 후 그 다음 다른 레벨의 것을 개선한다 예를 들어 구조를 개선할 떄는 디테일을 개선하지 아니한다 구조 개선 후 테스트가 제대로 동작하면 그 다음 디테일을 개선

우연히 보게 된.. Void 클래스

image 신기하다..

BeanNamedUrlHandlerMapping & Adapter

  • 컴포넌트 이름으로 url 등록을 해서 해당 bean을 호출할 수 있다
  @Component("/springmvc/old-controller")
  public class OldController implements Controller {
      @Override
      public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
          System.out.println("OldController.handleRequest");
          return null;
      }
  }
  • HandllerMapping의 우선순위

    • #0 RequestMappingHandlerMapping : 우리가 아는 @RequestMapping
    • #1 BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러 찾기

HandlerAdpater는 생략

뷰 리졸버 셋팅 비교

  • Bean으로 등록
  @Bean
	ViewResolver internalResourceViewResolver() {
		return new InternalResourceViewResolver("/WEB-INF/views/", ".jsp");
	}
  • 부트의 properties 등록
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

강의에서 작성한 view와 InternalResourceView 비교

  • model -> request 로 변환해주는 부분

  • MyView.java

  private void modelToRequestAttribute(Map<String, Object> model, HttpServletRequest request) {
    model.forEach((key, value) -> {
      request.setAttribute(key, value);
    });
  }
  • InternalResourceViewReolver 클래스 > InternalResourceView 클래스 > renderMergedOutputModel메서드 > exposeModelAsRequestAttributes 메서드
protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
		model.forEach((name, value) -> {
			if (value != null) {
				request.setAttribute(name, value);
			}
			else {
				request.removeAttribute(name);
			}
		});
  • 타임리프의 view & reolver 도 별도로 있다

  • JSP는 forward() 로 렌더링이 되고 타임리프는 자체적으로 자바코드로 바로 렌더링된다

@Controller

  • Component 스캔의 대상 (자체적으로 @Component 를 포함)
  • 핸들러 매핑의 대상이 됨
    • @RequestMapping, @Controller가 클래스 레벨에 붙어있어야 RequestMappingHandlerMapping 이 인식해서 url정보로 bean을 인식한다
  • 즉, @Controller = @Component + @RequestMapping

  • RequestMappingHandlerMapping > isHandler
	@Override
	protected boolean isHandler(Class<?> beanType) {
		return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
				AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
	}

해석: 클래스 레벨에 Controller나 RequestMapping이 붙어있으면 RequestMappingHandlerMapping이 인식 가능한 Handler이다

  • 혹은 아래와 같은 방법으로 Controller 등록이 가능하다
@RequestMapping
public class SpringMemberFormControllerV1 { ... }
@ServletComponentScan
@SpringBootApplication
public class ServletApplication {
	public static void main(String[] args) { ... );

	@Bean
	SpringMemberFormControllerV1 springMemberFormControllerV1() {
		return new SpringMemberFormControllerV1();
	}
  ...

ReuestMapping 과 GET, POST

  • @ReuestMapping 은 기본적으로 GET, POST를 둘다 수용한다
    • 무언가 하나만으로 타겟하고 싶다면 method 인자를 추가하면 된다
@RequestMapping(value = "new-form", method = RequestMethod.GET)

아래 POST 요청을 않음을 알 수 있다 image

  • 이젠 이것마저도.. @GetMapping, @PostMapping으로 대체 가능

War & Jar

  • War를 사용할 때는
    • JSP가 포함될떄
    • 부트의 내장 톰캣이 아닌 별도의 톰캣을 외부에 두고 배포할 떄
  • Jar이어도 될 떄는
    • JSP가 없을때
    • 부트의 내장 톰캣을 이용할 때
    • 최근에는 주로 이 방식 !

캐시를 사용하지 않을 때는

  • Cache-Control : no-store
    • https://www.inflearn.com/questions/112647
    • https://stackoverflow.com/questions/49547/how-do-we-control-web-page-caching-across-all-browsers




© 2020.12. by 따라쟁이

Powered by philz