IT

web.xml 에서 아래와 같이 수정한다.

<servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:/spring-servlet.xml</param-value>
        </init-param>
        <multipart-config>
            <max-file-size>52428800</max-file-size>
            <max-request-size>52428800</max-request-size>
            <file-size-threshold>0</file-size-threshold>
        </multipart-config>
    </servlet>

 

    <bean id="multipartResolver"     class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
    </bean>
//Controller

Collection<Part> parts = req.getParts();

        for(Part part : parts) {
            System.out.println("Name:");
            System.out.println(part.getName());
            System.out.println("Header: ");
            for(String headerName : part.getHeaderNames()) {
                System.out.println(headerName);
                System.out.println(part.getHeader(headerName));
            }
            System.out.println("Size: ");
            System.out.println(part.getSize());
            part.write(part.getName() + "-down");
        }

 

 

  • 전체다 가져오기: req.getParts()
  • 한개만 가져오기: req.getPart(String name)
  •  

    참고 : http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-multipart-resolver-standard

    Posted by sinpk
    ApplicationContext 또는 BeanFactory 안에서 사용할 때는 bean을 쓰고 싶을 때는 ref bean 태그를 사용한다.
    하지만, 하나의 파일(xml) 안에서만 쓰고 싶을 때는 ref local 태그를 쓴다.

    특정 플랫폼에서 사용될 때, 같은 이름을 주어서 서로 Conflict나 예기치 않은 일이 일어나지 않는 것이 중요하기 때문에..
    하나의 파일에서 처리하는 reference bean이 많을 때는 local을 쓰는 것이 좋다.

     

    Posted by sinpk

    메시지 컨버터의 종류

    사용할 메시지 컨버터는 AnnotationMethodHandlerAdapter 를 통해 등록한다. 일반적으로 하나 이상의 메시지 컨버터를 등록해 두고 요청 타입이나 오브젝트 타입에 따라 선택되게 한다. AnnotationMethodHandlerAdapter 에 등록되는 디폴트 메시지 컨버터는 다음과 같다.

    ByteArrayHttpMessageConverter

    지원하는 오브젝트 타입은 byte[] 이다. 미디어 타입은 모든 것을 다 지원한다. 따라서 @RequestBody 로 전달받을 때는 모든 종류의 HTTP 요청 메시지 본문을 byte 배열로 가져올 수 있다. 반대로 @ResponseBody 로 보낼 때는 콘텐트 타입이 application/octet-stream 으로 설정된다. 컨트롤러가 byte 배열에 담긴 바이너리 정보를 클라이언트에 전송할 필요가 있을 때 외에는 그다지 유용해 보이지 않는다. 바이너리 포맷을 가진 정보를 주고 받아야 하는 시스템이 있다면 활용할 수 있을 것이다.

    StringHttpMessageConverter

    지원하는 오브젝트는 스트링 타입이다. 미디어 타입은 모든 종류를 다 허용한다. 따라서 HTTP 요청의 본문을 그대로 스트링으로 가져올 수 있다. HTTP 가 기본적으로 텍스트 기반의 포맷이므로 가공하지 않은 본문을 직접 받아서 사용하고 싶은 경우라면 유용하게 쓸 수 있다.

    XML 이나 JSON 같은 공개된 형식 외에 직접 정의한 문서 포멧이 있다면 적절한 파서를 붙여서 활용할 수 있도록 문자열로 받는 것이 편리하다. 물론 좀 더 나은 방법은 해당 문서 포멧을 지원하는 HttpMessageConverter 를 직접 개발해서 적용하는 것이다.

    응답의 경우는 콘텐트 타입이 text/plain 으로 전달된다. 단순 문자열로 응답을 보내고 싶을 때는 @ResponseBody 와 함께 스트링 리턴값을 사용하면 된다.

    FormHttpMessageConverter

    미디터 타입이 application/x-www-form-urlencoded 로 정의된 폼 데이터를 주고 받을 때 사용할 수 있다. 오브젝트 타입은 다중 값을 갖는 맵 확장 인터페이스인 MultiValueMap<String, String> 을 지원한다. MultiValueMap 은 맵의 값이 List 타입인 맵으로, 하나의 이름을 가진 여러 개의 파라미터가 사용될 수 있는 HTTP 요청 파라미터를 처리하기에 적당하다. HTTP 요청의 폼 정보는 @ModelAttribute 를 이용해 바인딩하는 것이 훨씬 편리하고 유용하므로, FormHttpMessageConverter 를 @RequestBody 에 사용할 일은 별로 없을 것 같다.

    응답의 경우에도 application/x-www-form-urlencoded 콘텐트 타입을 사용하는 경우는 드물지만 클라이언트가 application/x-www-form-urlencoded 타입의 폼 정보를 선호한다면 이용할 수 있을 것이다.

    SourceHttpMessageConverter

    미디어 타입은 application/xml, application/*+xml, text/xml 세 가지를 지원한다. 오브젝트 타입은 javax.xml.transform.Source 타입인 DOMSource, SAXSource, StreamSource 세 가지를 지원한다. XML 문서를 Source 타입의 오브젝트로 전환하고 싶을 때 유용하게 쓸 수 있다. 최근에는 OXM 기술의 발달로 XML 을 바로 자바오브젝트로 변환하는 경우가 많기 때문에 그다지 많이 쓰이지는 낳겠지만, DOM 이나 SAX 방식의 XML 문서 접근을 선호한다면 이용할 만하다.

    기본적으로 네 가지 종류의 HttpMessageConverter 가 디폴트로 등록되지만, 이 보다는 디폴트로 등록되지 않는 다음 세 가지 HttpMessageConverter 가 실제로 더 유요하다. 이중에서 필요한 메시지 컨버터가 있다면 직접 AnnotationMethodHandlerAdapter 빈의 messageConverters 프로퍼티에 등록하고 사용해야 한다.

    Jaxb2RootElementHttpMessageConverter

    JAXB2의 @XmlRootElement 와 @XmlType 이 붙은 클래스를 이용해서 XML 과 오브젝트 사이의 메시지 변환을 지원한다. 기본적으로 SourceHttpMessageConverter 와 동일한 XML 미디어 타입을 지원한다. 오브젝트는 두 가지 에노테이션 중 하나가 적용됐다면 어떤 타입이든 사용할 수 있다.

    JAXB2의 스키마 컴파일러를 통해 생성된 바인딩용 클래스를 이용해서 손쉽게 XML 과 오브젝트 사이의 변환 기능을 이용할 수 있다. JAXB2에 숙련된 개발자라면 이를 이용해 편리하게 XML 문서 기반의 컨트롤러를 만들 수 있다.

    MarshallingHttpMessageConverter

    스프링의 OXM 추상화의 Marshaller 와 Unmarshaller 를 이용해서 XML 문서와 자바 오브젝트 사이의 변환을 지원해주는 컨버터다. MarshallingHttpMessageConverter 를 빈으로 등록할 때 프로퍼티에 marshaller 와 unmarshaller 를 설정해줘야 한다. 미디어 타입은 다른 XML 기반 메시지 컨버터와 동일하며, 지원 오브젝트는 unmarshaller 의 supports() 메소드를 호출해서 판단한다. OXM 기술을 자유롭게 선택해서 XML 문서 기반의 컨트롤러를 작성하려고 한다면 편리하게 이용할 수 있다. 단, Marshaller 의 개수만큼 MarshallingHttpMessageConverter 를 등록해줘야 하는 것이 조금 번거로울 수 있다.

    MappingJacksonHttpMessageConverter

    Jackson ObjectMapper 를 이용해서 자바 오브젝트와 JSON 문서를 자동변환해주는 메시지 컨버터다. 지원 미디어 타입은 application/json 이다. 자바 오브젝트 타입에 제한은 없지만 프로퍼티를 가진 자바빈 스트일이거나 HashMap 을 이용해야 정확한 변환 결과를 얻을 수 있다.

    Jackson 프로젝트의 ObjectMapper 가 대부분의 자바 타입을 무난히 JSON 으로 변환해주지만 날짜나 숫자 등에서 포맷을 적용하는 등의 부가적인 변환 기능이 필요하다면 ObjectMapper 를 확장해서 적용할 수 있다. 스프링 소스가 제공하는 MVC-AJAX 예제 프로젝트(https://src.springsource.org/svn/spring-samples/mvc-ajax/trunk) 를 보면, 스프링의 컨버전 서비스를 JSON 변환에 적용하도록 ObjectMapper 를 확장한 예를 찾아 볼 수 있다.

    위의 세 가지 메시지 컨버터를 사용하려면 다음과 같이 AnnotationMethodHandlerAdapter 빈을 등록하고 messageConverters 프로퍼티에 등록해줘야 한다. 여타 전략과 마찬가지로 전략 프로퍼티를 직접 등록하면 디폴트 전략은 자동으로 추가되지 않는다는 점을 주의하자.

     

    Posted by sinpk

    스프링에서는 기본적으로 JCL(자카르타 커먼스 로깅)을 사용하는데 SLF4J로 변경하는 방법을 적어놓았습니다.


    1. 스프링에서 참조하는 JCL 라이브러리를 빼버리기.

    2. JCL-over-SLF4J 추가하기.

    3. SLF4J API 추가.

    4. SLF4J-log4j 추가.

    5. log4j 추가.


    위의 방법을 메이븐 의존성 설정으로 한번에 할 수 있다.

    <dependency>

    <groupid>org.springframework</groupid>

    <artifactid>spring-context</artifactid>

    <version>${org.springframework.version}</version>

    <exclusions>

    <!-- 1. 스프링에서 참조하는 JCL 라이브러리를 빼버리기 -->

    <exclusion>

    <groupid>commons-logging</groupid>

    <artifactid>commons-logging</artifactid>

    </exclusion>

    </exclusions>

    </dependency>

    <!-- 3. SLF4J API 추가 -->

    <dependency>

    <groupid>org.slf4j</groupid>

    <artifactid>slf4j-api</artifactid>

    <version>${org.slf4j.version}</version>

    </dependency>

    <!--2. JCL-over-SLF4J 추가하기 -->

    <dependency>

    <groupid>org.slf4j</groupid>

    <artifactid>jcl-over-slf4j</artifactid>

    <version>${org.slf4j.version}</version>

    <scope>runtime</scope>

    </dependency>

    <!-- 4. SLF4J-log4j 추가 -->

    <dependency>

    <groupid>org.slf4j</groupid>

    <artifactid>slf4j-log4j12</artifactid>

    <version>${org.slf4j.version}</version>

    <scope>runtime</scope>

    </dependency>

    <!-- 5. log4j 추가 -->

    <dependency>

    <groupid>log4j</groupid>

    <artifactid>log4j</artifactid>

    <version>1.2.15</version>

    <exclusions>

    <exclusion>

    <groupid>javax.mail</groupid>

    <artifactid>mail</artifactid>

    </exclusion>

    <exclusion>

    <groupid>javax.jms</groupid>

    <artifactid>jms</artifactid>

    </exclusion>

    <exclusion>

    <groupid>com.sun.jdmk</groupid>

    <artifactid>jmxtools</artifactid>

    </exclusion>

    <exclusion>

    <groupid>com.sun.jmx</groupid>

    <artifactid>jmxri</artifactid>

    </exclusion>

    </exclusions>

    <scope>runtime</scope>

    </dependency>


     

    위 방법은 maven으로 라이브러리를 구성할때 방법

     

    commons-logging.jar를 빼고, slf4j-api.jar, slf4j-log4j12.jar, jcl-over-slf4j.jar, log4j.jar 라이브러리를 추가하면 된다.

     

    Posted by sinpk
    <logger name="java.sql.Connection">
        <level value="debug">
    </level></logger>
     <logger name="java.sql.Statement">
        <level value="debug">
    </level></logger>
     <logger name="java.sql.PreparedStatement">
        <level value="debug">
    </level></logger>
     <logger name="java.sql.ResultSet">
        <level value="debug">
    </level></logger>

    log4j.xml 에서 위의 설정을 하면 sql 디버그가 출력이 된다


    ※ java.sql.ResultSet 에 대한 로깅을 하면 Oracle CLOB 같은 스트림성 컬럼을 SELECT 할때  stream has already been closed 익셉션이 날수 있다.

    ※ java.sql.ResultSet 에 대한 로깅설정을 지우면 쿼리 결과에 대한 로깅은 제외된다.

    Posted by sinpk