Home

0

Spring Boot 응답 - 정적 리소스, 뷰 템플릿

목차 Spring MVC - ArgumentResolver Spring MVC - HttpMessageConverter Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력 Spring Boot 응답 - 정적 리소스, 뷰 템플릿 Spring Boot 요청 메시지 - JSON Spring Boot 요청 메시지 - Text Spring Boot 쿼리 파라미터, HTML Form Spring Boot 기본 헤더 조회 Spring Boot API 예시 Spring Boot @RequestMapping Spring Boot Logging Spring Boot 응답 - 정적 리소스, 뷰 템플릿@RequestMapping("/response-view-v1")public ModelAndView responseViewV1(){ ModelAndView mav = new ModelAndView("response/hello") .addObject("data", "hello"); return mav;} String을 반환하는 경우뷰 리졸버를 통해 반환되는 문자열에 해당되는 뷰를 찾아 렌더링 해준다. @RequestMapping("/response-view-v2")public String responseViewV2(Model model){ model.addAttribute("data", "hello!"); return "response/hello";} void를 반환하는 경우@RequestMapping("/response/hello")public void responseViewV3(Model model){ model.addAttribute("data", "hello!");}

0

Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력

목차 Spring MVC - ArgumentResolver Spring MVC - HttpMessageConverter Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력 Spring Boot 응답 - 정적 리소스, 뷰 템플릿 Spring Boot 요청 메시지 - JSON Spring Boot 요청 메시지 - Text Spring Boot 쿼리 파라미터, HTML Form Spring Boot 기본 헤더 조회 Spring Boot API 예시 Spring Boot @RequestMapping Spring Boot Logging Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력@GetMapping("/response-body-string-v1")public void responseBodyV1(HttpServletResponse response) throws IOException { response.getWriter().write("ok");} @GetMapping("/response-body-string-v2")public ResponseEntity<String> responseBodyV2(HttpServletResponse response) { return new ResponseEntity<>("ok", HttpStatus.OK);} @ResponseBody@GetMapping("/response-body-string-v3")public String responseBodyV3(HttpServletResponse response) { return "ok";} @GetMapping("/response-body-json-v1")public ResponseEntity<HelloData> responseBodyJsonV1() { HelloData helloData = new HelloData(); helloData.setUsername("userA"); helloData.setAge(20); return new ResponseEntity<>(helloData, HttpStatus.OK);} @ResponseBody@ResponseStatus(HttpStatus.OK)@GetMapping("/response-body-json-v1")public HelloData responseBodyJsonV2() { HelloData helloData = new HelloData(); helloData.setUsername("userA"); helloData.setAge(20); return helloData;}

0

Spring MVC - HttpMessageConverter

목차 Spring MVC - ArgumentResolver Spring MVC - HttpMessageConverter Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력 Spring Boot 응답 - 정적 리소스, 뷰 템플릿 Spring Boot 요청 메시지 - JSON Spring Boot 요청 메시지 - Text Spring Boot 쿼리 파라미터, HTML Form Spring Boot 기본 헤더 조회 Spring Boot API 예시 Spring Boot @RequestMapping Spring Boot Logging Spring MVC - HttpMessageConverterHttpMessageConverter 는 HTTP 요청, 응답 둘다 사용된다. canRead, canWrite : 메시지 컨버터가 해당 클래스, 미디어 타입을 지원하는지 확인한다. read, write : 메시지 컨버터를 통해 메시지르 읽고 쓰는 기능 public interface HttpMessageConverter<T> { boolean canRead(Class<?> clazz, @Nullable MediaType mediaType); boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType); List<MediaType> getSupportedMediaTypes(); default List<MediaType> getSupportedMediaTypes(Class<?> clazz) { return (canRead(clazz, null) || canWrite(clazz, null) ? getSupportedMediaTypes() : Collections.emptyList()); } T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;} 스프링 부트 기본 메시지 컨버터 ByteArrayHttpMessageConverter StringHttpMessageConverter MappingJackson2HttpMessageConverter 스프링 부트는 다양한 메시지 컨버터를 제공하는데, 대상 클래스 타입과 미디어 타입 둘을 체크해 사용여부를 결정한다. 만약 해당되지 않으면 다음 메시지 컨버터로 넘어간다. ByteArrayHttpMessageConverter

0

Spring Boot RequestMappingHandlerAdapter

목차 Spring MVC - ArgumentResolver Spring MVC - HttpMessageConverter Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력 Spring Boot 응답 - 정적 리소스, 뷰 템플릿 Spring Boot 요청 메시지 - JSON Spring Boot 요청 메시지 - Text Spring Boot 쿼리 파라미터, HTML Form Spring Boot 기본 헤더 조회 Spring Boot API 예시 Spring Boot @RequestMapping Spring Boot Logging public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean { private static final boolean shouldIgnoreXml = SpringProperties.getFlag("spring.xml.ignore"); public static final MethodFilter INIT_BINDER_METHODS = (method) -> { return AnnotatedElementUtils.hasAnnotation(method, InitBinder.class); }; public static final MethodFilter MODEL_ATTRIBUTE_METHODS = (method) -> { return !AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) && AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class); }; @Nullable private List<HandlerMethodArgumentResolver> customArgumentResolvers; @Nullable private HandlerMethodArgumentResolverComposite argumentResolvers; @Nullable private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers; @Nullable private List<HandlerMethodReturnValueHandler> customReturnValueHandlers; @Nullable private HandlerMethodReturnValueHandlerComposite returnValueHandlers; @Nullable private List<ModelAndViewResolver> modelAndViewResolvers; private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager(); private List<HttpMessageConverter<?>> messageConverters = new ArrayList(4); private final List<Object> requestResponseBodyAdvice = new ArrayList(); @Nullable private WebBindingInitializer webBindingInitializer; private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync"); @Nullable private Long asyncRequestTimeout; private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0]; private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0]; private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); private boolean ignoreDefaultModelOnRedirect = false; private int cacheSecondsForSessionAttributeHandlers = 0; private boolean synchronizeOnSession = false; private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); @Nullable private ConfigurableBeanFactory beanFactory; private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap(64); private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap(64); private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap(); private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap(64); private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap(); public RequestMappingHandlerAdapter() { this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(new StringHttpMessageConverter()); if (!shouldIgnoreXml) { try { this.messageConverters.add(new SourceHttpMessageConverter()); } catch (Error var2) { } } this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); } public void setCustomArgumentResolvers(@Nullable List<HandlerMethodArgumentResolver> argumentResolvers) { this.customArgumentResolvers = argumentResolvers; } @Nullable public List<HandlerMethodArgumentResolver> getCustomArgumentResolvers() { return this.customArgumentResolvers; } public void setArgumentResolvers(@Nullable List<HandlerMethodArgumentResolver> argumentResolvers) { if (argumentResolvers == null) { this.argumentResolvers = null; } else { this.argumentResolvers = new HandlerMethodArgumentResolverComposite(); this.argumentResolvers.addResolvers(argumentResolvers); } } @Nullable public List<HandlerMethodArgumentResolver> getArgumentResolvers() { return this.argumentResolvers != null ? this.argumentResolvers.getResolvers() : null; } public void setInitBinderArgumentResolvers(@Nullable List<HandlerMethodArgumentResolver> argumentResolvers) { if (argumentResolvers == null) { this.initBinderArgumentResolvers = null; } else { this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite(); this.initBinderArgumentResolvers.addResolvers(argumentResolvers); } } @Nullable public List<HandlerMethodArgumentResolver> getInitBinderArgumentResolvers() { return this.initBinderArgumentResolvers != null ? this.initBinderArgumentResolvers.getResolvers() : null; } public void setCustomReturnValueHandlers(@Nullable List<HandlerMethodReturnValueHandler> returnValueHandlers) { this.customReturnValueHandlers = returnValueHandlers; } @Nullable public List<HandlerMethodReturnValueHandler> getCustomReturnValueHandlers() { return this.customReturnValueHandlers; } public void setReturnValueHandlers(@Nullable List<HandlerMethodReturnValueHandler> returnValueHandlers) { if (returnValueHandlers == null) { this.returnValueHandlers = null; } else { this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite(); this.returnValueHandlers.addHandlers(returnValueHandlers); } } @Nullable public List<HandlerMethodReturnValueHandler> getReturnValueHandlers() { return this.returnValueHandlers != null ? this.returnValueHandlers.getHandlers() : null; } public void setModelAndViewResolvers(@Nullable List<ModelAndViewResolver> modelAndViewResolvers) { this.modelAndViewResolvers = modelAndViewResolvers; } @Nullable public List<ModelAndViewResolver> getModelAndViewResolvers() { return this.modelAndViewResolvers; } public void setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager) { this.contentNegotiationManager = contentNegotiationManager; } public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) { this.messageConverters = messageConverters; } public List<HttpMessageConverter<?>> getMessageConverters() { return this.messageConverters; } public void setRequestBodyAdvice(@Nullable List<RequestBodyAdvice> requestBodyAdvice) { if (requestBodyAdvice != null) { this.requestResponseBodyAdvice.addAll(requestBodyAdvice); } } public void setResponseBodyAdvice(@Nullable List<ResponseBodyAdvice<?>> responseBodyAdvice) { if (responseBodyAdvice != null) { this.requestResponseBodyAdvice.addAll(responseBodyAdvice); } } public void setWebBindingInitializer(@Nullable WebBindingInitializer webBindingInitializer) { this.webBindingInitializer = webBindingInitializer; } @Nullable public WebBindingInitializer getWebBindingInitializer() { return this.webBindingInitializer; } public void setTaskExecutor(AsyncTaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } public void setAsyncRequestTimeout(long timeout) { this.asyncRequestTimeout = timeout; } public void setCallableInterceptors(List<CallableProcessingInterceptor> interceptors) { this.callableInterceptors = (CallableProcessingInterceptor[])interceptors.toArray(new CallableProcessingInterceptor[0]); } public void setDeferredResultInterceptors(List<DeferredResultProcessingInterceptor> interceptors) { this.deferredResultInterceptors = (DeferredResultProcessingInterceptor[])interceptors.toArray(new DeferredResultProcessingInterceptor[0]); } public void setReactiveAdapterRegistry(ReactiveAdapterRegistry reactiveAdapterRegistry) { this.reactiveAdapterRegistry = reactiveAdapterRegistry; } public ReactiveAdapterRegistry getReactiveAdapterRegistry() { return this.reactiveAdapterRegistry; } public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect) { this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect; } public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) { this.sessionAttributeStore = sessionAttributeStore; } public void setCacheSecondsForSessionAttributeHandlers(int cacheSecondsForSessionAttributeHandlers) { this.cacheSecondsForSessionAttributeHandlers = cacheSecondsForSessionAttributeHandlers; } public void setSynchronizeOnSession(boolean synchronizeOnSession) { this.synchronizeOnSession = synchronizeOnSession; } public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) { this.parameterNameDiscoverer = parameterNameDiscoverer; } public void setBeanFactory(BeanFactory beanFactory) { if (beanFactory instanceof ConfigurableBeanFactory) { this.beanFactory = (ConfigurableBeanFactory)beanFactory; } } @Nullable protected ConfigurableBeanFactory getBeanFactory() { return this.beanFactory; } public void afterPropertiesSet() { this.initControllerAdviceCache(); List handlers; if (this.argumentResolvers == null) { handlers = this.getDefaultArgumentResolvers(); this.argumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers); } if (this.initBinderArgumentResolvers == null) { handlers = this.getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers); } if (this.returnValueHandlers == null) { handlers = this.getDefaultReturnValueHandlers(); this.returnValueHandlers = (new HandlerMethodReturnValueHandlerComposite()).addHandlers(handlers); } } private void initControllerAdviceCache() { if (this.getApplicationContext() != null) { List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(this.getApplicationContext()); List<Object> requestResponseBodyAdviceBeans = new ArrayList(); Iterator var3 = adviceBeans.iterator(); while(var3.hasNext()) { ControllerAdviceBean adviceBean = (ControllerAdviceBean)var3.next(); Class<?> beanType = adviceBean.getBeanType(); if (beanType == null) { throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean); } Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS); if (!attrMethods.isEmpty()) { this.modelAttributeAdviceCache.put(adviceBean, attrMethods); } Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS); if (!binderMethods.isEmpty()) { this.initBinderAdviceCache.put(adviceBean, binderMethods); } if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) { requestResponseBodyAdviceBeans.add(adviceBean); } } if (!requestResponseBodyAdviceBeans.isEmpty()) { this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans); } if (this.logger.isDebugEnabled()) { int modelSize = this.modelAttributeAdviceCache.size(); int binderSize = this.initBinderAdviceCache.size(); int reqCount = this.getBodyAdviceCount(RequestBodyAdvice.class); int resCount = this.getBodyAdviceCount(ResponseBodyAdvice.class); if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) { this.logger.debug("ControllerAdvice beans: none"); } else { this.logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize + " @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice"); } } } } private int getBodyAdviceCount(Class<?> adviceType) { List<Object> advice = this.requestResponseBodyAdvice; return RequestBodyAdvice.class.isAssignableFrom(adviceType) ? RequestResponseBodyAdviceChain.getAdviceByType(advice, RequestBodyAdvice.class).size() : RequestResponseBodyAdviceChain.getAdviceByType(advice, ResponseBodyAdvice.class).size(); } private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() { List<HandlerMethodArgumentResolver> resolvers = new ArrayList(30); resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), false)); resolvers.add(new RequestParamMapMethodArgumentResolver()); resolvers.add(new PathVariableMethodArgumentResolver()); resolvers.add(new PathVariableMapMethodArgumentResolver()); resolvers.add(new MatrixVariableMethodArgumentResolver()); resolvers.add(new MatrixVariableMapMethodArgumentResolver()); resolvers.add(new ServletModelAttributeMethodProcessor(false)); resolvers.add(new RequestResponseBodyMethodProcessor(this.getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestPartMethodArgumentResolver(this.getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestHeaderMethodArgumentResolver(this.getBeanFactory())); resolvers.add(new RequestHeaderMapMethodArgumentResolver()); resolvers.add(new ServletCookieValueMethodArgumentResolver(this.getBeanFactory())); resolvers.add(new ExpressionValueMethodArgumentResolver(this.getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver()); resolvers.add(new RequestAttributeMethodArgumentResolver()); resolvers.add(new ServletRequestMethodArgumentResolver()); resolvers.add(new ServletResponseMethodArgumentResolver()); resolvers.add(new HttpEntityMethodProcessor(this.getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RedirectAttributesMethodArgumentResolver()); resolvers.add(new ModelMethodProcessor()); resolvers.add(new MapMethodProcessor()); resolvers.add(new ErrorsMethodArgumentResolver()); resolvers.add(new SessionStatusMethodArgumentResolver()); resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); if (KotlinDetector.isKotlinPresent()) { resolvers.add(new ContinuationHandlerMethodArgumentResolver()); } if (this.getCustomArgumentResolvers() != null) { resolvers.addAll(this.getCustomArgumentResolvers()); } resolvers.add(new PrincipalMethodArgumentResolver()); resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), true)); resolvers.add(new ServletModelAttributeMethodProcessor(true)); return resolvers; } private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() { List<HandlerMethodArgumentResolver> resolvers = new ArrayList(20); resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), false)); resolvers.add(new RequestParamMapMethodArgumentResolver()); resolvers.add(new PathVariableMethodArgumentResolver()); resolvers.add(new PathVariableMapMethodArgumentResolver()); resolvers.add(new MatrixVariableMethodArgumentResolver()); resolvers.add(new MatrixVariableMapMethodArgumentResolver()); resolvers.add(new ExpressionValueMethodArgumentResolver(this.getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver()); resolvers.add(new RequestAttributeMethodArgumentResolver()); resolvers.add(new ServletRequestMethodArgumentResolver()); resolvers.add(new ServletResponseMethodArgumentResolver()); if (this.getCustomArgumentResolvers() != null) { resolvers.addAll(this.getCustomArgumentResolvers()); } resolvers.add(new PrincipalMethodArgumentResolver()); resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), true)); return resolvers; } private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() { List<HandlerMethodReturnValueHandler> handlers = new ArrayList(20); handlers.add(new ModelAndViewMethodReturnValueHandler()); handlers.add(new ModelMethodProcessor()); handlers.add(new ViewMethodReturnValueHandler()); handlers.add(new ResponseBodyEmitterReturnValueHandler(this.getMessageConverters(), this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager)); handlers.add(new StreamingResponseBodyReturnValueHandler()); handlers.add(new HttpEntityMethodProcessor(this.getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice)); handlers.add(new HttpHeadersReturnValueHandler()); handlers.add(new CallableMethodReturnValueHandler()); handlers.add(new DeferredResultMethodReturnValueHandler()); handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory)); handlers.add(new ServletModelAttributeMethodProcessor(false)); handlers.add(new RequestResponseBodyMethodProcessor(this.getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice)); handlers.add(new ViewNameMethodReturnValueHandler()); handlers.add(new MapMethodProcessor()); if (this.getCustomReturnValueHandlers() != null) { handlers.addAll(this.getCustomReturnValueHandlers()); } if (!CollectionUtils.isEmpty(this.getModelAndViewResolvers())) { handlers.add(new ModelAndViewResolverMethodReturnValueHandler(this.getModelAndViewResolvers())); } else { handlers.add(new ServletModelAttributeMethodProcessor(true)); } return handlers; } protected boolean supportsInternal(HandlerMethod handlerMethod) { return true; } protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { this.checkRequest(request); ModelAndView mav; if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized(mutex) { mav = this.invokeHandlerMethod(request, response, handlerMethod); } } else { mav = this.invokeHandlerMethod(request, response, handlerMethod); } } else { mav = this.invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader("Cache-Control")) { if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { this.prepareResponse(response); } } return mav; } protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) { return -1L; } private SessionAttributesHandler getSessionAttributesHandler(HandlerMethod handlerMethod) { return (SessionAttributesHandler)this.sessionAttributesHandlerCache.computeIfAbsent(handlerMethod.getBeanType(), (type) -> { return new SessionAttributesHandler(type, this.sessionAttributeStore); }); } @Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); Object result; try { WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod); ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod); if (this.argumentResolvers != null) { invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } if (this.returnValueHandlers != null) { invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) { result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); LogFormatUtils.traceDebug(this.logger, (traceOn) -> { String formatted = LogFormatUtils.formatValue(result, !traceOn); return "Resume with async result [" + formatted + "]"; }); invocableMethod = invocableMethod.wrapConcurrentResult(result); } invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]); if (!asyncManager.isConcurrentHandlingStarted()) { ModelAndView var15 = this.getModelAndView(mavContainer, modelFactory, webRequest); return var15; } result = null; } finally { webRequest.requestCompleted(); } return (ModelAndView)result; } protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) { return new ServletInvocableHandlerMethod(handlerMethod); } private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) { SessionAttributesHandler sessionAttrHandler = this.getSessionAttributesHandler(handlerMethod); Class<?> handlerType = handlerMethod.getBeanType(); Set<Method> methods = (Set)this.modelAttributeCache.get(handlerType); if (methods == null) { methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS); this.modelAttributeCache.put(handlerType, methods); } List<InvocableHandlerMethod> attrMethods = new ArrayList(); this.modelAttributeAdviceCache.forEach((controllerAdviceBean, methodSet) -> { if (controllerAdviceBean.isApplicableToBeanType(handlerType)) { Object bean = controllerAdviceBean.resolveBean(); Iterator var7 = methodSet.iterator(); while(var7.hasNext()) { Method method = (Method)var7.next(); attrMethods.add(this.createModelAttributeMethod(binderFactory, bean, method)); } } }); Iterator var7 = methods.iterator(); while(var7.hasNext()) { Method method = (Method)var7.next(); Object bean = handlerMethod.getBean(); attrMethods.add(this.createModelAttributeMethod(binderFactory, bean, method)); } return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler); } private InvocableHandlerMethod createModelAttributeMethod(WebDataBinderFactory factory, Object bean, Method method) { InvocableHandlerMethod attrMethod = new InvocableHandlerMethod(bean, method); if (this.argumentResolvers != null) { attrMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } attrMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); attrMethod.setDataBinderFactory(factory); return attrMethod; } private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception { Class<?> handlerType = handlerMethod.getBeanType(); Set<Method> methods = (Set)this.initBinderCache.get(handlerType); if (methods == null) { methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS); this.initBinderCache.put(handlerType, methods); } List<InvocableHandlerMethod> initBinderMethods = new ArrayList(); this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> { if (controllerAdviceBean.isApplicableToBeanType(handlerType)) { Object bean = controllerAdviceBean.resolveBean(); Iterator var6 = methodSet.iterator(); while(var6.hasNext()) { Method method = (Method)var6.next(); initBinderMethods.add(this.createInitBinderMethod(bean, method)); } } }); Iterator var5 = methods.iterator(); while(var5.hasNext()) { Method method = (Method)var5.next(); Object bean = handlerMethod.getBean(); initBinderMethods.add(this.createInitBinderMethod(bean, method)); } return this.createDataBinderFactory(initBinderMethods); } private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) { InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method); if (this.initBinderArgumentResolvers != null) { binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers); } binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer)); binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); return binderMethod; } protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods) throws Exception { return new ServletRequestDataBinderFactory(binderMethods, this.getWebBindingInitializer()); } @Nullable private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { modelFactory.updateModel(webRequest, mavContainer); if (mavContainer.isRequestHandled()) { return null; } else { ModelMap model = mavContainer.getModel(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (!mavContainer.isViewReference()) { mav.setView((View)mavContainer.getView()); } if (model instanceof RedirectAttributes) { Map<String, ?> flashAttributes = ((RedirectAttributes)model).getFlashAttributes(); HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(HttpServletRequest.class); if (request != null) { RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } } return mav; } }}

0

Spring Boot ReturnValueHandler

목차 Spring MVC - ArgumentResolver Spring MVC - HttpMessageConverter Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력 Spring Boot 응답 - 정적 리소스, 뷰 템플릿 Spring Boot 요청 메시지 - JSON Spring Boot 요청 메시지 - Text Spring Boot 쿼리 파라미터, HTML Form Spring Boot 기본 헤더 조회 Spring Boot API 예시 Spring Boot @RequestMapping Spring Boot Logging Spring Boot ReturnValueHandlerpublic interface HandlerMethodReturnValueHandler { boolean supportsReturnType(MethodParameter returnType); void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;}

0

Spring MVC Request Life Cycle - Filter

목차 Spring MVC - ArgumentResolver Spring MVC Request Life Cycle - ViewResolver Spring MVC Request Life Cycle - HandlerAdapter Spring MVC Request Life Cycle - HandlerMapping Spring MVC Request Life Cycle - DispatcherServlet Spring MVC Request Life Cycle - Interceptor Spring MVC Request Life Cycle - Filter Filter Filter는 Spring Context 이전에 실행되기 때문에 Spring자체와는 무관하며 Web Application에 등록이 된다. 요청이 DispatcherServlet에 도착하기 전에 처리를 하거나 요청이 끝나고 응답할 때 마지막으로 처리를 하는 역할을 한다. 주로 인코딩, 요청에 대한 인증, 권한 체크 와 같은 요청에 대한 전역적인 처리를 할 때 사용한다. Filter 인터페이스 init 필터 인스턴스 초기화 doFilter 실제 로직 처리(Filter Chain을 따라 다을 Filter로 움직인다.) destroy 필터 인스턴스 종료 public interface Filter { public default void init(FilterConfig filterConfig) throws ServletException {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; public default void destroy() {}} Filter Chain Filter는 Client와 Servlet사이에 존재해 Client가 보내는 요청정보를 가공해 Servlet으로 보내고 Servelt이 보내는 응답정보를 가공해 Client에게 전달하는 역할을 한다. Filter는 일반적인 경우 1개가 존재하지만 여러개의 필터를 모아 Filter Chain을 형성할 수 있다.

0

Spring Boot 요청 메시지 - JSON

목차 Spring MVC - ArgumentResolver Spring MVC - HttpMessageConverter Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력 Spring Boot 응답 - 정적 리소스, 뷰 템플릿 Spring Boot 요청 메시지 - JSON Spring Boot 요청 메시지 - Text Spring Boot 쿼리 파라미터, HTML Form Spring Boot 기본 헤더 조회 Spring Boot API 예시 Spring Boot @RequestMapping Spring Boot Logging Spring Boot 요청 메시지 - JSON@PostMapping("/request-body-json-v1")public void requestBodyJsonV1(HttpServletRequest request, HttpServletResponse response) throws IOException { ServletInputStream inputStream = request.getInputStream(); String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); log.info("messageBody={}", messageBody); HelloData helloData = objectMapper.readValue(messageBody, HelloData.class); log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); response.getWriter().write("ok");} RequestBody 어노테이션 사용하기RequestParam 어노테이션과 다르게 RequestBody 어노테이션은 생략하면 안된다. @ResponseBody@PostMapping("/request-body-json-v2")public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException { log.info("messageBody={}", messageBody); HelloData helloData = objectMapper.readValue(messageBody, HelloData.class); log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); return "ok";} DTO 사용하기@ResponseBody@PostMapping("/request-body-json-v3")public String requestBodyJsonV3(@RequestBody HelloData helloData) throws IOException { log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); return "ok";} @ResponseBody@PostMapping("/request-body-json-v4")public String requestBodyJsonV4(HttpEntity<HelloData> data) throws IOException { HelloData body = data.getBody(); log.info("username={}, age={}", body.getUsername(), body.getAge()); return "ok";}

0

Spring Boot 요청 메시지 - Text

목차 Spring MVC - ArgumentResolver Spring MVC - HttpMessageConverter Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력 Spring Boot 응답 - 정적 리소스, 뷰 템플릿 Spring Boot 요청 메시지 - JSON Spring Boot 요청 메시지 - Text Spring Boot 쿼리 파라미터, HTML Form Spring Boot 기본 헤더 조회 Spring Boot API 예시 Spring Boot @RequestMapping Spring Boot Logging Spring Boot 요청 메시지@PostMapping("/request-body-string-v1")public void requestBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException { ServletInputStream inputStream = request.getInputStream(); String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); log.info("messageBody = {}", messageBody); response.getWriter().write("ok");} @PostMapping("/request-body-string-v2")public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) throws IOException { String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); log.info("messageBody = {}", messageBody); responseWriter.write("ok");} HttpEntity 사용하기@PostMapping("/request-body-string-v3")public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) throws IOException { String messageBody = httpEntity.getBody(); log.info("messageBody = {}", messageBody); return new HttpEntity<>("ok");} RequestBody, ResponseBody 어노테이션 사용하기@ResponseBody@PostMapping("/request-body-string-v4")public String requestBodyStringV4(@RequestBody String messageBody) throws IOException { log.info("messageBody = {}", messageBody); return "ok";}

0

Spring Boot Logging

목차 Spring MVC - ArgumentResolver Spring MVC - HttpMessageConverter Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력 Spring Boot 응답 - 정적 리소스, 뷰 템플릿 Spring Boot 요청 메시지 - JSON Spring Boot 요청 메시지 - Text Spring Boot 쿼리 파라미터, HTML Form Spring Boot 기본 헤더 조회 Spring Boot API 예시 Spring Boot @RequestMapping Spring Boot Logging Spring Boot Logging로그 선언 방법 private final Logger log = LoggerFactory.getLogger(getClass()); private static final Logger log = LoggerFactory.getLogger(xxx.class); @slf4j // Lombok에서 제공하는 Log 기능 사용 log.trace("info log = {}", name);log.debug("info log = {}", name);log.info("info log = {}", name);log.warn("info log = {}", name);log.error("info log = {}", name); logging.level.com.example.springmvc=trace @Slf4j@RestControllerpublic class LogTestController {// private final Logger log = LoggerFactory.getLogger(getClass()); @RequestMapping("/log-test") public String logTest(){ String name = "Spring"; System.out.println("name = " + name); log.trace("info log = {}", name); log.debug("info log = {}", name); log.info("info log = {}", name); log.warn("info log = {}", name); log.error("info log = {}", name); return "ok"; }}

0

Spring Boot API 예시

목차 Spring MVC - ArgumentResolver Spring MVC - HttpMessageConverter Spring Boot Http 응답 - HTTP API, Message Body에 직접 입력 Spring Boot 응답 - 정적 리소스, 뷰 템플릿 Spring Boot 요청 메시지 - JSON Spring Boot 요청 메시지 - Text Spring Boot 쿼리 파라미터, HTML Form Spring Boot 기본 헤더 조회 Spring Boot API 예시 Spring Boot @RequestMapping Spring Boot Logging Spring Boot API 예시@RestController@RequestMapping("/mapping/users")public class MappingClassController { @GetMapping public String user(){ return "get users"; } @PostMapping public String addUser(){ return "post user"; } @GetMapping("/{userId}") public String findUser(@PathVariable String userId){ return "get suerId = " + userId; } @PatchMapping("/{userId}") public String updateUser(@PathVariable String userId){ return "update userId = " + userId; } @DeleteMapping("/{userId}") public String deleteUser(@PathVariable String userId){ return "delete userId = " + userId; }}