Whiteship's Note


Vlidator - ValidationUtils 사용하기



Spring에서 Validator를 구현하는 방법은 두 가지가 있습니다.
1. Programmatic
2. Declarative

그 중에서 첫 번째 Programmatic 방법을 사용하여 구현할 때 ValidationUtils를 사용하면 매우 간단하게 구현할 수 있습니다.
사용자 삽입 이미지
인터페이스 중에 인자가 네개인 녀석을 사용하여 defaultMessage를 주면 프로퍼티 파일을 만들지 않아도 메시지를 출력할 수 있습니다.

1. Validator 만들기
public class MemberInfoValidator implements Validator{

    public boolean supports(Class clazz) {
        return MemberInfo.class.isAssignableFrom(clazz);
    }

    public void validate(Object object, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "required", "Enter your email");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "required", "Enter your password");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "confirmPassword", "required", "Enter the same password for confirmation");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "confirmMember", "required", "Enter ajn member code");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required", "Enter your name");
    }

}

Validator 인터페이스를 구현하고 ValidationUtils를 사용하여 간단하게 구현할 수 있습니다.

2. Controller에 등록하기
  public CreateMemberInfoController() {
        setCommandClass(MemberInfo.class);
        setCommandName("memberInfo");
        setFormView("createMemberInfo");
        setSuccessView("viewMemberList");
        setValidator(new MemberInfoValidator());
    }

setValidator 메소드를 사용하여 위에서 만든 Validator를 등록해 줍니다.

3. 화면에 보여주기
<form:errors path="속성 이름" />

이런식으로 속성 이름을 적어주면 그 이름에 해당하는 에러 메시지를 고자리에 출력해 줍니다.

사용자 삽입 이미지

<form:errors path="*" />

이렇게 써주면 저 태그가 들어간 위치에 모든 에러 메시지를 모아서 출력할 수 있습니다. 좋군요~
사용자 삽입 이미지

신고
top


13.10. Handling exceptions

Spring/Chapter 13 : 2007.05.21 11:35


특정 예외가 발생했을 때 특정 페이지로 이동 시킬 수 있습니다.

먼저 컨트롤러든 서비스 단이든 벨리데이션 할 때든 에러를 발생시킵니다. 예외 처리 할 것도 없기 때문에 RuntimeException이 좋겠네요.

    public void add(MemberInfo memberInfo) {
        if(memberInfo.getConfirmMember().equals("ajnapaqj")){
            String email = memberInfo.getEmail();
            if(memberInfoDao.findByEmail(email) == null)
                memberInfoDao.insert(memberInfo);
            else
                throw new AlreadyExistEmailException();
        }
        else
            throw new InvalidMemberCodeException();
    }

저는 서비스 단에 구현했습니다. 사실 고민이 됩니다. 이런 거는 벨리데이터에 넣어야 필드 값 검사할 때 같이 하면 좋을 것 같은데 아직 벨리데이터를 만들지 않았기 때문에 간단하게 서비스 단에 구현해 뒀습니다. 나중에 옮겨야 벨리데이터 만들고 옮겨야 겠습니다.

그리고 사용자 예외를 만들어 줍니다.
public class AlreadyExistEmailException extends RuntimeException {}
public class InvalidMemberCodeException extends RuntimeException {}

그리고 Spring의 ExceptionResolver를 등록해줍니다.
    <!-- Exception Resolver -->
    <bean id="exceptionMapping"
        class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="InvalidMemberCodeException">
                    /exception/joinFailedByMemberCode
                </prop>
                <prop key="AlreadyExistEmailException">
                    /exception/joinFailedByExistingEmail
                </prop>
            </props>
        </property>
    </bean>

이런식으로 Exception과 view 이름을 매핑 시켜 주면 view 리졸버에 의해 view를 찾게 됩니다.



신고
top


Intercepting requests 예제

Spring/Chapter 13 : 2007.05.17 12:36


어떤 서비스를 로그인 한 유저에게만 제공하고 싶다면...

request를 처리하는 메소드 내에서

if (request.getSession.getAttribute("user") != null)
    throw LoginRequiredException();

이런식으로 예외를 발생시키고 이 예외가 발생할 때마다 로그인 페이지로 이동 시키게 할 수 있습니다.

하지만 저런 코드가 여러 부분에서 필요하게 될 것이고 이것을 AOP를 적용하여 Aspect로 빼내고 싶어지는 것이 당연합니다.

그런데 Spring AOP가 조금 복잡하자나열(2.0 에서는 많이 나아졌지만)...pointcut 정의 해줘야 하는데 문법도 좀 희한하고 advice 종류도 다양한데 특정 인자를 받아와야 하는 방법을 써야 하니까 args 표현식을 써야 하고.. 등등 복잡합니다.

그래서.. 간단하게 HadlerMapping과 HandlerInterceptor 를 사용해서 AOP를 적용할 수 있습니다. 요녀석을 사용하면 HttpRequest와 HttpResponse를 인자로 받는 Around Advice를 적용하는 기분이 들 것입니다.

1. Handler Mapping 등록하기
- Handler Mapping을 여러 개 사용할 수 있습니다. 그리고 그 들간의 순서를 order 속성을 사용하여 지정해 줄 수 있습니다. viewResolver를 여러 개 등록하는 거랑 같습니다.

    <bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
        <property name="order" value="2" />
    </bean>

기존에 사용하던 HandlerMapping은 BeanNameUrlHandlerMapping으로 암묵적으로[각주:1] 사용하고 있었습니다.

이 녀석을 위에 보시다시피 명시적으로 표기해 주고 순서를 두 번째로 지정합니다. 다음으로는 User를 체크해야 할 request를 처리할 HandlerMapping을 등록합니다.

<bean id="userCheckHandlerMapping"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="order" value="1" />
        <property name="interceptors">
            <list>
                <ref bean="memberCheckInterceptor"/>
            </list>
        </property>
        <property name="mappings">
            <value>
                /board/createArticle.html = createArticleController
                /board/createReply.html = createReplyController
                /createAuction.html = createLPAuctionController
                /auction/insertAuctionReply.html = insertAuctionReplyController
                /fileUpload.html = uploadFileController
            </value>
        </property>
    </bean>

SimpleUrlHandlerMapping을 사용하여 다섯개의 request를 처리할 것입니다. 저 request 들은 모두 memberCheckInterceptor를 거쳐가게 되어있습니다.

따라서 이제 memberCheckInterceptor만 구현해 주면 구현이 끝납니다.

2. Interceptor 만들기

public class MemberCheckInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(request.getSession().getAttribute("user") != null)
            return true;
        else {
            response.sendRedirect("http://localhost:8080/classicMania/login.html");
            return false;
        }
    }
}

와.. 간단합니다. user라는 이름의 객체가 세션에 있으면 계속 request를 처리하고 아니면 login 페이지로 넘어가도록 합니다. true는 계속 처리 false는 처리 안하게 합니다. Around Advice에서 해당 메소드를 실행 할지 말지 선택할 수 있었던 것과 유사하지 않나효.

3. 실행


로그인 안 한 상태에서 파일 업로드 페이지로 가려고 하면 => 로그인 페이지로 이동
로그인 한 상태라에서 파일 업로드 페이지로 가려고 하면 => 파일 업로드 페이지 요청을 처리합니다.
  1. 명시적으로 handleMapping을 등록하지 않으면 DispacherSevlet이 알아서 이녀석을 만들어서 사용하기 떄문이빈다. [본문으로]
신고
top


MultipartResolver 사용하여 파일 업로드 구현 예제

Spring/Chapter 13 : 2007.05.14 17:23


1. 사용할 Resolver 선택 및 등록
1.1. 필요한 jar 파일 추가

2. 폼 만들기

3. 모델 객체에 파일 다룰 속성 추가
3.1. String, bate[], MultupartFile 중 어떤 타입으로 받을 것인가 선택 및 코딩

4. 컨트롤러 만들기
(4.0. 바인딩 할 꺼면-String, byte[] 사용할 때- PropertyEditor 사용해서 바인딩 하기)
4.1. 디렉토리 설정
4.2. 디렉토리로 원본의 사본을 만들어 넣어 둡니다.

제 나름대로 책보고 예제 만들어 보다가 정리한 순서이지 꼭 저 위에 있는 순서대로 해야 하는건 아닙니다.

1. 사용할 Resolver 선택 및 등록

Cos와 Commons 라이브러리 중에 선택할 수 있습니다. Spring Reference, Pro Spring, Spring MVC 책 모두 Commons 라이브러리를 사용하고 있었습니다. 그래서 저도 그냥 Commons 라이브러리 사용했습니다.

1.1 필요한 Jar 파일 추가

Commons 라이브러리를 사용할 때 필요한 jar 파일은 두 개 입니다. 레퍼런스에는 commons-fileupload.jar 만 필요하다고 나오는데 저 jar 가 commons-io.jar 에 의존성을 가지고 있기 때문에 commons-io.jar도 추가해야 합니다.

2. 폼 만들기

간단합니다. <input type="file"> 로 해주면 파일 업로드 할 수 있는 버튼이 추가 됩니다. 이 때 폼태그에는 추가해줘야 할 것이 있습니다. request 타입을 multipart를 포함하는 request임을 알려주기 위한 것 같네요.

<form:form commandName="fileCommand" method="post" enctype="multipart/form-data">
    파일 선택 <input type="file" name="file"/><br/>
    <input type="submit" value="Submit"/>
</form:form>

3. 모델 객체에 파일 다룰 속성 추가

굳이 모델 객체에 추가하지 않고 커맨드 객체를 사용할 것이라면 커맨드 객체에 속성을 추가해 줍니다. 하지만 전 객체 하나 만드는 것 보다 필드 하나 추가하는 걸 선택했습니다. 따라서 FILE 도메인에 속성 하나를 추가할 것입니다.

3.1. String, bate[], MultupartFile 중 어떤 타입으로 받을 것인가 선택 및 코딩

폼에서 입력되는 파일을 객체의 속성으로 받기 위해 Spring에서 지원해주는 기능으로 사용할 수 있는 타입은 String, byte[], MultipartFile 세가지 입니다. 이 중에서 File 타입으로 받아서 File의 이름과 사이즈 등을 구하려면 역시 MultipartFile을 선택하는 것이 편하겠습니다.

    private String name;
    private Long size;
    private String filePath;
    private MultipartFile file;


4. 컨트롤러 만들기

4.0 String, bytep[], Multipart 로 바인딩 하기

Spring Reference 13.8.3에 보면 예제가 잘 나와있습니다. 저 세가지 중에서 String과 byte[]로 바인딩 할 때는 Spring이 제공하는 별도의 PropertyEditor를 등록해줘야 합니다. 하지만 MultipartFile은 그럴 필요가 없이 그냥 알아서 바인딩 해줍니다.

4.1. 디렉토리 설정

Spring 워크북에는 조금 다른 방식으로 등록했지만 저는 Spring MVC에 나와있는 예제가 사용한 방식을 사용했습니다.
컨트롤러에 File 타입으로 디렉토리를 속성으로 주고 setter injection을 사용합니다.

    <!-- MusicFile  -->
    <bean name="/fileUpload.html"
        class="com.classicMania.controller.file.UploadFileController">
        <property name="destinationDir" value="D://down" />
    </bean>

4.2. 디렉토리로 원본의 사본을 만들어 넣어 둡니다.

Spring이 제공하는 FileCopyUtils 를 사용하여 간단하게 원본(웹에서 입력하고 있는 파일)을 사본(위에서 설정한 디렉토리로)을 만들 수 있습니다.

컨트롤러의 소스코드를 보면 다음과 같습니다.
public class UploadFileController extends SimpleFormController implements InitializingBean {
    // 4.1
    private File destinationDir;

    public void setDestinationDir(File destinationDir) {
        this.destinationDir = destinationDir;
    }

    public UploadFileController() {
        setCommandName("fileCommand");
        setCommandClass(FILE.class);
        setFormView("file/uploadFile");
        setSuccessView("file/viewFileList");
    }

    public void afterPropertiesSet() throws Exception {
        if (destinationDir == null) {
            throw new IllegalArgumentException("Must specify destinationDir");
        }
        else if (!destinationDir.isDirectory() && !destinationDir.mkdir()) {
            throw new IllegalArgumentException(destinationDir + " is not a " + "directory, or it couldn't be created");
        }
    }

    @Override
    protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command,
            BindException exception) throws Exception {
        response.setContentType("text/plain");
        if (! (request instanceof MultipartHttpServletRequest)) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Expected multipart request");
            return null;
        }
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        String fileName = file.getOriginalFilename();
        File destination = File.createTempFile("file", fileName, destinationDir);
        //4.2
        FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(destination));

        Member member = (Member) request.getSession().getAttribute("user");

        FILE newFile = (FILE) command;
        newFile.setMember(member);
        newFile.setFilePath(destination.getAbsolutePath());
        newFile.setName(file.getOriginalFilename());
        newFile.setSize(file.getSize());
        newFile.setFile(file);
        ServiceManager.getMemberService().update(member);
        ServiceManager.getFileService().add(newFile);

        Map<String, Object> model = new HashMap<String, Object>();
        model.put("files", ServiceManager.getFileService().getAll());
        model.put("owner", member.getName());
        return new ModelAndView(getSuccessView(), model);
    }

}


아~ Spring 좋아라~ 너무 좋아라~

파일 업로드 화면
사용자 삽입 이미지
파일 선택 화면
사용자 삽입 이미지
파일 업로드 선택
사용자 삽입 이미지
파일 업로드 결과
사용자 삽입 이미지

위 컨트롤러에서 설정한 패스(D:\down)에 잘 들어갔습니다.

신고
top


13.8. Spring's multipart (fileupload) support

Spring/Chapter 13 : 2007.05.12 21:48


13.8.1. Introduction

MultipartResolver 인터페이스를 사용하여 파일 업로드를 구현할 수 있습니다. 내부 구현체는 Commons FileUpload 와 COS FileUpload 를 사용합니다.

기본적으로 Spring은 Multipart 를 지원하진 않지만 Multipart를 포함하는 요청이 들어오면 Context에 설정해둔 MutipartResoolver를 사용하여 적절하게 처리할 수 있습니다.

13.8.2. Using the MultipartResolver

Multipart 기능을 사용하기 위해 먼저 사요할 MultipartResolver를 bean으로 등록해야 합니다.

CommonsMultipartResolver 등록하기 :: commons-fileupload.jar, commons-io.jar 필요함
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="100000"/>
</bean>

CosMultipartResolver 등록하기 :: cos.jar 필요함
<bean id="multipartResolver" class="org.springframework.web.multipart.cos.CosMultipartResolver">

    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="100000"/>
</bean>

13.8.3. Handling a file upload in a form

화면에서 파일 입력 받기.
<html>
    <head>
        <title>Upload a file please</title>
    </head>
    <body>
        <h1>Please upload a file</h1>
        <form method="post" action="upload.form" enctype="multipart/form-data">
            <input type="file" name="file"/>
            <input type="submit"/>
        </form>
    </body>
</html>


화면에서 입력받은 파일을 객체로 바인딩 해야 하는데 이 때 String 타입으로 바인딩하려면 StringMultipartEditor, byte타입의 배열로 바인딩 하려면 ByteArrayMultipartEditor 를 사용할 수 있습니다.

byte 타입의 배열 이나 String으로 바인딩하지 않고 MultipartFile 타입으로 받으려면 별다른 바인딩이 필요 없습니다.

이 세가지 방법 중 String으로 바인딩하는 예제를 보겠습니다.
public class FileUploadController extends SimpleFormController {

    protected ModelAndView onSubmit(
        HttpServletRequest request,
        HttpServletResponse response,
        Object command,
        BindException errors) throws ServletException, IOException {

         // cast the bean
        FileUploadBean bean = (FileUploadBean) command;

         let's see if there's content there
        String file = bean.getFile();
        if (file == null) {
             // hmm, that's strange, the user did not upload anything
        }

         // well, let's do nothing with the bean for now and return
        return super.onSubmit(request, response, command, errors);
    }

    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder)
        throws ServletException {
        // to actually be able to convert Multipart instance to a String
        // we have to register a custom editor
        binder.registerCustomEditor(String.class, new StringMultipartFileEditor());
        // now Spring knows how to handle multipart object and convert them
    }

}

public class FileUploadBean {

    private String file;

    public void setFile(String file) {
        this.file = file;
    }

    public String getFile() {
        return file;
    }
}

오호.. 간단하군요. 집에가서 써먹어 봐야겠습니다.
신고
top


13.7. Using themes

Spring/Chapter 13 : 2007.05.12 21:08


13.7.1. Introduction

테마를 적용하기 위해서는 전역적으로 사용할 스타일 시트(CSS)와 그림 파일등의 자원을 정의하는 것이 필요합니다.

13.7.2. Defining themes

ThemeSource 를 사용하면 되는데 XmlWebApplicationContext 가 ThemeSource 를 구현하고 있으며 내부 구현체로는 ResourceBundleThemeSource 를 기본으로 사용하고 있습니다.

사용자 삽입 이미지

ResourceBundleThemeSource는 classpath에 들어있는 프로퍼티 파일을 읽어 들여서 theme을 설정할 때 사용합니다.

styleSheet=/themes/cool/style.css
background=/themes/cool/img/coolBg.jpg

위와 같이 프로퍼티 파일에 설정해 두고 view에서는 spring:theme 태그를 사용하여 key에 해당하는 이름으로 각 요소들을 사용할 수 있습니다.

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
   <head>
      <link rel="stylesheet" href="<spring:theme code="styleSheet"/>" type="text/css"/>
   </head>
   <body background="<spring:theme code="background"/>">
      ...
   </body>
</html>

13.7.3. Theme resolvers

마지막으로 저렇게 만들어둔 여러개의 Theme 중에 어떤 Theme를 사용할지 선택해야 합니다. 이때 ThemeResolver를 사용하면 됩니다.

Class

Description

FixedThemeResolver

defaultThemeName 속성을 사용해서 고정적인 테마를 설정합니다.

SessionThemeResolver

각 세션에 테마에 대한 정보를 유지합니다. 세션 간에 공유되지는 않습니다.

CookieThemeResolver

선택된 테마에 대한 정보를 쿠키에 유지 합니다.




신고
top


13.6. Using locales

Spring/Chapter 13 : 2007.05.12 18:22


Request가 들어오면 Dispatcher는 Locale resolver를 찾게 되고 만약에 있으면 Locale을 설정할 때 사용합니다. RequestContext.getLocale() 메소드를 사용해서 Locale resolver에 의해 설정 된 Locale을 가져올 수 있습니다.

13.6.1. AcceptHeaderLocaleResolver

사용자의 브라우져에서 보내진 request의 헤더에 accept-language 부분에서 Locale을 읽어들입니다. 사용자의 OS locale을 나타냅니다.

13.6.2. CookieLocaleResolver

사용자 컴터에 쿠키를 남아 있다면 그 쿠키에 설정한 Locale을 읽어 들입니다.
다음과 같은 속성을 설정할 수 있습니다.

Property

Default

Description

cookieName

classname + LOCALE

쿠키 이름

cookieMaxAge

Integer.MAX_INT

쿠키 살려둘 시간.

-1로 해두면 브라우저를 닫을 때 없어집니다.

cookiePath

/

Path를 지정해 주면 해당 하는 path와 그 하위 path에서만 참조할 수 있습니다.


13.6.3. SessionLocaleResolver

requst가 가지고 있는 session으로 부터 locale 정보를 가져옵니다.

13.6.4. LocaleChangeInterceptor

HandlerMapping에 인터셉터를 등록하여 특정 locale의 요청을 가로채서 특정 파라미터에 넘어 온 값으로 locale 을 알아낼 수 있습니다.
<bean id="localeChangeInterceptor"
      class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    <property name="paramName" value="siteLanguage"/>
</bean>

<bean id="localeResolver"
      class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>

<bean id="urlMapping"
      class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="interceptors">
        <list>
            <ref bean="localeChangeInterceptor"/>
        </list>
    </property>
    <property name="mappings">
        <value>/**/*.view=someController</value>
    </property>
</bean>

여기서는 모든 .view로 끝나는 요청을 가로채서 siteLanguage라는 request의 파라미터를 조사 하여 locale을 알 수 있게 됩니다.
신고
top


13.5.2. Chaining ViewResolvers

Spring/Chapter 13 : 2007.05.12 16:18


다수의 ViewResolver들을 등록해 둘 수 있습니다. 그 때 특정 view 이름을 해석할 View Resolver들을 순서대로 나열하는 것을 Chaining ViewResolver라고 하는 것 같습니다. ViewResolver들의 순서는 Ordered 인터페이스를 사용하여 설정할 수 있습니다.

레퍼런스의 예를 보겠습니다.
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
  <property name="prefix" value="/WEB-INF/jsp/"/>
  <property name="suffix" value=".jsp"/>
</bean>

<bean id="excelViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
  <property name="order" value="1"/>
  <property name="location" value="/WEB-INF/views.xml"/>
</bean>

<!-- in views.xml -->

<beans>
  <bean name="report" class="org.springframework.example.ReportExcelView"/>
</beans>

이렇게 등록 해두면 InternalResourceViewResolver는 특성상 ViewReslove 체인의 맨 마지막에 위치 하기 때문에 굳이 ExcelViewResolver에 order 속성에 숫자를 주지 않아도 되겠죠.

만약에 해당 ViewResolver에서 적당한 view를 찾지 못하면 그 다음 ViewResolver를 사용하여 찾게 됩니다. 끝까지 못찾으면 Exception이 발생합니다.

InternalResouceViewResolver와 VelocityViewResolver, FreeMarkerViewResolver 들은 맨 뒤에 위치 해야 합니다.

신고
top


13.5. Views and resolving them

Spring/Chapter 13 : 2007.05.12 15:05


핸들러(controller)는 요청을 처리 한 뒤 ModelAndView 객체를 넘겨 줍니다. 이 때 이 객체에 view의 이름을 같이 넘겨 주는데 이 이름으로 실제 view를 찾아 주는 역할을 하는 것이 View Resolver입니다.

13.5.1. Resolving views - the ViewResolver interface

Spring 에서 제공하는 다양한 ViewResolver들을 살펴 봅니다.

13.5.2. Chaining ViewResolvers

여러 개의 viewResolver를 사용할 수 있습니다.

13.5.3. Redirecting to views

리다이렉트 하는 방법들이 나와있는데 pass하겠습니당;;

신고
top


13.4.3. Intercepting requests - the HandlerInterceptor interface

Spring/Chapter 13 : 2007.05.12 14:26


HandlerMapping 안에 interceptor를 만들어서 HandlerMapping에 들어오는 요청들 중에 일부를 처리하는 Handler 하테 요청을 세 가지 시점(넘기기 전과 후, 완료 된 후)에 특정 작업을 추가할 수 있습니다.

레퍼런스에 나와있는 예제는 특정 시간 사이에 들어오는 요청이 아니면 모두 특정 페이지로 요청을 넘겨 버리게 됩니다.

먼저 인터셉터를 만들려면 HandlerInterceptor 인터페이스를 구현해야 합니다.
사용자 삽입 이미지
구현해야 할 메소드는 세 개이며 저 중에서 원 하는 것만 구현해서 사용할 수 있도록 어댑터 클레스를 제공합니다.

package samples;

public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter {

    private int openingTime;
    private int closingTime;

    public void setOpeningTime(int openingTime) {
        this.openingTime = openingTime;
    }

    public void setClosingTime(int closingTime) {
        this.closingTime = closingTime;
    }

    public boolean preHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler) throws Exception {

        Calendar cal = Calendar.getInstance();
        int hour = cal.get(HOUR_OF_DAY);
        if (openingTime <= hour < closingTime) {
            return true;
        } else {
            response.sendRedirect("http://host.com/outsideOfficeHours.html");
            return false;
        }
    }
}

예제에서는 이 어댑터를 사용하여 구현하였으며 preHandler 메소드를 사용하여 요청을 핸들러에게 넘기기 전에 작업을 합니다. 작업의 내용은 현재 요청이 들어온 시간이 특정 시간 사이라면 true, 아니면 http://host.com/outsideOfficeHours.html 여기로 요청을 넘기고 false를 리턴합니다.

인터셉터를 사용하려면 HandlerMapping의 peopertie에 등록해 주면 됩니다.
<beans>
    <bean id="handlerMapping"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="interceptors">
            <list>
                <ref bean="officeHoursInterceptor"/>
            </list>
        </property>
        <property name="mappings">
            <value>
                /*.form=editAccountFormController
                /*.view=editAccountFormController
            </value>
        </property>
    </bean>

    <bean id="officeHoursInterceptor"
          class="samples.TimeBasedAccessInterceptor">
        <property name="openingTime" value="9"/>
        <property name="closingTime" value="18"/>
    </bean>
<beans>

요청을 처리하기 전에 로그인 되어 있는지 확인하는 로직을 이렇게 구현해도 될 것 같네요.
신고
top


13.4.2. SimpleUrlHandlerMapping

Spring/Chapter 13 : 2007.05.11 18:06


이 HandlerMapping은 Ant 스타일의 path 매칭(특수 문자 사용을 말하는 듯 합니다.)을 사용할 수 있습니다.

<web-app>
    ...
    <servlet>
        <servlet-name>sample</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- maps the sample dispatcher to *.form -->
    <servlet-mapping>
        <servlet-name>sample</servlet-name>
        <url-pattern>*.form</url-pattern>
    </servlet-mapping>

    <!-- maps the sample dispatcher to *.html -->
    <servlet-mapping>
        <servlet-name>sample</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    ...
</web-app>

위와 같이 설정해두면 .form 과 .html 로 끝나는 request들을 sample-context.xml 이라는 DispatcherServlet에서 처리하게 됩니다.

<beans>
       
    <!-- no 'id' required, HandlerMapping beans are automatically detected by the DispatcherServlet -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <value>
                /*/account.form=editAccountFormController
                /*/editaccount.form=editAccountFormController
                /ex/view*.html=helpController
                /**/help.html=helpController
            </value>
        </property>
    </bean>

    <bean id="helpController"
          class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>

    <bean id="editAccountFormController"
          class="org.springframework.web.servlet.mvc.SimpleFormController">
        <property name="formView" value="account"/>
        <property name="successView" value="account-created"/>
        <property name="commandName" value="Account"/>
        <property name="commandClass" value="samples.Account"/>
    </bean>
<beans>

위의 설정 파일에서 ant 스타일의 문자를 사용하여 다수의 요청을 하나의 특정 컨트롤러에서 처리하도록 설정하였습니다.

ant 스타일에 대한 내용은 여기서 확인할 수 있습니다.
  • ? 는 문자 하나에 매칭하고
  • * 는 빵개에서 여러개의 문자에 매칭하고
  • ** 는 빵개에서 여러개의 디렉토리에 매칭합니다.
사용자 삽입 이미지

신고
top


13.4.1. BeanNameUrlHandlerMapping

Spring/Chapter 13 : 2007.05.11 17:52


전달 받은 Request를 application context에 정의해둔 특정 bean의 이름으로 매핑시킵니다.

예를 들어 http://samples.com/editaccount.form 이라는 request를 처리할 컨트롤러를 다음과 같이 등록할 수 있습니다.
<beans>
  <bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

  <bean name="/editaccount.form" class="org.springframework.web.servlet.mvc.SimpleFormController">
    <property name="formView" value="account"/>
    <property name="successView" value="account-created"/>
    <property name="commandName" value="account"/>
    <property name="commandClass" value="samples.Account"/>
  </bean>
<beans>


formView 는 입력받을 view 이름이고 seccessView 는 성공적으로 폼에서 객체를 입력받은 뒤 submit 할 view 이름이고 commandName은 폼에서 입력받은 값들을 바인딩할 객체이며 그 객체의 타입은 commandClass에서 지정합니다.

~~~.form 로 끝나는 요청을 distpacher에서 받아서 위에 설정해둔 handler Mapping을 사용하도록 하려면 다음과 같이 web.xml에 설정해야 합니다.
<web-app>
    ...
    <servlet>
        <servlet-name>sample</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

   <!-- maps the sample dispatcher to *.form -->
    <servlet-mapping>
        <servlet-name>sample</servlet-name>
        <url-pattern>*.form</url-pattern>
    </servlet-mapping>
    ...
</web-app>

BeanNameUrlHandlerMapping을 사용할 때는 굳이 위의 예제 처럼 bean으로 등록해줄 필요가 없습니다. 아무런 HandlerMapping도 등록되어 있지 않다면 Dispatcher가 알아서 BeanNameUrlHandlerMapping을 만들어서 사용하기 때문입니다.

사용자 삽입 이미지


신고
top


13.4. Handler mappings

Spring/Chapter 13 : 2007.05.11 13:37


사용자 삽입 이미지

DispatcherServlet 과의 관계를 나타내면 다음과 위와 같이 여러 개의 handlerMapping 객체를 List 형태로 가지고 있습니다. Dispatcher Servlet은 위 그림에 표현하지 않은 다른 객체들도 여럿 가지고 있습니다.

저 중에 딱 Dispatcher Servelt과 HandlerMapping 하나와의 관계를 보겠습니다.
사용자 삽입 이미지
요청을 처리할 커맨드 객체를 찾아서 HandlerExecutionChain 객체에 감싸서 넘겨 줍니다.

HandlerMapping들의 상위 클레스인 AbstractHandlerMapping 과 하위 클레스들의 관계를 살펴보겠습니다.
사용자 삽입 이미지
위와 같은 상속구조를 가지며 HandlerMapping을 아무것도 설정하지 않을 떄는 BeanNameUrlHandlerMapping을 사용합니다.

AbstractHandlerMapping에서 설정할 수 있는 설정들은 다음과 같습니다.
interceptors :: 사용할 인터셉터의 리스트
defaultHandler :: 매칭 하는 핸들러 없을 때 사용할 기본 핸들러
order: 여러 개의 HandlerMapping이 있을 때 그것 들 중에서 어떤 걸로 먼저 핸들러 찾을 지 설정할 때 사용
alwaysUseFullPath :: true로 설정하면 request의 전체 경로를 사용하고, false면 현재 servlet이 매핑 되어 있는 위치에서 부터 경로를 사용합니다.
urlPathHelpe :r: 보통 기본 값 그대로 둔다고 하네요.(using this property, you can tweak the UrlPathHelper used when inspecting URLs)
urlDecode :: 기본값은 false입니다. hadler mapping에서 적당한 핸들러를 찾기 전에 Request URL을 디코딩 하고 싶을 때 ture로 설정합니다.
lazyInitHandlers :: 싱글톤 스콥의 핸들러들의 객체를 필요로 할 때 생성하고 싶을 때 설정합니다.
신고
top


13.3.4. Command controllers

Spring/Chapter 13 : 2007.05.11 12:20


AbstractCommandController :: 특정 객체로 request의 파라미터를 바인딩 할 수 있습니다. 폼 기능은 제공하지 않지만 validation을 할 수 있으며 바인딩 객체를 사용하여 원하는 일을 할 수 있습니다.

AbstractFormController :: submit 기능을 제공하기 위한 추상 클레스 입니다. 사용자의 화면의 폼에 입력할 값을 채우면 각각의 필드로 바인딩하고 validation 할 수 있으며 폼을 보여줄 view와 입력이 성공적으로 완료 했을 때 보여줄 success view를 구현해야 합니다.

SimpleFormController :: 위에 있는 폼 컨트롤러 보다 진보한 것으로 폼 입력을 받을 커맨드 객체와 폼 view, success view를 설정할 수 있습니다.
이 녀석 라이프 사이클이 굉장히 복잡한 것 같던데 레퍼런스에는 설명이 없군요.

AbstractWizardFormController ::
이 클레스를 상속하는 클레스는 validatePage(), processFinish(), processCancel() 세 개의 메소드를 구현해야 합니다. 모델 객체를 view에게 넘겨 줄 때 referenceData(..) 메소드를 재정의 하여 사용할 수 있습니다.
getTargetPage() 를 사용하여 페이지를 넘길 수 있으며, 기본 바인딩과 validation을 재정의 하고 싶다면 onBindAndValidate()를 사용합니다.
getTargetPage() 에서 현재 페이지가 검증에 실패하면 앞이나 뒤로 움직일 수 있도록 setAllowDirtyBack() 와 setAllowDirtyForward()를 사용할 수 있습니다.
신고
top


13.3.2. Other simple controllers

Spring/Chapter 13 : 2007.05.10 11:28


ParameterizableViewController 를 사용하면 AbstractController 와 기능은 같지만 veiw 이름을 Configuration 파일에서 설정할 수 있습니다.
사용자 삽입 이미지
위의 인터페이스를 보면 viewName이라는 멤버 변수가 있고 setter injection 사용하여 설정 파일로 부터 view 이름을 설정 할 수 있다는 것을 알 수 있습니다.
사용자 삽입 이미지

AbstractController와의 관계는 다음과 같습니다. 실제 구현한 코드도 예상 했던 것 만큼이나 매우 간결합니다.

 public class ParameterizableViewController extends AbstractController {
   
   private String viewName;


   /**
    * Set the name of the view to delegate to.
    */
   public void setViewName(String viewName) {
       this.viewName = viewName;
   }

   /**
    * Return the name of the view to delegate to.
    */
   public String getViewName() {
       return viewName;
   }

   protected void initApplicationContext() {
       if (this.viewName == null) {
           throw new IllegalArgumentException("viewName is required");
       }
   }


   /**
    * Return a ModelAndView object with the specified view name.
    */
   protected ModelAndView handleRenderRequestInternal(RenderRequest request, RenderResponse response)
           throws Exception {

       return new ModelAndView(getViewName());
   }

}

신고

'Spring > Chapter 13' 카테고리의 다른 글

13.4.2. SimpleUrlHandlerMapping  (0) 2007.05.11
13.4.1. BeanNameUrlHandlerMapping  (0) 2007.05.11
13.4. Handler mappings  (0) 2007.05.11
13.3.4. Command controllers  (0) 2007.05.11
13.3.3. The MultiActionController  (2) 2007.05.10
13.3.2. Other simple controllers  (4) 2007.05.10
13.3.1. AbstractController and WebContentGenerator  (0) 2007.05.10
13.3. Controllers  (0) 2007.05.09
13.2. The DispatcherServlet  (0) 2007.05.07
13.1. Introduction  (0) 2007.05.07
13. Web MVC framework  (0) 2007.05.07
top


13.3.1. AbstractController and WebContentGenerator

Spring/Chapter 13 : 2007.05.10 08:41


다양한 컨트롤러들의 가장 기반이 되는 구현체인 AbstractController에서 설정할 수 있는 속성들은 다음과 같습니다.

Feature

Explanation

supportedMethods

어떤 형식의 요청을 받아 들일지 설정합니다. 보통은 GET 이나 POST 둘 중 하나며 원하는 메서드 이름으로 바꿀 수 도 있습니다. 지원 하지 않는 요청의 경우 ServletException이 발생합니다.

requiresSession

해당 컨트롤러가 작업을 할 때 Http session이 필요한지 설정합니다.

만약 필요로 하는데도 session을 담고 있는 request가 오지 않으면 SevletException이 발생합니다.

synchronizeSession

사용자의 Session을 동기화 처리해주고 싶을 때 사용합니다.

cacheSeconds

이 컨트롤러가 Http reponse에 캐쉬를 남기고 싶을 때 사용합니다.

기본값은 -1로 캐쉬를 남기지 않습니다.

useExpiresHeader

생성할 response HTTP 1.0과 호환 가능한 “Expires” 헤더를 기술합니다.

기본값은 true입니다.

useCacheHeader

생성할 responseHTTP 1.1과 호환 가능한 “Cache-Control” 헤더를 기술합니다.

기본값은 true입니다.


AbstractController를 사용하는 방법은 간단합니다. 다음과 같이 handleRequest 메소드를 구현해주면 됩니다.

package samples;

public class SampleController extends AbstractController {

    public ModelAndView handleRequestInternal(
        HttpServletRequest request,
        HttpServletResponse response) throws Exception {

        ModelAndView mav = new ModelAndView("hello");
        mav.addObject("message", "Hello World!");
        return mav;       
    }
}

AbstractController와 Controller 간의 관계는 다음과 같습니다.
사용자 삽입 이미지

이 컨트롤러는 view 이름을 소스 코드 내부에 위치 해야 하는 단점이 있습니다. 이렇게 되면 view가 바뀔 때 마다 소스 코드를 수정해줘야 하죠.
신고

'Spring > Chapter 13' 카테고리의 다른 글

13.4.2. SimpleUrlHandlerMapping  (0) 2007.05.11
13.4.1. BeanNameUrlHandlerMapping  (0) 2007.05.11
13.4. Handler mappings  (0) 2007.05.11
13.3.4. Command controllers  (0) 2007.05.11
13.3.3. The MultiActionController  (2) 2007.05.10
13.3.2. Other simple controllers  (4) 2007.05.10
13.3.1. AbstractController and WebContentGenerator  (0) 2007.05.10
13.3. Controllers  (0) 2007.05.09
13.2. The DispatcherServlet  (0) 2007.05.07
13.1. Introduction  (0) 2007.05.07
13. Web MVC framework  (0) 2007.05.07
top


13.3. Controllers

Spring/Chapter 13 : 2007.05.09 23:12


컨트롤러는 MVC중 C에 해당하며 사용자의 입력을 받은 뒤 뷰에 보여주기 적당한 모델로 바꿔준다.

Spring은 다양한 컨트롤러들을 제공하는데 크게 폼 컨트롤러, 커맨드 기반 컨트롤러, 마법사 스타일의 컨트롤러로 나뉩니다.

Spring 컨트롤러의 가장 상위에 위치한 Controller 인터페이스는 다음과 같습니다.
public interface Controller {

    /**
     * Process the request and return a ModelAndView object which the DispatcherServlet
     * will render.
     */
    ModelAndView handleRequest(
        HttpServletRequest request,
        HttpServletResponse response) throws Exception;

}

모든 Controller 구현체들은 재사용 가능하며, Thread-safe 해야합니다.

Workflow
사용자 삽입 이미지
Request 요청이 들어오면 DisptacherServlet에서 Locale, Theme 등등을 확인하고 HandlerMapping을 사용하여 요청을 담당할 컨트롤러를 물색합니다.

요청을 처리할 컨트롤러를 찾으면 그 컨트롤러의 handleRequest 메소드에게 HttpServletRequest와 HttpServletReponse 객체를 인자로 넘겨주며 호출합니다.

해당 컨트롤러는 요청을 처리하고 넘겨줄 ModelAndView 객체가 있다면 DispatcherServlet에게 해당 객체를 넘겨줍니다.

Notes on design and testing

Servlet API에 종속되어 기존 Servlet 의 기능을 모두 사용할 수 있습니다.

Servlet API에 의해 제공되는 HttpServletRequest 와 HttpServletResponse의 Mock 객체를 사용하여 handleRequest 메소드를 테스트 할 수 있습니다.
신고

'Spring > Chapter 13' 카테고리의 다른 글

13.4.2. SimpleUrlHandlerMapping  (0) 2007.05.11
13.4.1. BeanNameUrlHandlerMapping  (0) 2007.05.11
13.4. Handler mappings  (0) 2007.05.11
13.3.4. Command controllers  (0) 2007.05.11
13.3.3. The MultiActionController  (2) 2007.05.10
13.3.2. Other simple controllers  (4) 2007.05.10
13.3.1. AbstractController and WebContentGenerator  (0) 2007.05.10
13.3. Controllers  (0) 2007.05.09
13.2. The DispatcherServlet  (0) 2007.05.07
13.1. Introduction  (0) 2007.05.07
13. Web MVC framework  (0) 2007.05.07
top


13.2. The DispatcherServlet

Spring/Chapter 13 : 2007.05.07 23:03


<web-app>

    <servlet>
        <servlet-name>example</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <url-pattern>*.form</url-pattern>
    </servlet-mapping>

</web-app>

이렇게 web.xml에서 DispatcherServlet을 등록해 두면 .form 으로 끝나는 url은 모두 'example' 이라는 DispatcherServlet이 담당하게 됩니다.

사용자 삽입 이미지

(1)Front Controller 패턴을 사용하여 모든 요청을 하나의 서브릿에서 받은 뒤
(2)각각의 요청을 처리할 컨트롤러를 Handler Mapping을 기반으로 찾아서 요청을 넘기게 됩니다.
(3)컨트롤러에서 요청을 처리한 뒤 ModelAndView 객체를 다시 Dispatcher에게 넘기면
(4)Dispatcher는 받은 객체의 view 이름과 ViewResolver를 사용하여 해당 응답을 랜더링할 view에게 Model 객체들을 넘기게 되고 그것을 바탕으로 HTML 을 만들고
(5)다시 Dispatcher에게 제어권을 넘기면
(6)Reponse에 방금 만들어낸 HTML을 실어 보냅니다.

Spring 프레임워크는 맨 위에 있는 web.xml의 내용을 바탕으로 Dispatcher를 초기화 할 때
"Dispatcher의 이름"-servlet.xml 파일을 WEB-INF 폴더에서 찾고 그 안에 등록한 모든 bean들을 생성합니다.
each DispatcherServlet has its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. These inherited beans defined can be overridden in the servlet-specific scope, and new scope-specific beans can be defined local to a given servlet instance.
위의 레퍼런스 인용구에서 볼 수 있듯이 DispatcherSevlet이 WebApplicationContext를 가지고 있고 여기에 설정할 수 있는 특별한 bean들은 다음과 같습니다.

Bean type

Explanation

Controllers

MVC C에 해당하는 각종 컨트롤러들

Handler mappings

요청을 처리할 컨트롤러들 명시

View resolvers

View 이름을 풀 수 있는 컴포넌트들

Locale resolver

국제화 지원하기 위해 client locale 알아낸다

Theme resolver

테마 사용할 때 사용

multipart file resolver

Http 폼에서 파일 업로드 할 때 사용

Handler exception resolver(s)

특정 예외가 발생할 때의 보여줄 view 등록



신고

'Spring > Chapter 13' 카테고리의 다른 글

13.4.2. SimpleUrlHandlerMapping  (0) 2007.05.11
13.4.1. BeanNameUrlHandlerMapping  (0) 2007.05.11
13.4. Handler mappings  (0) 2007.05.11
13.3.4. Command controllers  (0) 2007.05.11
13.3.3. The MultiActionController  (2) 2007.05.10
13.3.2. Other simple controllers  (4) 2007.05.10
13.3.1. AbstractController and WebContentGenerator  (0) 2007.05.10
13.3. Controllers  (0) 2007.05.09
13.2. The DispatcherServlet  (0) 2007.05.07
13.1. Introduction  (0) 2007.05.07
13. Web MVC framework  (0) 2007.05.07
top


13.1. Introduction

Spring/Chapter 13 : 2007.05.07 22:02


Spring MVC 의 특징
  • 다른 web MVC 프레임워크와 마찬가지로 모든 요청을 DispatcherServlet 을 사용하여 요청을 처리할 핸들러에게 dispatch 합니다.
  • 요청을 처리할 핸들러(Controller)로는 가장 심플한 Controller 인터페이스 부터 여러 경우에 사용할 수 있는 구현체들을 제공합니다.
  • 어떤 객체라도 폼에 입력되는 값을 받아들이는 객체(폼 객체, Command)로 사용할 수 있습니다.
  • view resolution이 매우 유연(flexible)합니다.
  • ModelAndView 객체를 사용하여 view 와 model(맵 형태)을 담게 됩니다.
  • ModelAndView에 있는 view이름을 다양한 ViewResolver 를 사용하여 적당한 view에 매핑할 수 있습니다.
13.1.1. Pluggability of other MVC implementations

스트럿츠나 웹워크 같은 다른 웹 MVC 프레임워크로 Spring MVC를 대체 할 수 있습니다.

13.1.2. Features of Spring Web MVC
  • Clear separation of roles - controller, validator, command object, form object, model object, DispatcherServlet, handler mapping, view resolver, 기타 등등. 여러 책임을 각각의 객체로 나눠 놨기 때문에 보다 객체 지향적인 MVC 구현이 가능합니다.
  • Powerful and straightforward configuration - 웹 컨트롤러들 부터 비즈니스 객체까지 모든 객체들을 컨텍스트에 빈으로 등록하여 사용할 수 있습니다.
  • Adaptability, non-intrusiveness - 각각 상황에 맞는 컨트롤러를 골라서 사용할 수 있습니다.
  • Reusable business code - 비즈니스 객체를 커맨드 객체로 재사용할 수 있습니다.
  • Customizable binding and validation - 애플리케이션 차원에서 데이터를 바인딩하고 검증할 수 있습니다.
  • Customizable handler mapping and view resolution - 다양한 방법으로 핸들러 맵핑과 뷰 리졸버를 사용할 수 있습니다.
  • Flexible model transfer - 모델이 name/value 쌍의 맵으로 구성되기 때문에 여러 view간에 이동할 때 사용하기 편합니다.
  • 여러 view 기술들과 연동할 수 있습니다.
  • spring 태그를 제공합니다.
  • form 태그를 제공합니다.
  • session 과 request Scope을 사용할 수 있습니다.

신고

'Spring > Chapter 13' 카테고리의 다른 글

13.4.2. SimpleUrlHandlerMapping  (0) 2007.05.11
13.4.1. BeanNameUrlHandlerMapping  (0) 2007.05.11
13.4. Handler mappings  (0) 2007.05.11
13.3.4. Command controllers  (0) 2007.05.11
13.3.3. The MultiActionController  (2) 2007.05.10
13.3.2. Other simple controllers  (4) 2007.05.10
13.3.1. AbstractController and WebContentGenerator  (0) 2007.05.10
13.3. Controllers  (0) 2007.05.09
13.2. The DispatcherServlet  (0) 2007.05.07
13.1. Introduction  (0) 2007.05.07
13. Web MVC framework  (0) 2007.05.07
top


13. Web MVC framework

Spring/Chapter 13 : 2007.05.07 18:47


13.1. Introduction

Spring MVC는 DispatcherServlet  를 중심으로 만들어졌습니다.
모든 객체가 Command 객체로 사용될 수 있습니다.
View Resolution이 정말 유연하다.

13.2. The DispatcherServlet

Spring MVC 프레임워크도 다른 request 중심의 웹 MVC 프레임워크와 마찬가지로 중앙 서브릿에서 요청(request)을 디스패칭하여 웹 애플리케이션의 다른 기능들을 제공합니다.

13.3. Controllers

MVC에서 "C"에 해당하며 Service 인터페이스를 사용하여 애플리케이션의 기능을 제공합니다. ModelAdnView 객체와 더불어 Spring MVC를 구성하는 기본 요소 입니다.

13.4. Handler mappings

Handler mapping을 사용하여 웹에서 들어온 요청을 처리할 적당한 핸들러(컨트롤러)로 매핑 시킵니다.

13.5. Views and resolving them

컨트롤러에서 요청을 처리한 뒤 ModelAndView 객체에 넘기는 View에 대한 정보를 풀어제낄 녀석과 VIew에 대해 살펴봅니다.

13.6. Using locales

DispatcherServlet 을 사용하여 국제화를 위해 사용자의 Locale을 읽을 수 있습니다.

13.7. Using themes

웹에 특정 테마를 적용하고 싶다면 리소스 파일과 <spring:theme/> 태그를 사용 할 수 있습니다.

13.8. Spring's multipart (fileupload) support

파일 업로드 기능을 지웝합니다.

13.9. Using Spring's form tag library

Spring의 form 태그 사용법

13.10. Handling exceptions

웹에서 요청에서 에외가 발생했을 때 그것을 처리할 핸들러를 지정할 수 있습니다.

13.11. Convention over configuration

네이밍 규약만 잘 지킨다면 상당량의 설정 내용을 줄일 수 있습니다. Spring에서 지원하는 CoC를 설명합니다.

13.12. Further Resources

Spring 사이트에 있는 Spring MVC Step-by-Step
Expert Spring Web MVC and WebFlow
신고

'Spring > Chapter 13' 카테고리의 다른 글

13.4.2. SimpleUrlHandlerMapping  (0) 2007.05.11
13.4.1. BeanNameUrlHandlerMapping  (0) 2007.05.11
13.4. Handler mappings  (0) 2007.05.11
13.3.4. Command controllers  (0) 2007.05.11
13.3.3. The MultiActionController  (2) 2007.05.10
13.3.2. Other simple controllers  (4) 2007.05.10
13.3.1. AbstractController and WebContentGenerator  (0) 2007.05.10
13.3. Controllers  (0) 2007.05.09
13.2. The DispatcherServlet  (0) 2007.05.07
13.1. Introduction  (0) 2007.05.07
13. Web MVC framework  (0) 2007.05.07
top







티스토리 툴바