@Service("productManager")
public class ProductManagerImpl extends GenericManagerImpl<Product,
Long> implements ProductManager {
.....
@Autowired(required = true)
private HttpServletRequest request;
@Autowired
private CommonsMultipartResolver multipartResolver;
@Override
public Product save(Product product) throws Exception {
....
MultipartHttpServletRequest multipartRequest =
multipartResolver.resolveMultipart(request);
MultipartFile fileImage = multipartRequest.getFile("file_image");
....
}
위 코드에서 fileImage 객체를 가져올 수가 없습니다.
이상한것은 multipartResolver.isMultipart(request) 값은 true가 리턴됩니다.
Controller에서 Service layer에 parameterf로 HttpSerlvetRequet를 넘기는 것이 모양새가
좋지 않아 @Autowired를 이용해 주입시켜 처리할려고 했는데 파일 업로드에서 문제가 생기네요.
Domain 객체(Product) 에 private byte[] file; 프로퍼티를 선언한 후 그것을 이용한 업로드 처리는 가능합니다.
하지만 위 소스와 같은 방법으로는 원래 안되는 것인지, 제가 뭘 잘못하고 있는건지 궁금합니다.
컨트롤러에서 멀티파트파일 객체를 파일 객체로 변환해 도메인 객체에 넣고 도메인 객체를 서비스에 넘기든지 해야 하겠네요
일단 서비스 레이어에 http리퀘스트가 들어있는 모양이 이상하네요
2012. 1. 13. 오후 7:26 Jihwan Kim <jhki...@gmail.com> 작성:
> --
> Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
> 이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
> 그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
> 더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.
>
그러나 비즈니스 로직 처리하는 부분에 있어서 request객체로부터 필요한 값들이 있어어요. 물론 도메인 객체에 넣어서
전달하면 되겠지만,..그부분은 좀 더 고민해보겠습니다.
컨트롤러에서는 가급적 로직처리를 하지 않을려고 하다보니, 이런 경우가 생기네요.
현재로서는 도메인 모델 객체에 MutipartFile 객체를 추가하여 받는 방법밖에는 없을 것 같습니다.
하이버네이트 엔터티 객체를 화면단까지 같이 사용하고 있기 때문에 @Transient로 프로퍼티를 추가하면 소스가 좀
지저분해지는 것 같아, 서비스에서 처리해볼려고 한것인데 이런 문제가 생겼어요.
2012년 1월 13일 오후 7:36, 황용대 <sta...@gmail.com>님의 말:
Controller 는 전역 applicationContext에 등록하여 사용하고 있습니다.(AOP문제로) 웹계층 서블릿
컨텍스트에서 전역 컨텍스트로 옮긴것이구요. 어차피 서블릿컨텍스트는 하나만 사용하고 있으므로 별 관계없을것이라고 판단하였습니다.
즉 Controller와 Service를 동일한 전역 컨텍스트에 등록하여 사용하고 있으므로 말씀하신
"DispatcherServlet은 웹 계층의 서블릿 콘텍스트로 한정되므로 서비스 계층 또한 반드시 이 콘텍스트에 속해야 하는
문제가 있습니다." 대로 하고 있습니다.
제가 궁금한 것은 HttpServletRequest를 Autowired해서 사용할 경우 이것이 (Controller
layer나 Service layer나 동일합니다.) 다른 request는 처리하는데 문제가 없는데 FileUpload일
경우에만 처리하는데에 문제가 있어 왜 그런것일까 원래 안되는것일까, 아니면 스프링에서 그건 모델객체를 통해서 처리하라는
뜻일까..싶은 궁금증이었습니다.
@Autowired HttpServletRequest request 나,
RequestContextHolder.currentRequestAttributes()).getRequest() 를 통해서
HttpServletRequest에 접근하는게 가능하다는 것은 스프링이 관리해주는것으로 생각합니다.따라서 스프링이 관리하는
HttpServletRequest에서는 MultipartRequest는 지원하지 않는다가 제가 듣고싶은 대답이었던 것
같습니다. ^^. 다른 Request처리는 문제가 없는데 왜 multipart만 안되는것일까..하는게 궁금했구요.
위와같은 처리를 Controller에서 하지 않고 ServiceLayer에서 고집하는 이유는 케사르님이 말씀하신 비즈니스
로직에서 프리젠테이션 로직으로의 의존성문제를 포기하고,
개발 편이성에 타협했습니다.트랜잭션이 서비스 계층의 메소드단위로 움직이고, 그 트랜잭션을 결정하는 요소중에 하나가 파일처리도
관련되어 있어 서비스레이어에서 처리하도록 한것이에요.
2012년 1월 14일 오전 12:22, Kesarr <kes...@playxp.com>님의 말:
context 정의를 applicationContext.xml, dispatcher-servlet.xml 2개구요. 이외에
database라든지 다른 리소스관련 컨텍스트 들이 있습니다.
controller와 service는 applicationContext.xml에 정의했습니다. 아래와 같습니다.
[applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
default-lazy-init="true">
<context:annotation-config/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
<context:component-scan base-package="com.rsupport.remotecall.base">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Service" />
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Repository" />
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<context:component-scan
base-package="com.rsupport.remotecall.auth.base.service"/>
<context:component-scan
base-package="com.rsupport.remotecall.auth.operator.service"/>
<context:component-scan
base-package="com.rsupport.remotecall.auth.client.service"/>
<context:component-scan
base-package="com.rsupport.remotecall.auth.base.util"/>
<context:component-scan
base-package="com.rsupport.remotecall.auth.base.aop"/>
<context:component-scan
base-package="com.rsupport.remotecall.auth.base.controller"/>
<context:component-scan
base-package="com.rsupport.remotecall.auth.operator.controller"/>
<context:component-scan
base-package="com.rsupport.remotecall.auth.client.controller"/>
</beans>
[dispatcher-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:oxm="http://www.springframework.org/schema/oxm"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/oxm
http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-lazy-init="true">
<bean id="exceptionResolver"
class="com.rsupport.remotecall.auth.base.util.CustomSimpleMappingExceptionResolver">
</bean>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="2097152"/>
</bean>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean id="jsonView"
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"
/>
<bean id="jsonpView"
class="com.rsupport.remotecall.base.webapp.view.MappingJacksonJsonpView"
/>
<bean id="downloadView"
class="com.rsupport.remotecall.base.webapp.view.DownloadView" />
<!-- View Resolver for JSPs -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="urlFilenameViewController"
class="org.springframework.web.servlet.mvc.UrlFilenameViewController"
/>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"
/>
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/**/*.html=urlFilenameViewController
</value>
</property>
<property name="order" value="3" />
</bean>
</beans>
[web.xml]
......
<!-- Context Configuration locations for Spring XML files -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/spring/applicationContext*.xml
classpath*:/**/applicationContext.xml
/WEB-INF/applicationContext*.xml
/WEB-INF/security.xml
/WEB-INF/cxf-servlet.xml
/WEB-INF/cxf-client.xml
</param-value>
</context-param>
.......
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
===============================================
처음에는 controller는 dispatcher-servlet.xml에 정의했었습니다. 그런데 controller에서
AOP가 동작하지 않아, applicaton-context.xml로 옮겼습니다.
위와같이 설정한 상태에서 @Controller나 @Service에서
@Autowired
private HttpServletRequest request2;
하게되면 잘 주입됩니다. 일반 Request는 문제없이 처리됩니다. 다만 multipart-form data만 문제가 있습니다.
Controller에서 넘겨받은 HttpServletRequest 는 ((MultipartHttpServletRequest)
request;) 캐스팅 하면 잘됩니다만 autowired로 주입받은 request객체는 타입 오류로 에러납니다.
그래서 multipartResolver를 써서
변환(multipartResolver.resolveMultipart(getHttpServletRequest());)시켜본건데
그것도 안됩니다. 에러는 안나지만 Multipart file을 못가져옵니다.
디버그를 걸어서 두객체(Controller에서 넘긴 request Vs autowired reqeust)를 비교해보니,
autowired request는 proxy 객체인데,
WebApplicationContextUtils$RequestObjectFactory에서 만들어주는데 type이
javax.servlet.ServletReuqest네요.
이미지 캡쳐해서 파일로 첨부했습니다.
위 문제로 현재는 Model 객체에 MultipartFile 변수를 추가하여 처리하는것으로 처리했습니다.
감사합니다.
2012년 1월 17일 오전 12:18, Kesarr <kes...@playxp.com>님의 말: