Spring 에서 @PathVariable 사용하여 값을 넘겨받을때 값에 . 가 포함되어 있으면 .포함하여 그뒤가 잘려서 들어온다.



@RequestMapping(value = "/user/email/{email}", method=RequestMethod.GET)


위와같은 형식일때 아래와 같이 바꿔주면 제대로 들어온다.



@RequestMapping(value = "user/email/{email:.+}", method = RequestMethod.GET)
public ModelAndView getUserByEmail(@PathVariable("email") String email) {


http://stackoverflow.com/questions/16332092/spring-mvc-pathvariable-with-dot-is-getting-truncated



YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST




http://www.cronmaker.com/


원하는 주기나 시간 선택하고 generate 하면 표현식을 만들어주고, 직접 만든 표현식을 테스트해 볼 수 있는 사이트


그리고 더 멋진건 실행되는 시간들까지 알려준다.



YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST



Velocity를 이용한 뷰 구현


  □ Velocity
    ■ 정의
      - 템플릿 엔진.
    ■ 특징
      - 템플릿 파일을 비교적 쉽게 작성 가능.
      - 자바 객체를 템플릿 파일에서 조작할 수 있기 때문에 뷰를 생성하는데 JSP 만큼 널리 사용.

  □ VelocityViewResolver와 VelocityConfigurer를 이용한 Velocity 연동
    ■ VelocityViewResolver
      - 스프링에서 Velocity를 연동할 때에 사용.
      - Velocity 템플릿 파일을 이용해서 뷰를 생성.
      - VelocityConfigurer를 사용해서 Velocity와 관련된 설정 정보를 입력.
      - VelocityConfigurer에서 설정한 경로에서 템플릿 파일을 읽어와 뷰를 생성.
      - prefix 프로퍼티와 suffix 프로퍼티는 뷰 이름으로부터 템플릿 파일의 경로를 생성할 때 사용.
    ■ VelocityConfigurer
      ○ resourceLoaderPath 프로퍼티
        - 템플릿 파일을 로딩할 경로를 입력.
      ○ velocityProperties 프로퍼티
        - Velocity 설정 정보를 지정.
    ■ 설정
 <bean id="velocityConfigurer"
    class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
    <property name="resourceLoaderPath" value="/WEB-INF/viewvm/" />
    <property name="velocityProperties">
        <props>
            <prop key="input.encoding">EUC-KR</prop>
            <prop key="output.encoding">EUC-KR</prop>
        </props>
    </property>
 </bean>

 <bean id="viewResolver"
    class="org.springframework.web.serlvet.view.velocity.VelocityResolver"
    p:suffix=".vm" p:contentType="text/html; charset="EUC-KR" />
         - 컨트롤러가 리턴한 뷰 이름이 "hello"라면 실제 사용되는 템플릿 파일은 "/WEB-INF/viewvm/hello.vm"이 됨.
    ■ 템플릿 파일
      - 템플릿 파일에서는 ModelAndView 객체에 저장된 모델 정보를 사용 가능.
      ○ 컨트롤러
 @Override
 protected ModelAndView handleRequestInternal(HttpServletRequest request, 
    HttpServletResponse response) throws Exception {

    ModelAndView mav = new ModelAndView();
    mav.setViewName("hello");
    mav.addObject("greeting", getGreeting());
    mav.addObject("me", me);

    return mav;
 }
      ○ 템플릿 파일
 <html>
 
 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>인사</title>
 </head>
 
 <body>
    전 ${me}입니다. ${greeting}
 </body>

 </html>
    ■ Velocity Tools의 NumberTool과 DateTool 설정
      - Veloctiy는 템플릿 파일에서 유용하게 사용할 수 있는 기능인 다양한 툴을 제공하는 Velocity Tools를 제공.
      - 숫자와 날짜를 형식에 맞게 출력해주는 NumberTool과 DateTool을 제공.
      ○ VelocityViewResolver에서 제공하는 프로퍼티
        - dateToolAttribute : DateTool에 접근할 때 사용할 변수명을 지정.
        - numberToolAttribute : NumberTool에 접근할 때 사용할 변수명을 지정.
      ○ 설정
 <bean id="viewResolver"
    class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"
    p:suffix=".vm" p:contentType="text/html; charset=EUC-KR"
    p:dateToolAttribute="dateTool" p:numberToolAttribute="numberTool" />
      ○ 사용 예
 <html>

 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>#springMessage("title.currentTime")</title>
 </head>

 <body>
    #springMessage("lagel.currentTime")
    :$dateTool.format("yyyy-MM-dd HH:mm:ss". $time)
 </body>

 </html>
    ■ request 및 session 속성 템플릿 파일에서 사용하기
      ○ request 및 session 속성을 템플릿에 전달하기 위한 VelocityViewResolver 프로퍼티
        - exposeRequestAttributes : 프로퍼티 값을 true 로 지정. (기본값 : false)
        - exposeSessionAttributes : 프로퍼티 값을 true 로 지정. (기본값 : false)
      ○ 설정
 <bean id="viewResolver"
    class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"
    p:suffix=".vm" p:contentType="text/html; charset=EUC-KR"
    p:dateToolAttribute="dateTool" p:numberToolAttribute="numberTool"
    p:exposeRequestAttributes="true" p:exposeSessionAttributes="true" />

  □ 스프링이 제공하는 Velocity 매크로
    ■ 설정
      - 입력 폼을 위한 HTML 태그와 에러 메시지 등을 생성할 때 매크로를 유용하게 사용.
      - exposeSpringMacroHelpers 프로퍼티의 값을 true로 지정. (스프링 2.5의 경우는 기본 값이 true)
 <bean id="viewResolver"
    class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"
    ...
    p:exposeRequestAttribute="true" p:exposeSessionAttributes="true"
    p:exposeSpringMacroHelpers="true" />
    ■ 메시지 출력을 위한 #springMessage 매크로와 #spring MessageText 매크로
      - 스프링의 MessageSource로부터 메시지를 읽어와 출력할 때 사용.
      ○ 정의
        ● springMessage(code)
          - 코드에 해당하는 메시지를 출력.
          - 메시지가 존재하지 않을 경우 예외가 발생.
        ● springMessageText(code text)
          - 코드에 해당하는 메시지를 출력.
          - 메시지가 존재하지 않을 경우 text를 출력.
      ○ 사용 예
 <p>
    <label for="id">#springMessage("login.form.id")</label>
    #springFormInput("login.id" "")
    #springShowErrors("<br/>" "")
    #springMessageText("login.form.id.help". "도움말이 없습니다.")
 </p>
         - #springMessage 매크로는 login.form.id 메시지 코드에 해당하는 메시지를 출력.
         - #springMessageText 매크로는 login.form.id.help 메시지 코드에 해당하는 메시지를 출력. 해당 메시지가 존재하지 않으면
           "도움말이 없습니다"를 대신 출력.
    ■ 커맨드 객체 연동을 위한 #springBind 매크로와 #springBindEscaped 매크로
      ○ #springBind 매크로
        - 커맨드 객체와 관련된 BindStatus 정보를 설정.
        - 커맨드 객체와 관련된 경로를 설정하고 관련 BindStatus 정보는 status 변수를 통햇 접근 가능.
      ○ #springBind 매크로 사용 예
 <p>
    <label for="id">#springMessage("login.form.id")</label>
    #springBind("login.id")
    <input type="text" name="${status.expression}" id="${status.expression}"
        value="$!status.value" />
    #springShowErrors("<br/>" "")
 </p>
         - login 커맨드 객체의 id 프로퍼티를 #springBind 매크로를 사용해서 바인딩.
         - id 프로퍼티와 관련된 BindStatus 객체는 status 변수를 통해서 접근 가능.
         - status.expression은 "id"를 출력.
         - status.value는 login 커맨드 객체의 id 프로퍼티의 값을 출력.
      ○ status 변수
        ● status.expression
          - BindStatus 객체와 연관된 커맨드 객체의 경로를 출력.
        ● status.value
          - 커맨드 객체와 관련된 값을 출력.
          - defaultHtmlEscape 컨텍스트 파라미터의 값에 따라 HTML 특수 문자 처리 여부를 결정.
      ○ #springBindEscaped 매크로
        - HTML 특수 문자 처리 여부를 직접 명시.
 <p>
    <label for="id">#springMessage("login.form.id")</label>
    #springBindEscaped("login.id" false)
    <input type="text" name="${status.expression}" id="${status.expression}"
        value="$!status.value" />
    #springShowErrors("<br/>" "")
 </p>
         - springBindEscaped 매크로의 두 번째 파라미터는 특수 문자를 치환할지의 여부를 설정. 
         - false 이므로 특수 문자를 변환하지 않도록 설정.
    ■ <input> 태그를 위한 매크로
      ○ #springFormInput 매크로
        - 커맨드 객체와 관련된 <input> 태그를 손쉽게 출력.
      ○ #springFormInput 매크로 정의
 #springFormInput($path $attributes)
        ● $path
          - <input> 태그를 생성할 때 사용할 커맨드 객체의 경로.
        ● $attributes
          - <input> 태그에 삽입할 HTML 속성 설정.
      ○ 사용 예
 <label for="name">이름</label>
 #springFormInput("memberInfo.name" "class="input")
 #springShowErrors("<br/>" "")
         - #springFormInput 매크로는 memberInfo 커맨드 객체의 name 프로퍼티와 관련된 <input> 태그를 생성.
      ○ hidden 타입의 <input> 태그나 password 타입의 <input> 태그 생성
        ● #springFormPasswordInput($path $attributes)
          - password 타입의 <input> 태그를 생성.
          - 사용 방법은 #springFormInput 매크로와 동일.
        ● #springFormHiddenInput($path $attributes)
          - hidden 타입의 <input> 태그를 생성.
          - 사용 방법은 #springFormInput 매크로와 동일.
      ○ #springBind 매크로를 사용하여 커맨드 객체와 관련된 BindStatus 정보 설정
        - 내부적으로 #springBind 매크로를 사용해서 커맨드 객체와 관련된 BindStatus 정보에 접근.
 #macro(springFormInput $path $attributes)
    #springBind($path)
    <input type="text" id="${status.expression}" name="${status.expression}"
        value="$!status.value" ${attributes}#springCloseTag()
 #end
         - 폼과 관련된 모든 매크로는 위 코드와 같이  #springBind 매크로를 이용해서 커맨드 객체와 관련된 BindStatus 정보를 설정.
    ■ <select> 태그를 위한 매크로
      ○ <select> 태그와 관련한 매크로
        ● #springFormSingleSelect($path $options $attributes)
          - 한 개의 옵션을 선택할 수 있는 <select> 태그를 생성.
          - $options : <option> 태그를 생성할 때 사용할 Map 객체를 지정.
          - $attributes : HTML 태그의 속성 설정을 입력.
        ● #springFormMultiSelect($path $options $attributes)
          - 다중 선택이 가능한 <select> 태그를 생성.
          - $options : <option> 태그를 생성할 때 사용할 Map 객체를 지정.
          - $attributes : HTML 태그의 속성 설정을 입력.
      ○ 사용 예
 Map<String, String> jobCodes = new HashMap<String, String>();
 jobCodes.put("1", "개발자");
 jobCodes.put("2", "UI 개발자");
 jobCodes.put("3", "웹 디자이너");
 jobCodes.put("4", "기획자");

 ModelAndView mav = new ModelAndView();
 mav.addObject("jobCodes", jobCodes);
 <label for="jobCode">직업</label>
 #spriingFormSingleSelect("memberInfo.jobCode" $jobCodes "")
 #springShowErrors("<br/>" "")
      ○ #springFormSingleSelect 매크로
        - $options에 전달받은 Map 객체의 키를 <option> 태그의 value 속성의 값으로 사용.
        - Map 객체의 값을 <option> 태그의 텍스트로 사용.
      ○ List 객체를 이용해서 <option> 태그 생성
        - #springBind 매크로를 이용해서 직접 <select> 태그와 <option> 태그를 생성.
 #springBind("login.loginType")
 <select id="${status.expression}" name="${status.expression}">
    #foreach($option in $loginTypes)
        <option value="${option}"
        #if("$!status.value" == "$option")
            selected="selected"
        #end
        $option</option>
    #end
 </select>
    ■ checkbox 타입 <input> 태그를 위한 매크로
      ○ checkbox 타입을 위한 <input> 태그 생성 매크로
        ● #springFormCheckboxes($path $options $separator $attributes)
          - $options : checkbox 타입의 <input> 태그를 생성할 때 사용할 Map 객체를 전달 받음.
          - $separator : 각각의 선택 항목을 구분하기 위한 구분자를 입력
      ○ 사용 예
 Map<String, String> favoritesOsNames = new HashMap<String, String>();
 favoritesOsNames.put("WIN2000", "윈도우2000");
 favoritesOsNames.put("WINXP", "윈도우XP");
 favoritesOsNames.put("VISTA", "비스타");
 favoritesOsNames.put("UBUNTU", "우분투");
 favoritesOsNames.put("MAC", "맥");
 
 referenceData.put("favoritesOsNames", favoritesOsNames);
 <label for="favorites">선호 OS</label>
 #springFormCheckboxes("memberInfo.favorites" $favoritesOsNames " | " "")
 #springShowErrors("<br/>" "")
    ■ radio 타입 <input> 태그를 위한 매크로
      ○ radio 타입의 <input> 태그 생성 매크로
        ● #springFormRadioButtons($path $options $separator $attributes)
          - 사용 방법은 #springFormCheckboxes 매크로와 동일.
      ○ 사용 예
 <p>
    <label for="tool">주로 사용하는 개발툴</label>
    #springFormRadioButtons("memberInfo.tool" $tools "" "")
 </p>
    ■ <textarea> 태그를 위한 매크로
      ○ <textarea> 태그 생성 매크로
        ● #springFormTextarea($path $attributes)
      ○ 사용 예
 <p>
    <label for="etc">기타</label>
    #springFormTextarea("memberInfo.etc" "cols='20' rows='3'")
 </p>
    ■ 에러 메시지 출력을 위한 #springShowErrors 매크로
      ○ #springShowErrors 매크로
        - 커맨드 객체와 관련된 에러 메시지를 출력할 때 사용.
      ○ 정의
        ● #springShowErrors($separator $class/style)
          - #springBind/#springBindEscaped 매크로로 바인딩 도니 BindStatus와 관련된 에러 메시지들을 출력.
          - $separator : 각 에러 메시지를 구분할 때 출력되는 값.
          - $class/style : 각 에러 메시지를 위한 CSS 관련 정보를 설정할 때 사용.
      ○ 컨트롤러에서 생성한 에러 메시지 출력
 // 커맨드 객체와 관련된 에러 정보를 추가.
 errors.reject("invalidldOrPassword", new Object[] {loginCommand.getId()}, null);
 // 에러 메시지 출력
 #springBind("login")
 #springShowErrors("<br>" "")
      ○ 특정 프로퍼티와 관련된 에러 메시지 출력
        - #springBind 매크로를 사용하거나 폼 관련 매크로를 사용.
 <p>
    <label for="id">#springMessage("login.form.id")</label>
    #springBind("login.id")
    <input type="text" name="${status.expression}" id="${status.expression}"
        value="$!status.value" />
    #springShowErrors("<br/>" "")
 </p>
 <p>
    <label for="password">#springMessage("login.form.password")</label>
    #springFormPasswordInput("login.password" "")
    #springShowErrors("<br/>" "")
 </p>
        - 폼 입력을 위한 매크로는 #springBind 매크로를 사용하기 때문에 폼 관련 매크로 사용한 뒤에는 #springShowErrors 매크로를
          사용해서 입력 폼과 관련된 에러 메시지를 출력.
      ○ #springShowErros 매크로의 두 번째 파라미터($class/style) 값 처리
        ● 파라미터 값이 ""로 지정
          - 에러 메시지를 <b> 태그를 사용해서 강조.
 <b> 잘못된 ID나 암호를 입력하셨습니다. 입력한 ID는 124입니다. </b>
        ● CSS 관련 속성을 사용하여 에러 메시지 출력
          - CSS 관련 정보 입력.
          - ""이 아닐 경우 : <span> 태그를 이용해서 에러 메시지를 감싼다.
          - ":"로 시작할 경우 : <span>의 style 속성의 값을 두 번째 파라미터의 값으로 설정.
 #springFormInput("memberInfo.userId" "")
 #springShowErrors("<br/>" ":font-size:15pt;")
 // 에러 메시지는 두 번째 파라미터로 전달받은 값을 style 속성의 값으로 사용.
 <span style=":font-size:15pt; ">필수 항목입니다. </span>
          - ":"로 시작하지 않을 경우 : class 속성의 값을 두 번째 파라미터 값으로 설정.
 #springFormInput("memberInfo.name" "class='input'")
 #springShowErrors("<br/>" "error")
 // 에러 메시지는 두 번째 파라미터로 전달받은 값을 class 속성의 값으로 사용.
 <span class="error">필수 항목입니다. </span>
         
  □ VelocityLayoutViewResolver를 이용한 Velocity 레이아웃 템플릿 사용
    ■ VelocityLayoutServlet
      - Velocity Tools가 제공.
      - Velocity에서 동일한 레이아웃을 여러 페이지에 적용할 수 있도록 도와줌. (Tiles와 비슷)
      - 여러 Veloticy 템플릿 파일에서 레이아웃 처리를 위해 중복된 HTML 코드를 작성하지 않아도 됨.
    ■ VelocityLayoutViewResolver
      - VelocityLayoutServlet과 동일하게 하나의 레이아웃을 여러 템플릿 파일에 적용.
    ■ VelocityLayoutViewResolver를 이용한 레이아웃 템플릿 적용
      - 결과 화면을 생성해주는 View 클래스로 VelocityLayoutView 객체를 생성.
      - VelocityLayoutViewResolver를 ViewResolver로 사용하도록 설정.
      ○ 설정
 <bean id="velocityConfigurer"
    class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
    <property name="resourceLoaderPath" value="/WEB-INF/viewvmlayout/" />
    <property name="velocityProperties">
        ...
    </property>
 </bean>

 <bean id="viewResolver"
    class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver"
    p:layoutUrl="/template/layout.vm" 
    p:suffix=".vm" p:contentType="text/html; charset=EUC-KR" ... />
         - prefix나 suffix 등의 프로퍼티는 VelocityViewResolver와 동일.
         - layoutUrl 프로퍼티를 사용하여 레이아웃으로 사용될 Velocity 템플릿 파일을 지정.
      ○ 응답화면 생성
        - VelocityViewLayout 객체는 2단계 과정을 거쳐서 응답 화면 생성.
 1) 컨트롤러의 처리 결과를 보여 줄 템플릿 파일을 찾은 뒤, 템플릿 파일로부터 결과 화면을 생성. 이때 생성된 
     결과 화면을 screen_content 변수에 저장.
 2) layoutUrl 프로퍼티로 지정한 레이아웃 템플릿 파일을 파싱하여 결과 화면을 생성. 이때 레이아웃 템플릿 파일
     은 $screen_content 변수를 사용하여 1단계에서 생성한 결과 화면을 내부에 포함 시킴.

        - /greeting/hello.htm 요청을 처리한 뒤 그 결과를 /hello.vm 템플릿 파일을 통해서 출력할 경우 /hello.vm을 통해서 생성된 결과

          화면이 레이아웃으로 지정한 /template/layout.vm 템플릿 파일의 특정 영역에 삽입.
          (layout.vm이 포함하고 있는 레이아웃이 hello.vm의 출력 결과에 적용되는 것.)

    ■ Velocity 레이아웃 파일 생성
      ○ 레이아웃으로 사용될 Velocity 템플릿 파일과 일반 Velocity 템플릿 파일의 차이점
        - 처리 결과로 생성된 결과를 포함하기 위한 $screen_content 변수 사용.
 <html>
 
 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>제목</title>
 </head>

 <body>
    #parse("/template/header.vm")
    <hr />
    $screen_content
    <hr />
    #parse("/template/footer.vm")
 </body>

 </html>
      ○ 특징
        - 다수의 요청에 대해서 동일한 레이아웃 템플릿 파일이 사용되기 때문에 모든 페이지가 동일한 레이아웃을 갖게 됨.
        - 각 요청의 처리 결과를 생성하는 Velocity 템플릿의 출력 결과는 $screen_content 변수에 위치.
        - Velocity의 #parse나 #include를 사용하면 다수의 레이아웃 템플릿 파일에서 사용되는 부분을 재사용.
      ○ 사용 예
        - 왼쪽 메뉴가 추가된 레이아웃.
 <html>

 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>제목</title>
 </head>

 <body>
    #parse("/template/header.vm")
    <hr />
    <div id="left">#parse("/common/left_menu.vm")</div>
    <div id="content" class="content_side">
        $screen_content
    </div>
    <hr />
    #parse("/templat/footer.vm")
 </body>
 </html>
         - #parse를 사용하여 head.vm이나 top_logo.vm 등의 내용을 재사용.
    ■ 레이아웃 커스터마이징
      ○ 예
        - /a.htm 요청과 /b.htm 요청을 처리 결과를 각각 a.vm과 b.vm을 통해 생성.
        - 공통으로 사용되는 레이아웃으로 layout.vm을 사용.
        - layout.vm은 a.vm이나 b.vm에서 지정한 변수 사용 가능.
 /* a.vm 파일의 내용 */
 #set($htmlTitleTail = '카페')
 ...
 #foreach ($content in $contents)
 ...$content.title ...
 #end
 ...
 /* layout.vm의 내용 */
 <html>
    <title>세상을 즐겁게 변화시키는 DAUM
    #if($htmlTitleTail) : $htmlTitleTail #end</title>
    ...
    <body>
    ${screen_content}
    #parse("/common/bottom.vm")
 </html>   
         - a.vm은 $htmlTitleTail 변수의 값을 지정.
         - layout.vm은 $htmlTitleTail 변수가 존재할 경우 해당 값을 출력하는 코드를 갖고 있음.
         - a.vm이 먼저 파싱된 뒤 layout.vm이 파싱되고, 추가적으로 a.vm에서 정의한 변수를 layout.vm에서 사용할 수 있음.
        ● /a.htm의 요청 결과 HTML 코드
 <html>
    <title>세상을 즐겁게 변화시키는 DAUM : 카페 </title>
    ...
    <body>
    ...
    글제목1
    글제목2
    ...
      ○ 레이아웃의 일부 변경
        - 변수를 전달할 수 있는 기능을 사용하면 레이아웃의 일부 변경 가능.
        ● 레이아웃 템플릿 파일
 #if($headVm)
    #parse($headVm)
 #else
    #parse("/templat/head.vm")
 #end
 ...
         - $headVm 변수가 존재할 경우 변수에 해당하는 vm 파일을 파싱해서 포함.
         - $headVm 변수가 존재하지 않을 경우 "/template/head.vm"을 파싱해서 포함.
        ● /a.htm의 결과가 /template/head_wide.vm을 헤드로 사용
          - /a.htm의 처리 결과를 생성하는 a.vm 파일에서 $headVm 변수 값으로 '/template/head_wide.vm'을 지정.
 #set ($headVm = '/template/head_wide.vm')
 ...
      ○ 레이아웃 템플릿 자체 변경
        - $layout 변수에 레이아웃으로 사용할 템플릿 파일을 지정.
 #set($layout = "/template/layout_index.vm")
 ...

      ○ VelocityLayoutViewResolver 특징
        - Tiles나 Sitemesh 처럼 설정 파일을 사용하여 레이아웃을 관리할 수는 없지만, 레이아웃을 관리하는데 있어서 필요한 부분적인

           레이아웃의 변경, 전체 레이아웃의 변경과 같은 기능을 사용.

출처 : 
http://blog.naver.com/PostView.nhn?blogId=chocolleto&logNo=30087127522 

YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST
  1. 꼬렙 2012.03.06 11:48 신고  댓글주소  수정/삭제  댓글쓰기

    이건 또 뭐고 -_-;;;
    김주임 희안한거 마이 하는구나





nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appProcess' defined in ServletContext resource
[/WEB-INF/Appdi-servlet.xml]: Cannot resolve reference to bean 'SimpleJdbcTemplate' while setting bean property 'template';

nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'SimpleJdbcTemplate' defined in ServletContext resource

[/WEB-INF/Appdi-servlet.xml]: Cannot resolve reference to bean 'DataSource' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DataSource' defined in ServletContext resource

[/WEB-INF/Appdi-servlet.xml]: Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool/KeyedObjectPoolFactory

 
Spring 에서 mysql 로 JDBC 구현할 때, 저딴 에러가 나면 그냥 파일하나 lib 에 넣어주면된다...ㅠㅠ;

ㅅㅂ...내 2시간......

 

YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST
  1. Cheap Moncler vests for women 2015.01.01 16:07  댓글주소  수정/삭제  댓글쓰기

    이용약관위배로 관리자 삭제된 댓글입니다.

  2. New Era 59FIFTY Hats Wholesale Free shipping 2015.01.09 16:46  댓글주소  수정/삭제  댓글쓰기

    이용약관위배로 관리자 삭제된 댓글입니다.

  3. Wholesale New Era Caps,Cheap Snapback Hats/Caps 2015.01.09 16:49  댓글주소  수정/삭제  댓글쓰기

    이용약관위배로 관리자 삭제된 댓글입니다.

  4. louboutin homme 2015.01.17 10:48  댓글주소  수정/삭제  댓글쓰기

    이용약관위배로 관리자 삭제된 댓글입니다.

  5. louboutin pas cher 2015.01.20 04:23  댓글주소  수정/삭제  댓글쓰기

    이용약관위배로 관리자 삭제된 댓글입니다.

  6. giubbotti peuterey 2015 2015.01.20 06:35  댓글주소  수정/삭제  댓글쓰기

    이용약관위배로 관리자 삭제된 댓글입니다.

  7. hogan scarpe 2015.01.20 08:42  댓글주소  수정/삭제  댓글쓰기

    이용약관위배로 관리자 삭제된 댓글입니다.

  8. anello tiffany 2015.01.21 07:19  댓글주소  수정/삭제  댓글쓰기

    이용약관위배로 관리자 삭제된 댓글입니다.





SimpleJdbcTemplate 클래스는

JdbcTemplate 과 NamedParameterJdbcTemplate 을 합쳐 놓은 템플릿 클래스로서

이름 기반의 파라미터 설정인덱스 기반의 파라미터 설정을 모두 지원한다.

이름 기반의 파라미터를 설정할 때에는 Map과 SqlParameterSource 두 가지 방법을 모두 사용할 수 있다.

SimpleJdbcTemplate 클래스가 제공하는 주요메소드는 아래와 같다. 



Method Summary

<T> List<T> 
query(String sql, RowMapper<T> rm, Map<String,?> args)
<T> List<T>
query(String sql, RowMapper<T> rm, Object... args) 
<T> List<T>
query(String sql, RowMapper<T> rm, SqlParameterSource args) 




int queryForInt(String sql, Object... args) 
int queryForInt(String sql, SqlParameterSource args) 



List<Map<String,Object>> queryForList(String sql, Object... args)
List<Map<String,Object>> queryForList(String sql, SqlParameterSource args) 



<T> T
queryForObject(String sql, RowMapper<T> rm, Object... args) 
<T> T
queryForObject(String sql, RowMapper<T> rm, SqlParameterSource args)  



int update(String sql, Object... args)
int update(String sql, SqlParameterSource args) 



이렇게 받은 template을 처리해야될 방법에 따라 잘 만들어진 메소드를 고르기만 하면 된다.

가장 기본인 DB 에서 모든 글을 긁어온다음 list 를 만들어서 보여주는 걸 해보자.
나는  List query(String sql, RowMapper<T> rm, Object... args) 이놈을 골랐다!

그럼이제 리스트 를 보여주기위한 작업을 해보자.


1.  servlet.xml 에 SimpleJdbcTemplate 을 등록한다. (http://winmargo.tistory.com/116 참고)


2. 처리를 수행하는 구현클래스에서 SimpleJdbcTemplate 을 이용해서 Statement 작업을 구현하면 끝이다.
  


구현클래스를 보자
     private SimpleJdbcTemplate template = null;
	
   
	
	
	//모든글을 몽땅 가져온다.
	@Override
	public List getArticles(int index) {
		
						
		sql =  "SELECT * FROM (SELECT ROWNUM rnum,A.* FROM " +
				"(SELECT * FROM margo ORDER BY article_num DESC) A ) "
				+ "WHERE rnum BETWEEN ? AND ?";
	
					
			
		return template.query( sql, 
				
				   				   new ItemBeanRowMapper(),
								   new Object[]{ index, (index + 10)});
		
	}
	
 

코드를 보면 17 라인에 return 값에 simpleJdbcTemplate을 줬다. 리턴값이 List


첫 번째 인자에 sql쿼리를 넣고,

두번째에 3라인에 선언한 ItemBeanRowMapper() 를 넣어주고 있다.(아래에서 자세히)

세 번째 인자에는 쿼리문 안에 있는 '?' 에 대응되어 들어갈 값 2개가 있다. ? 순서와 개수에 맞게 넣어주면 된다.(이것이 인덱스 방식이다)
  
  - 쿼리에 값을 넣는 방법은 두가지가 있는데, 인덱스 파라미터 방식과, 네임드 파라미터(이름 기반) 방식이 있다.
     
     ? 에 순서대로 대입하는 방식은 Index 기반 파라미터 방식이고,
     
      넣어줄 값을 들고있는 맵이나, 빈클래스의 변수을 ':' 콜론과 같이 쓰면 값이 들어가는데
     이 방식이 이름 기반의 파라미터 방식이다.  




기본적인 동작 방식은 template 이 sql쿼리문에 값을 넣고, Statement 처리를 한후

19라인에 있는 ItemBeanRowMapper()  클래스를 이용해서 ResultSet 을 처리한후

리턴되어오는 어떤 클래스(여기서는 Bean파일이다) 를  List 에 자동으로 담은후

그 List 를 리턴해준다.


여기서 중요한건 19라인에 ItemBeanRowMapper()  클래스 이다.

이 클래스는 위설명과 같이 쿼리수행후 리턴된 다수개의 레코드들을 모은 ResultSet에서

레코드컬럼과, 자바빈 변수를 Mapping 시켜

한 개의 레코드를 하나의 자바빈 으로 만들어서 return 시켜주면

Template 이 자동으로 List 에 담아서 Template 수행후 마지막으로 리턴 시킨다.

ItemBeanRowMapper() 클래스는 RowMapper<T> 를 구현해야한다.


ItemBeanRowMapper 클래스를 보자


package Spring;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

public class ItemBeanRowMapper implements RowMapper {

	
	
	@Override
	public ItemBean mapRow(ResultSet rs, int rowNum) throws SQLException {
		
		ItemBean itemBean = new ItemBean();
		
		String str ="";
				
		itemBean.setArticle_num(rs.getInt("article_num"));
		itemBean.setId(rs.getString("id"));
		itemBean.setTitle(rs.getString("title"));
		itemBean.setCount(rs.getInt("hit"));
		itemBean.setDepth(rs.getInt("depth"));
		itemBean.setWrite_date(rs.getTimestamp("write_date"));
		itemBean.setFileName(rs.getString("filename"));
		
		int cnt = itemBean.getDepth();
		
		while( cnt > 0){
			
			str += "    ";
			cnt--;
		}

		itemBean.setSpace(str);
		
		return itemBean;
	}

}

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
메소드 코드를 대충보면 딱 알수 있을만큼 간단하다.  

mapRow(ResultSet rs, int rowNum)

메소드를 오버라이딩 하면서 인자로  ResultSet 과 정수하나를 주는데

뒤에정수는 레코드 개수이다.

사용할 일이 있을때 사용하면된다.

빈파일에 컬럼을 매핑시킨후, 빈파일을 리턴하면

template 이 자동으로 List 에 쑥쑥 넣는다.


수가지의 방식이 있는데, 일단은 제일 요긴하고 잘쓰일 방법으로 구현해보았다.


다음편에는 다른 여러가지 구현방식을 알아보겠음



YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


1. SELECT 쿼리 예제
// 숫자형을 리턴할때
int countOfActorsNamedJoe = this.jdbcTemplate.queryForInt(
"select count(0) from t_actors where first_name = ?", new Object[]{"Joe"});

// 도메인 객체와 매핑할때
public Collection findAllActors() {
return this.jdbcTemplate.query( "select first_name, surname from t_actor", new ActorMapper());
}
private static final class ActorMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Actor actor = new Actor();
actor.setFirstName(rs.getString("first_name"));
actor.setSurname(rs.getString("surname"));
return actor;
}
}

2. INSERT, UPDATE, DELETE 쿼리 예제
this.jdbcTemplate.update(
"insert into t_actor (first_name, surname) values (?, ?)",
new Object[] {"Leonor", "Watling"});

SQL문만 다를뿐 모두 update 메서드를 사용하면 된다.
또한 간단한 스토어드프로시져도 update메서드를 이용할수 있다.
this.jdbcTemplate.update(
"call SUPPORT.REFRESH_ACTORS_SUMMARY(?)",
new Object[]{Long.valueOf(unionId)});


3.기타
그밖에 DDL 같은 특수한 쿼리를 실행할때는 execute()메서드를 사용하기도 한다.
this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");


출처 : 
http://yunsunghan.tistory.com/239
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST



스프링에서 지원하는 다운로드를 쓰려면 아래와 같이 하시오.!

일단 기본적으로 파일 다운로드 처리하기에 앞서서 알아야 할 사항을 배워보도록 하자.

1. 파일링크를 클릭할때 컨트롤러 클래스에게 파일패스와 파일이름을 던져주고 

2. 받은 컨트롤러 클래스에서 그 파일 패스와 파일이름으로 file 을 만들어서 (DownloadController)

3. 뷰로 전달을 할 것이다. 

4. 그럼 뷰에서 받은 file 정보를 이용해서 실제 파일을 읽어들인 다음 원하는 위치에 쓰는 작업을 한다. (DownloadView)

 

 

일반적인 컨트롤러 클래스에서 작업을 한 후, 뷰 페이지로 결과값을 뿌려주는 것인데

일반적인 뷰페이지는 JSP 페이지였다.

하지만 다운로드에 사용될 뷰는 JSP 가 아니라  클래스 파일이다. 



그렇기 때문에 아래처럼 일반적으로 사용하던 viewResolver 가 처리하는 것이 아니라

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property name="prefix" value="/"/>

<property name="suffix" value=".jsp"/>

<property name="order" value="1"/>

</bean>  






download 만을 처리하는 viewResolver 가 따로 존재해야 한다. 여기에는 id값이 없다...주의할것!!!!!!!!!

<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">

      <property name="order" value="0"/>

</bean>


주의할 점은 위 두 코드에 포함된 프로퍼티를 보면 order 라는 프로퍼티가 있는데

이 프로퍼티는 두개이상 존재하는 viewResolver 를 위해서

우선순위를 매기는 것이다. 만약 우선순위를 명시 하지 않으면 "가장 낮은 우선순위를 갖게 된다."

우선순위는 "0"이 가장 먼저 실행되고, 이후로 매겨지는 순서에 따라 실행된다.


다음 viewResolver가 실행되는 기준은 "null" 이 반환되느냐 가 기준이다. 

그렇기 때문에 널값이 있을수 없는 InternalResourceViewResolver 가 우선순위가 높게 되면,
다른 viewResolver 는 사용되지 않게되는
문제가 있다. (항상 뷰 이름에 매핑이 되는 뷰 객체를 리턴하기 때문)

 그래서 InternalResourceViewResolver 은 우선순위가 가장 낮아야 한다.





그러면 이제 BeanNameViewResolver 를 사용하는 법을 알아 보자


BeanNameViewResolver (파일 다운로드 viewResolver)

"null" 이 반환되지 않는다면, (즉 컨트롤러 클래스에서 리턴되온 뷰페이지 값과 일치하는 빈이 있는 경우)


컨트롤러 클래스에서 리턴되온 뷰페이지 값과 일치하는  빈이 등록되있는 경우는 그 빈에 해당하는 컨트롤러 클래스가

파일 다운로드를 처리하게 된다.  

그렇기 때문에 컨트롤러 클래스에서 viewResolver 로 던져줄 뷰페이지 이름과, 처리할 View 클래스 빈이름이 같아야 한다. 
(이말을 반대로 하자면, 실제 jsp 가 보여져야될 때는 리턴값과, view 빈 이름이 같아서는 절대 안된다.)
 

<bean id="download" class="Spring.DownloadView"/>
    - 이 코드가 다운로드를 처리할 뷰 클래스를 등록하는 것이다.
       저기 id="download" 라고 되있는 부분과, 클래스에서 리턴된 값이 같아야 한다.



그리고 url 을 처리할 컨트롤러 클래스도 등록되야되겠지.

<bean id="down" class="Spring.DownloadController"/>




여기 까지가 좀 복잡하지만 servlet.xml 파일을 설정하는 부분이다. 
하나하나 천천히 다시 읽어보면 이해가 될 것이다.






이제 처음부터 하나씩 따라가보자.


파일 이름에 링크를 걸어서 컨트롤러 클래스로 넘기는 부분부터 시작

<a href="/Spring_margo/download.do?path=${path }&fileName=${itemBean.fileName }" >       ${itemBean.fileName }      </a>

download.do 로 파일네임과 패스를 넘기게 되어있다. 







그럼 저 url 을 처리하는 컨트롤 클래스는 아래와 같다.
<bean id="down" class="Spring.DownloadController"/>
@Controller
public class DownloadController implements ApplicationContextAware{

	private WebApplicationContext context = null;
	
	@RequestMapping("download.do")
	public ModelAndView download(@RequestParam("path")String path, 
                                  @RequestParam("fileName")String fileName){
		
		String fullPath = path + "\\" + fileName;
		
		File file = new File(fullPath);
		
		return new ModelAndView("download", "downloadFile", file);
	}

	@Override
	public void setApplicationContext(ApplicationContext arg0)
			throws BeansException {
		// TODO Auto-generated method stub
		
		this.context = (WebApplicationContext)arg0;
		
	}
	
}

@RequestMapping("download.do") 어노테이션으로 지정해준것처럼
download.do 가 들어오면 저 메소드가 동작한다.
링크에서 준것처럼 패스와 파일네임을 받아서

파일에 조합해서 쓰고 "download" 뷰페이지로 파일을 "downloadFile"이름으로 삽입하고 리턴시킨다.

그러면 <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">

저 viewResolver 가 먼저 리턴을 처리하려 할 것이다.

"download"로 등록된 빈이 있는지 찾아 보는데 우리는 아까 "download"로 뷰클래스를 등록시켜 놓았다. 
<bean id="download" class="Spring.DownloadView"/>

이제 DownloadView.java 클래스가 뷰페이지로 동작할 것이다.
뷰페이지에서는 map 에 등록된 파일을 이용해서 encoding 설정과 헤더설정을 해준 후 파일을 지정위치에 쓴다.

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;

public class DownloadView extends AbstractView {


	public void Download(){
		
		setContentType("application/download; utf-8");
		
	}
		
	@Override
	protected void renderMergedOutputModel(Map model,
			HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		
		File file = (File)model.get("downloadFile");
		System.out.println("DownloadView --> file.getPath() : " + file.getPath());
		System.out.println("DownloadView --> file.getName() : " + file.getName());
		
		response.setContentType(getContentType());
		response.setContentLength((int)file.length());
		
		String userAgent = request.getHeader("User-Agent");
		
		boolean ie = userAgent.indexOf("MSIE") > -1;
		
		String fileName = null;
		
		if(ie){
			
			fileName = URLEncoder.encode(file.getName(), "utf-8");
						
		} else {
			
			fileName = new String(file.getName().getBytes("utf-8"));
			
		}// end if;

		
		response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
		
		response.setHeader("Content-Transfer-Encoding", "binary");
		
		OutputStream out = response.getOutputStream();
		
		FileInputStream fis = null;
		
		try {
			
			fis = new FileInputStream(file);
			
			FileCopyUtils.copy(fis, out);
			
			
		} catch(Exception e){
			
			e.printStackTrace();
			
		}finally{
			
			if(fis != null){
				
				try{
					fis.close();
				}catch(Exception e){}
			}
			
		}// try end;
		
		out.flush();
		
	}// render() end;
}


여기까지가 

파일링크를 클릭해서 다운로드를 하는 일련의 과정을 코드로 풀어논 것이다.

복잡해 보이지만, ....복잡하다.......죄송;




열심히 뚝딱뚝닥 거리다보면 위그림처럼 다운로드가 될것이다!!!!!!!!!


YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST
  1. 로스비 2011.08.17 20:05 신고  댓글주소  수정/삭제  댓글쓰기

    저번 처럼 이상하게 건들지도 않은 ListImpl이 오류가 생깁니다.

  2. 메로메로 2012.10.03 18:46 신고  댓글주소  수정/삭제  댓글쓰기

    지나가다가 잘배우고 갑니다. 많은 도움이 되었습니다. 이제 완전 초보인데요.

    이클립스를 세팅중인데요, 보리마고님의 이클립스를 보면 검은바탕까진 저도 설정을 햇는데, 나머지 글씨를 파란색과 형광색으로 하고 싶은데 방법좀 알려주시면 정말 감사하게습니다. ㅠ

    • 보리마고 2012.10.08 17:53 신고  댓글주소  수정/삭제

      이클립스 세팅이 아니라, 티스토리에 포스팅할때 하이라이팅 기능을 써서 코드를 저렇게 보이게 한겁니다. 이클립스는 코드 하이라이트 플러그인이 있으니 여러가지 찾아보셔서 마음에 드시는걸로 하세요 ㅎㅎ

  3. eugene 2014.05.07 12:19 신고  댓글주소  수정/삭제  댓글쓰기

    1.png가 나오는 이유는 무엇인지 궁금합니다
    직접 뷰로 값을 넘겨주는 건가요? 예제대로 하고 있는데 파일네임에 계속 null이 잡히네요

  4. kim 2014.05.30 11:31 신고  댓글주소  수정/삭제  댓글쓰기

    혹시 위 소스를 war 파일로 좀 받을수있나요?

  5. kim 2014.05.30 11:32 신고  댓글주소  수정/삭제  댓글쓰기

    가능하시다면 hg97804@naver.com
    으로 부탁좀 드리겟습니다

  6. Nathan 2015.01.16 10:30 신고  댓글주소  수정/삭제  댓글쓰기

    큰도움이 되었습니다. 감사합니다!

  7. LHN 2015.07.08 16:21 신고  댓글주소  수정/삭제  댓글쓰기

    정말 잘 배워 가요 ㅠ-ㅠ! 감사합니다.

  8. 오늘은진돗개 2015.11.25 15:00 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요.
    궁금한게 있는데요.

    download.do에서 파일정보 데이터를 쿼리로 가져와서 다운받게하려고 하는데 파일 안만들고 가능한가요?
    File file = new File(fullPath);
    return new ModelAndView("download", "downloadFile", file);

    이거 대신 return new ModelAndView("download", "downloadFile", binary); 이런식으로요




가장 기본적으로 파일 업로드를 하려면 

html 문서 안에 <form> 태그에서

<form method="post" enctype="multipart/form-data">
...........
</form> 







Multipart 지원기능을 사용하려면  먼저 multipartResolver 를 스프링 설정 파일에 등록 해주어야 한다.

CommonsMultipartResolver 를 multipartResolver 로 사용하려면, 다음과 같이 

빈 이름을 반드시!!!  "multipartResolver" 로 등록해서 사용하면 된다.
다른이름으로 등록하면 안된다. 그냥 안된다. 절대안된다. 업로드를 포기하라.

<bean id="multipartResolver
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

참고로 프로퍼티들은

maxUploadSize(최대업로드 가능한 바이트크기)
maxInMemorySize(디스크에 임시 파일을 생성하기 전에 메모리에 보관할수있는 최대 바이트 크기)
defaultEncoding(요청을 파싱할 때 사용할 캐릭터 인코딩. 기본값 ISO-8859-1)





이제 컨트롤러 파일에서 업로드가 되는 파일에 접근을 해야하는데, 

빈객체를 이용해서 받는 방법(커맨드 객체), 
@RequestParam 어노테이션을 이용하는 방법,
MultipartHttpServletRequest 를 이용하는 방법,

머 편한 방법을 택하면 된다.

주의 할 점은 <input type="file" name="file" size="50">
폼에서 파일프로퍼티 이름을 "file"로 썼다면, 
업로드될 파일에 접근 프로퍼티도 항상 무조건 네버! "file" 이 되어야 한다.


빈객체를 이용하는 방법은
public class ItemBean {

	MultipartFile file;
	

	public MultipartFile getFile() {
		return file;
	}

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

	
자바빈 파일에 set,get을 등록해주면 자동으로 들어간다. 



다음은 @RequestParam 어노테이션을 이용한 방법
	

	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView process(HttpSession session, ItemBean itemBean,
								@RequestParam("file")MultipartFile file) {



나머지는 귀찮아서....

일단 이렇게 하면 MultipartFile 타입으로 file 에 업로드된 파일이 들어오게된다.


여기까지 했으면 다 끝난거다. 이제 쓰기만 하면 된다.

쓰는법은 하고싶은데로 하면되는데, 

MultipartFile 의 주요 메소드는

 String getName() 파라미터 이름을 구한다. 
 String getOriginalFilename()  업로드 한 파일의 실제!! 이름을 구한다.
 boolean isEmpty()  업로드 한 파일이 존재하지 않는 경우 true를 리턴한다.
 long getSize()  업로드한 파일의 크기를 구한다.
 byte[] getBytes() throws IOException  업로드 한 파일 데이터를 구한다. --> 이걸로 파일 쓰면된다.
 InputStream getInputStream()  InputStrem을 구한다.
 void transferTo(File dest)  업로드 한 파일 데이터를 지정한 파일에 저장한다. --> 요고도 파일쓰는거다.




걍 쉽게 MultipartFile.getBytes() 를 이용해서 쓰는게 편하다.
package Spring;

import java.io.FileOutputStream;

import org.springframework.web.multipart.MultipartFile;

public class FileWriter {

	private FileOutputStream fos;
	
	public void writeFile(MultipartFile file, String path, String fileName){
		
		try{
		
			byte fileData[] = file.getBytes();
			
			fos = new FileOutputStream(path + "\\" + fileName);
			
			fos.write(fileData);
		
		}catch(Exception e){
			
			e.printStackTrace();
			
		}finally{
			
			if(fos != null){
				
				try{
					fos.close();
				}catch(Exception e){}
				
				}
		}// try end;
		
	}// wirteFile() end;
}




업로드한 파일을 특정파일로 저장하고 싶다면 MultipartFile.transferTo() 를 쓰면 편하다.

File file = new File(filePath + fileName);

multipartFile.transferTo(file); 





YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST
  1. 탐구생활 2012.10.16 12:07 신고  댓글주소  수정/삭제  댓글쓰기

    '그냥 안된다. 절대안된다. 업로드를 포기하라.'

    웃겨서 댓글답니다. ㅋㅋㅋ

  2. 휴렛 2014.11.20 10:56 신고  댓글주소  수정/삭제  댓글쓰기

    감사합니다. 덕분에 놓친부분 찾고 갑니다^^

  3. 방문객 2015.01.07 15:25 신고  댓글주소  수정/삭제  댓글쓰기


    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
    설정덕분에 해결하고 지나갑니다 ^^



스프링 MVC의 주요 구성 요소

DispatcherServlet : 클라이언트의 요청을 전달받는다. 컨트롤러에게 클라이언트의 요청을 전달하고,

                            컨트롤러가 리턴한 결과값을 View에 전달하여 알맞은 응답을 생성하도록 한다.

HandlerMapping : 클라이언트의 요청 URL을 어떤 컨트롤러가 처리할지를 결정한다.

Controller(컨트롤러) : 클라이언트의 요청을 처리한 뒤, 그 결과를 DispatcherServlet에 알려준다.
                               스트럿츠의 Action과 동일한 역할을 수행한다.

ModelAndView : 컨트롤러가 처리한 결과 정보 및 뷰 선택에 필요한 정보를 담는다.

ViewResolver : 컨트롤러의 처리 결과를 생성할 뷰를 결정한다.

View(뷰) : 컨트롤러의 처리 결과 화면을 생성한다. JSP나 Velocity템플릿 파일 등을 뷰로 사용한다.




스프링 MVC 구성요소들의 처리흐름


위 그림을 글로 풀어보면

1. 클라이언트 요청이 DispatcherServlet 에 전달된다.

2. DispatcherServlet 은 HandlerMapping 을 사용하여 클라이언트의 요청을 처리할 컨트롤러 객체를 구한다.

3. DispatcherServlet 은 컨트롤러 객체를 이용해서 클라이언트의 요청을 처리한다.

4. 컨트롤러는 클라이언트의 요청 어리 결과 정보를 담은 ModelAndView 객체를 리턴한다.

5. DispatcherServlet 은 ViewResolver 로부터 응답 결과를 생성할 뷰 객체를 구한다.

6. 뷰는 클라이언트에 전송할 응답을 생성한다.



위 과정에서 개발자가 직접 개발해야 할 부분은 클라이언트의 요청을 처리할 컨트롤러와 클라이언트에 응답 결과 화면을 전송할 

JSP 나 Velocity 템플릿 등의 뷰 코드
이다.

나머지, DispatcherServlet 이나 HandlerMapping, ViewResolver 등은 스프링이 기본적으로 제공하는
구현클래스를 사용하게 된다.




위 스프링 MVC 구성요소들과, 처리흐름을 바탕으로 web.xml , dispatcher-servlet.xml, cotroller.java 작성법을 기본적으로
진행해보자.

일단 web.xml 을 설정해야한다.

<servlet>
  
  <servlet-name>dispatcher</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  
  </servlet>
  
  <servlet-mapping>
 
  <servlet-name>dispatcher</servlet-name>
  <url-pattern>*.do</url-pattern>
  
  </servlet-mapping>

  
*.do 로 요청되는 모든 요청은 dispatcher 라는 이름으로 등록된

org.springframework.web.servlet.DispatcherServlet 서블릿이 하겠다고 지정한다.

여기서 주의할점은 dispatcher 라고 쓰겠다고 정했으므로

DispatcherServlet 이 참조해야되는 설정 파일은 WEB-INF/ 에 위치한 [서블릿이름]-servlet.xml 이다. 

그래서 여기서 만들어야될 설정파일 이름은

반드시 dispatcher-servlet.xml 이 되야된다. 앞대가리가 바로 정의한 이름이다.

필요한 자르 파일들은 구현하는 목적에 다르지만, 

현재 예제에 필요하고 향후 잘쓰이게되는 라이브러리 파일은 페이지 아래쪽에 첨부하겠습니다. 





이제 dispatcher-servlet.xml 파일을 작성합니다.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
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-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">
       
<bean id="helloController" class="Spring.HelloController"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>       
</beans>

                 

DispatcherServlet 은 스프링 컨테이너에서 컨트롤러 객체를 검색하기 때문에

스프링 설정 파일에 컨트롤러를 빈으로 등록해 주어야 합니다.

위 코드에서 class="Spring.HelloController" 

Spring 패키지안의 HelloController.java 파일이 요청을 실제 처리하는 코드가 들어있는

컨트롤러 파일입니다. 


그 아래 viewResolver 라고 정의되있는 것은 컨트롤러의 결과값으로 어떤 뷰페이지를 어떻게 보여줄지 

설정하는 구문입니다.

<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>

prefix 는 결과값중 setViewName("결과페이지이름");

으로 담겨오는 결과페이지 이름앞뒤에 붙여서 포워딩 시킬 이름을 완성시키는 겁니다.

저코드에 따르면   "컨테스트주소/결과페이지이름.jsp" 라고 생성되어져서,

포워딩 되게됩니다.







그럼이제 컨트롤러 파일을 작성합니다. 순서상보면 컨트롤러를 먼저 코딩하는게 맞는거같습니다.

 HelloController.java
package Spring;

import java.util.Calendar;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HelloController {

	@RequestMapping("/hello.do")
	public ModelAndView hello(){
		
		ModelAndView mav = new ModelAndView();
		
		mav.setViewName("hello");
		
		mav.addObject("greeting", getGreeting());
		
		
		return mav;
	} //hello() end;
	
	
	
	public String getGreeting(){
		
		int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
		
		if(hour >= 6 && hour <= 10){
			
			return "굿모닝~~~~~~";
			
		} else if(hour >= 12 && hour <= 15){
			
			return "점심 드셨음?";
			
		} else if(hour >= 18 && hour <= 22){
			
			return "굿 밤";
			
		} // end if;
		
		
		return "하이~~~~~~~~~~";
	}
}


컨트롤러를 구현하려면 먼저 @Controller 어노테이션을 클래스에 적용합니다.

그리고 @RequestMapping 어노테이션을 이용해서 클라이언트의 요청을 처리할 메서드를 지정합니다.

9라인의 @Controller 어노테이션은 해당 클래스가 스프링 MVC의 컨트롤러를 구현한 클래스라는 것을 지정합니다.

또한 @RequestMapping("/브라우저요청값") 어노테이션은 값으로 지정한   컨텍스트이후의 요청경로를 처리할 메소드를

지정하는 것입니다. 여기서는 "/hello.do" 라고 지정했는데 이 경우에는 'http://localhost:8080/Spring_BBS/hello.do'

요청을 HelloController.java 의 hello() 메소드가 처리하게됩니다.


15라인에서 ModelAndView 를 생성하고 있는데, 이것은 컨트롤러의 처리결과를 보여줄 뷰와 뷰에서 출력할 모델을

지정할 때 사용됩니다. 사용할 뷰 이름으로 "hello" 를 사용 했고, 모델에 "greeting"이라는 이름으로 String 타입의 값을 추가하였습니다.

뷰이름은 위에서 언급했듯이 prefix 값과 suffix값을 앞뒤로 붙여서, 포워드합니다.



hello.jsp 파일에서 EL 태그로 간단하게 출력할수있습니다. 





아래는 WEB-INF/lib 폴더에 들어가야할 Spring jar 파일들입니다.






  
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST
  1. 초보개발자 2012.07.10 20:03 신고  댓글주소  수정/삭제  댓글쓰기

    이런 유용한 정보에! 코멘트가 없다니요! 감사히 잘 배우고 갑니다~ 즐겨찾기해놓고 공부하러 또 올게요^^ 감사합니다

  2. 오픈 2014.05.29 14:30 신고  댓글주소  수정/삭제  댓글쓰기

    잘보고 많이 배우고 갑니다. 감사합니다.




핵심관심 : Major Concern(예:게시판에 글쓰리, 글 보기, 글 삭제, 글 수정,...)

횡단관심 : Cross-Cutting Concern(예:로깅, 인증, 예외처리,...)

 

기존코드 : 핵심관심과 횡단관심이 결합되어 있는형태

->유지보수 어려움(중복발생, 지저분함, 생산성 저하, 재사용 힘듬, 변화 힘듬)
 

AOP적용코드 : 핵심관심과 횡단관심이 분리 되어 깜끔함


Code : 핵심관심을 구현한 것

Advice : 횡단관심을 구현한 것

Joinpoint : Advice가 Code에 끼어 들 수 있는 순간들

Pointcut : Joinpoint 중에서 실제 Advice가 Code에 끼어드는 순간

Aspect : Advice+Pointcut

weaving : Code에 Aspect를 적용하는 과정


출처 

복사http://blog.naver.com/ooops_jabie/70037939404ooops_jabie

 

[출처] AOP 용어|작성자 ooops_jabie

YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST