Spring MVC & Java1.4 tip

From JCFWiKi

Jump to: navigation, search

그림:check.gif

  • 산출물: Java 1.4에서 Spring MVC 간단하게 사용하기
  • 작성자: 나윤주
  • 최초작성일 : 2008/07/01
  • 최종작성일 : 2008/07/02

Copyright © 2008 Daewoo Information Systems Co., Ltd.

그림:information.gif

  • 이 문서는 Java 1.4환경에서 Spring Web MVC Framework를 간단하게 사용할 수 있는 Tip을 제공한다.

목차

[편집] 설정파일의 간략화

  • Arid와 ControllerClassNameHandlerMapping의 조합으로 Annotation을 사용할 수 없는 Java 1.4 환경에서 번거로울 수 있는 web controller의 설정을 줄이고, Controller 클래스의 수를 줄임으로써 개발의 편이성을 높일 수 있다.
  • 다음은 블로그 예제에 대하여 Java 1.4에서 SpringMVC를 사용하였을 때, arid와 coc를 적용하였을 때, Jave 5.0+에서 annotation을 사용하였을 때를 비교한 것이다.
코드Blog(Original) Blog(arid+coc)Blog(java5.0+ annotation)
blog-servlet.xmlView Resolver bean 등록,
각 Controller-url 맵핑 bean 등록
Arid, mapping handler bean,
view name translator bean 등록
component scan,
view resolver bean 등록
약 30 lines약 20 lines약 15 lines
Controller blog.web.CreateBlogFormController,
blog.web.EditBlogFormController,
blog.web.FindBlogController
blog.web.BlogControllerblog.web.BlogController
MultiActionController,
SimpleFormController 상속
MultiActionController 상속@Controller 지정

그림:forbidden.gif

  • 위 표는 Spring MVC를 이용하여 개발한 블로그의 예제에서 각 경우에 따라 설정파일 및 controller 파일을 최소화 하였을 때를 나타낸 것으로, 프로젝트 구조 및 성격에 따라 내용이 달라질 수 있다.

[편집] Arid

  • <arid:define-bean />
    • 클래스 및 클래스의 멤버변수를 bean으로 등록해주는 역할을 한다.
  • arid 사용하기
    • arid-framework.jar와 aspectjweaver.jar 클래스 파일이 필요하다.
    • beans 정의에 arid를 추가해야 한다.
    • web controller는 xxx-servlet.xml에서 설정한다.
    • controller 클래스 멤버변수의 set 메소드의 작성이 필요하다.
@Autowired == <arid:define-bean /> + setXXX()
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:arid="http://chrisrichardson.net/schema/arid"
    xsi:schemaLocation="http://chrisrichardson.net/schema/arid http://chrisrichardson.net/schema/arid.xsd" >
 
    <!-- auto registration and wiring of beans  -->
    <arid:define-beans package="edu.blog" pattern="*..web.*Controller" autowire="byName"/> 
</beans>
  • 한계
    • Spring MVC annotation 중 @Autowired를 커버할 수 있지만, Controller, RequestMapping 등의 다른 annotation을 대체할 순 없다.

그림:information.gif

[편집] ControllerClassNameHandlerMapping

  • url과 클래스 맵핑의 관계를 자동으로 지정해주는 Handler Mapper이다.
  • Conversion of Configuration(CoC)의 개념이다.
  • ControllerClassNameHandlerMapping을 적용하지 않은 경우 Controller class에 대한 url을 직접 지정해주어야 한다.
<bean name="/findBlogs.do" class="blog.web.FindBlogController">
      <property name="blogService" ref="blogService" />
</bean>
  • ControllerClassNameHandlerMapping을 적용한 경우 Controller class의 이름이 url로 자동 매핑된다.
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<bean class="blog.web.FindBlogController">
      <property name="blogService" ref="blogService"/>
</bean>
  • 한계
    • ControllerClassNameHandlerMapping을 사용하더라도, 각 controller 파일에 대해 bean 등록을 직접 해주어야 한다.
    • 클래스 및 메소드의 이름이 url로 사용되므로, 클래스 및 메소드 이름 결정에 주의해야 한다.
    • Controller의 종류에 따라 url 매핑의 형태가 다르므로, jsp 소스 코드 관리에 주의해야 한다.
      • MultiActionController의 경우 /클래스이름/메소드이름.확장자로 매핑되며, 다른 Controller의 경우 /클래스이름.확장자로 매핑된다.

[편집] Arid + ControllerClassNameHandlerMapping

  • Arid의 자동 bean 등록과 ControllerClassNameHandlerMapping의 url 자동 매핑의 기능을 사용하여 설정파일을 간략하게 사용할 수 있다.
  • Web Controller는 MultiActionController를 상속받아 사용함으로써 Controller 클래스의 수를 줄일 수 있다.

[편집] servlet 설정

  • Arid와 ControllerClassNameHandlerMapping의 설정 만으로 기존의 url-controller class 설정을 모두 생략할 수 있다.
  • InternalResourceViewResolver는 Controller에서 ModelAndView 타입이 아닌 ModelMap 타입으로 반환하더라도 알맞은 View를 선택하여 보여주도록 해준다.
    • stripLeadingSlash 속성은 false로 설정을 해야 requestContext 이후의 정확한 url 매핑이 이루어진다. (stripLeadingSlash의 default value는 true이다.)
    • InternalResourceViewResolver를 사용할 경우 suffix를 지정하기 위해 사용한 InternalResourceViewResolver를 중복으로 사용하지 않아도 된다. (단, 특정 viewClass를 지정하거나 InternalResourceViewResolver에서 필요한 속성을 설정하기 위해서는 지정해준다.)
<!-- blog-servlet.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:arid="http://chrisrichardson.net/schema/arid"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
	         http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
	         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
	         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
	         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
	         http://chrisrichardson.net/schema/arid http://chrisrichardson.net/schema/arid.xsd" >
 
    <!-- auto registration and wiring of beans  -->
    <arid:define-beans package="edu.blog" pattern="*..web.*Controller" autowire="byName"/> 
    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>  
 
    <bean id="viewNameTranslator" class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator">
    	<property name="stripLeadingSlash" value="false"/>
    	<property name="suffix" value=".jsp"/>
    </bean>  
	
    <!-- view & resolver 
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    	<property name="suffix" value=".jsp"/>
    	<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    </bean>
    -->
</beans>

[편집] Web Controller

  • 하나의 controller에서 처리하기 위해 MultiActionController를 사용하고, 메소드 형태의 혼란을 줄이기 위해 같은 형태의 메소드를 사용하였다.
  • 다른 레이어와 연계가 필요한 멤버변수(blogService)는 setXxx 함수로 설정을 해준다.
  • 서블릿에서 InternalResourceViewResolver를 사용하지 않을 경우, 반환형을 ModelAndView로 하여 view 이름을 지정해주어야 한다.
  • deleteBlog()와 같이 직접 view로 반환하지 않는 메소드는 return type이 Map/ModelAndView형태가 아니어도 된다.
    • redirect/forword 키워드로 알맞은 url로 변환해준다.
/* BlogController.java */
/* 패키지 선언 및 import 생략 */
public class BlogController extends MultiActionController {
	private BlogService blogService;
 
	public void setBlogService(BlogService blogService) {
		this.blogService = blogService;
	}
 
	public Map findBlogs(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		Collection blogList = blogService.findBlogs();
		return new ModelMap("blogList", blogList);
	}
	
	public String deleteBlog(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		blogService.deleteBlog(Integer.parseInt((String)request.getParameter("blogId")));	
		return "redirect:findBlogs.do";
	}
  • get 형태의 파라미터는 request.getParameter()로, post 형태의 form 관련 파라미터는 bind() 함수로 설정할 수 있다.
  • SessionAttributes Annotation과 같이 하나의 blog 모델을 유지할 수 없기 때문에, View에서는 Controller에서 넘겨준 모델의 모든 정보를 다시 설정하여 보내주도록 해야한다. (blog 예제 소스 참고)
	public Map createBlog(HttpServletRequest request, 
			HttpServletResponse response) throws Exception {
		Blog blog = new Blog();
		blog.setRegDate(new Date());
		return new ModelMap("blog", blog);
	}
	
	public String addBlog(HttpServletRequest request, 
			HttpServletResponse response) throws Exception {
		Blog blog = new Blog();
		bind(request, blog);
		blogService.createBlog(blog);
		return "redirect:findBlogs.do";
	}
	/* 중간 생략 */
  • MultiActionController로부터 override한 initBinder 함수는 form 관련 속성 값들에 대한 설정이 필요할 때 사용한다.
    • 이 예제에서는 Date Type과 String Type의 변환을 위해 initBind() 메소드를 사용하였다.
	// Override
	protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		CustomDateEditor dateEdit = new CustomDateEditor(df, false);
		binder.registerCustomEditor(Date.class, dateEdit);
	}
	
}

[편집] Spring MVC Blog 예제 다운로드

그림:information.gif

  • 예제 실행을 위해서는 JDK, 이클립스, 톰캣 등의 개발환경이 필요하다. (개인 개발환경 참고)


[편집] 참고자료