일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 인터페이스
- oracle
- GRANT VIEW
- cursor문
- 대덕인재개발원
- 오라클
- 참조형변수
- 메소드오버로딩
- 예외미루기
- EnhancedFor
- 추상메서드
- 자동차수리시스템
- 정수형타입
- Java
- 환경설정
- 객체 비교
- 컬렉션프레임워크
- abstract
- 다형성
- 제네릭
- 컬렉션 타입
- 사용자예외클래스생성
- 한국건설관리시스템
- exception
- 집합_SET
- 생성자오버로드
- 예외처리
- 어윈 사용법
- 자바
- NestedFor
- Today
- Total
거니의 velog
(9) 스프링에서 지원하는 여러 가지 기능 3 본문
5. 스프링 인터셉터 사용하기
* 이번에는 스프링에서 제공하는 기능인 인터셉터(Interceptor)에 대해 알아보자. 인터셉터를 사용하면 브라우저 요청이 있을 때 요청 메서드 호출 전후에 개발자가 원하는 기능을 수행할 수 있다.
* 무슨 말인지 다음 그림을 보자.
* 위 그림과 같이 브라우저의 요청을 해당 컨트롤러의 메서드가 처리하기 전후에 인터셉터를 두어 특정 작업을 수행한다. 인터셉터는 필터와 비슷한 기능을 하지만 필터는 웹 애플리케이션의 특정한 위치에서만 동작하는 데 반해 인터셉터는 좀 더 자유롭게 위치를 변경해서 기능을 수행할 수 있다. 즉, 인터셉터는 애플리케이션 안에서 적용 범위를 설정할 수 있다. 주로 쿠키(cookie) 제어, 파일 업로드 작업 등에 사용한다.
* 다음 표는 스프링에서 인터셉터 기능을 구현하는 데 사용되는 HandlerInterceptor 클래스의 메서드들이다.
< 스프링 HandlerInterceptor 클래스의 여러 가지 메서드 >
메서드 | 기능 |
preHandle() | 컨트롤러 실행 전 호출한다. |
postHandle() | 컨트롤러 실행 후 DIspatcherServlet이 뷰로 보내기 전에 호출한다. |
afterCompletion() | 뷰까지 수행하고 나서 호출된다. |
(1) 인터셉터 사용해 다국어 기능 구현하기
* 이번에는 인터셉터를 사용해 다국어 기능을 구현해 보자.
1. 다국어 기능 관련 설정을 하기 위해 XML 파일을 준비한다.
2. servlet-context.xml에서 브라우저의 요청에 대해 수행할 인터셉터를 빈으로 설정한다.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--
xmlns:mvc="http://www.springframework.org/schema/mvc" : <mvc:~> 태그를 사용하기 위해 추가한다.
-->
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.myspring.pro28" />
<!-- 멀티파트 리졸버 -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<beans:property name="maxUploadSize" value="52428800" />
<beans:property name="maxInMemorySize" value="1000000" />
<beans:property name="defaultEncoding" value="utf-8" />
</beans:bean>
<!--
<mvc:interceptors> : 인터셉터 기능을 사용하도록 설정한다.
<mvc:mapping path="/test/*.do" /> : 특정 요청, 즉 /test/*.do에 대해서만 인터셉터 빈을 수행한다.
<beans:bean class="com.myspring.pro28.ex05.LocaleInterceptor" /> : 인터셉터 기능을 수행할 빈을 설정한다.
-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/test/*.do" />
<mvc:mapping path="/*/*.do" />
<beans:bean class="com.myspring.pro28.ex05.LocaleInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans:beans>
3. 그런 다음 다국어 기능과 관련된 빈과 메시지 파일을 읽어 들이는 message-context.xml을 작성한다. ReloadableResourceBundleMessageSource 클래스를 사용해 message 프로퍼티 파일을 읽어 들이면 다국어 기능을 사용할 수 있다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 스프링의 -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:locale/messages</value> <!-- 패키지 locale에서 massages.properties를 읽어 들인다. -->
</list>
</property>
<!-- 파일의 기본 인코딩을 지정합니다. -->
<property name="defaultEncoding" value="UTF-8" /> <!-- 파일의 기본 인코딩을 지정한다. -->
<property name="cacheSeconds" value="60" /> <!-- properties 파일이 변경되었는지 확인하는 주기를 지정한다. 60초 간격으로 지정한다. -->
</bean>
</beans>
4. 다국어 메시지들을 저장한 프로퍼티 파일을 생성한다. 프로젝트의 /src/main/resource 패키지 하위에 locale 패키지를 만든 후 프로퍼티 파일들을 작성해 넣는다.
[messages_en.properties]
site.title=Member Info
site.name=name
site.job=job
name=hong kil-dong
job=student
btn.send=send
btn.cancel=cancel
btn.finish=finish
[messages_ko.properties]
site.title=\ud68c\uc6d0\uc815\ubcf4
site.name=\uc774\ub984
site.job=\uc9c1\uc5c5
name=\ud64d\uae38\ub3d9
job=\ud504\ub85c\uadf8\ub798\uba38
btn.send=\uc804\uc1a1
btn.cancel=\ucde8\uc18c
btn.finish=\uc885\ub8cc
[messages.properties]
site.title=\ud68c\uc6d0\uc815\ubcf4
site.name=\uc774\ub984
site.job=\uc9c1\uc5c5
name=\ud64d\uae38\ub3d9
job=\ud504\ub85c\uadf8\ub798\uba38
btn.send=\uc804\uc1a1
btn.cancel=\ucde8\uc18c
btn.finish=\uc885\ub8cc
5. 사용자가 직접 만든 인터셉터를 구현하는 데 필요한 자바 클래스 파일들을 준비한다.
6. 스프링의 인터셉터 기능은 스프링에서 제공하는 HandlerInterceptorAdapter 클래스를 상속받거나 인터페이스인 HandlerInterceptor를 구현해서 사용한다. preHandle() 메서드는 컨트롤러를 실행하기 전에 호출되어 수행한다.
package com.myspring.pro28.ex05;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class LocaleInterceptor extends HandlerInterceptorAdapter { // 사용자 정의 인터셉터는 반드시 HandlerInterceptorAdapter를 상속받아야 한다.
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 컨트롤러 실행 전 호출된다.
HttpSession session = request.getSession();
String locale = request.getParameter("locale"); // 브라우저에서 전달한 locale 정보를 가져온다.
if (locale == null) locale = "ko"; // 최초 요청시 locale을 한국어로 설정한다.
session.setAttribute("org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE", new Locale(locale)); // LOCALE 속성 값을 세션에 저장해 SessionLocaleResolver가 사용할 수 있게 한다.
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception { // 컨트롤러 실행 후 호출된다.
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception { // 뷰(JSP)를 수행한 후 호출된다.
}
}
7. 컨트롤러는 요청에 대해 JSP 이름만 뷰리졸버로 반환한다.
package com.myspring.pro28.ex05;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller("localeController")
public class LocaleController {
@RequestMapping(value = "/test/locale.do", method = { RequestMethod.GET })
public String locale(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("localeController입니다.");
return "locale"; // 컨트롤러는 뷰이름만 반환한다.
}
}
8. locale 값에 따라 다국어로 표시되는 JSP 페이지를 구현한다.
9. JSP에서 다국어들을 표시하기 위해 스프링의 <spring:message> 태그를 이용한다. code에 properties 파일의 키를 입력하면 키에 대한 값이 표시되고, code에 해당하는 값이 없으면 기본값으로 표시된다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
import="java.io.*"
pageEncoding="UTF-8"
isELIgnored="false" %>
<%-- spring:message 태그를 이용할 수 있도록 설정한다. --%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>
<%-- spring:message 태그를 이용해 code 속성에 프로퍼티 파일의 site.title 값을 표시한다. --%>
<spring:message code="site.title" text="Member Info" />
</title>
</head>
<body>
<%-- 한국어를 요청한다. --%>
<a href="${pageContext.request.contextPath }/test/locale.do?locale=ko">한국어</a>
<%-- 영어를 요청한다. --%>
<a href="${pageContext.request.contextPath }/test/locale.do?locale=en">ENGLISH</a>
<h1>
<spring:message code="site.title" text="Member Info" />
</h1>
<p>
<%-- 프로퍼티 site.name에 해당하는 값을 표시한다. --%>
<spring:message code="site.name" text="no name" /> :
<%-- 프로퍼티 name에 해당하는 값을 표시한다. --%>
<spring:message code="name" text="no name" />
</p>
<p>
<spring:message code="site.job" text="no job" /> :
<spring:message code="job" text="no job" />
</p>
<%-- spring:message 태그를 이용해 프로퍼티 btn.send를 버튼 이름으로 설정한다. --%>
<input type="button" value="<spring:message code='btn.send' />" />
<input type="button" value="<spring:message code='btn.cancel' />" />
<input type="button" value="<spring:message code='btn.finish' />" />
</body>
</html>
10. 다음의 주소로 최초 요청 시 한글로 표시된다.
- http://localhost/pro28/test/locale.do
11. ENGLISH를 클릭하면 페이지의 텍스트가 영어로 표시된다.
12. 한국어를 클릭하면 다시 한국어로 표시된다.
* 이상으로 인터셉터 기능에 대해 알아봤다.
6. 인터셉터 사용해 요청명에서 뷰이름 가져오기
* 이번에는 인터셉터를 사용해 요청 URL에서 뷰이름을 가져오는 기능을 구현해 보자. 이전에 실습한 회원 관리 기능에 인터셉터 기능을 추가하고 수정하는 작업이다.
1. 실습에 필요한 파일은 다음과 같다.
2. servlet-context.xml에 인터셉터를 설정한다.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--
xmlns:mvc="http://www.springframework.org/schema/mvc" : <mvc:~> 태그를 사용하기 위해 추가한다.
-->
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.myspring.pro28" />
<!-- 멀티파트 리졸버 -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<beans:property name="maxUploadSize" value="52428800" />
<beans:property name="maxInMemorySize" value="1000000" />
<beans:property name="defaultEncoding" value="utf-8" />
</beans:bean>
<!--
<mvc:mapping path="/*/*.do" /> : 모든 요청에 대해 인터셉터를 수행한다.
-->
<mvc:interceptors>
<mvc:interceptor>
<!-- <mvc:mapping path="/test/*.do" /> -->
<mvc:mapping path="/*/*.do" />
<beans:bean class="com.myspring.pro28.ex05.LocaleInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans:beans>
3. member 패키지 하위에 interceptor 패키지를 만든 후 ViewNameInterceptor 클래스를 작성한다.
4. 인터셉터 수행 시 preHandle() 메서드로 전달된 request에서 추가한 getViewName() 메서드를 이용해 뷰이름을 가져온 후 request에 바인딩한다.
package com.myspring.pro27.member.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class ViewNameInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
try {
String viewName = getViewName(request); // getViewName() 메서드를 이용해 브라우저의 요청명에서 뷰이름을 가져온다.
request.setAttribute("viewName", viewName); // 뷰이름을 request에 바인딩한다.
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
private String getViewName(HttpServletRequest request) throws Exception { // 요청명에서 뷰 이름을 반환한다.
String contextPath = request.getContextPath();
String uri = (String) request.getAttribute("javax.servlet.include.request_uri");
if (uri == null || uri.trim().equals("")) {
uri = request.getRequestURI();
}
int begin = 0;
if (!((contextPath == null) || ("".equals(contextPath)))) {
begin = contextPath.length();
}
int end;
if (uri.indexOf(";") != -1) {
end = uri.indexOf(";");
} else if (uri.indexOf("?") != -1) {
end = uri.indexOf("?");
} else {
end = uri.length();
}
String fileName = uri.substring(begin, end);
if (fileName.indexOf(".") != -1) {
fileName = fileName.substring(0, fileName.lastIndexOf("."));
}
if (fileName.lastIndexOf("/") != -1) {
fileName = fileName.substring(fileName.lastIndexOf("/", 1), fileName.length());
}
return fileName;
}
}
5. 컨트롤러에서는 request에서 바인딩된 뷰이름을 가져와 뷰리졸버로 반환한다.
@Controller("memberController")
public class MemberControllerImpl implements MemberController {
...
@Override
@RequestMapping(value="/member/listMembers.do" ,method = RequestMethod.GET)
public ModelAndView listMembers(HttpServletRequest request, HttpServletResponse response) throws Exception {
//String viewName = getViewName(request);
String viewName = (String) request.getAttribute("viewName"); // 인터셉터에서 바인딩한 뷰이름을 가져온다.
List membersList = memberService.listMembers();
ModelAndView mav = new ModelAndView(viewName);
mav.addObject("membersList", membersList);
return mav;
}
...
@RequestMapping(value = "/member/*Form.do", method = RequestMethod.GET)
private ModelAndView form(@RequestParam(value= "result", required=false) String result,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
//String viewName = getViewName(request);
String viewName = (String)request.getAttribute("viewName"); // 인터셉터에서 바인딩된 뷰이름을 가져온다.
ModelAndView mav = new ModelAndView();
mav.addObject("result",result);
mav.setViewName(viewName);
return mav;
}
6. 다음의 주소로 로그인창을 요청하여 뷰이름을 인터셉터에서 가져온다. 그리고 이를 컨트롤러에 전달한다.
- http://localhost/pro27/member/loginForm.do
* 지금까지 스프링에서 제공하는 여러 가지 오픈 소스 라이브러리에 대해 알아봤다. 이 외에도 제공하는 기능이 많으므로 스프링 관련 사이트를 참고하기 바란다.
'Java_Spring Framework part2' 카테고리의 다른 글
(11) 스프링 REST API 사용하기 2 (0) | 2023.11.20 |
---|---|
(10) 스프링 REST API 사용하기 1 (0) | 2023.11.16 |
(8) 스프링에서 지원하는 여러 가지 기능 2 (0) | 2023.11.15 |
(7) 스프링에서 지원하는 여러 가지 기능 1 (0) | 2023.11.15 |
(6) 메이븐과 스프링 STS 사용법 6 (0) | 2023.11.15 |