2012-06-14 2 views
1

저는 Spring MVC 주석 중심 프로젝트를 가지고 있으며 훌륭하게 작동합니다. 이 시점에서 많은 양식이 작고 Ajax 요청을 사용하여 양식을 처리하는 경향이 있습니다. 나는이 플러그인을 사용하여 Ajax 요청을 처리하기 위해 http://jquery.malsup.com/form/을 사용했으며, 또한 훌륭하게 작동 해왔다. 나는 문제가 생겼다. Jackson을 사용하여 @ResponseBody 항목을 json으로 직렬화합니다. 그것은 훌륭하게 작동했지만, 파일을 업로드해야하는 첫 번째 형식으로 진행되었습니다. AjaxForm은 iframe 제출 트릭을 사용하여 구형 브라우저에서 이것을 처리하지만 모든 정보가 성공적으로 도착하는지 확인하기 위해 응답을 <textarea></textarea>으로 묶어야한다고 경고합니다. 나는 미친 듯이 주변을 둘러 보았고, 객체를 위해 Custom Serializer를 만들 수 있다는 것을 알았지 만 요청 유형이 XHR이고 그 다음에만 <textarea></textarea> 태그로 응답을 둘러싸고 있는지 확인하는 방법을 생각할 수 없다. . 어떤 아이디어? 사전에Spring MVC 3 - Jackson - AjaxForm

public @ResponseBody 
    JsonResponse setReferenceNumber(@ModelAttribute("referenceNumber") 
    @Valid ReferenceNumberBean referenceNumber, 
    BindingResult result, 
    HttpServletResponse response) 
    { 
     //Do some stuff 
     //Theoretically here I would call upon some logic to surround the response? 
     return jsonResponse; 
    } 

감사 :

여기 내 코드의 일부입니다!

UPDATE - 난 거의 특히 봄에 새로운 인터셉터를 추가하여, 나는이 문제를 해결했다고 생각 :

<mvc:interceptors> 
     <bean class="edge.portal.vendor.web.interceptor.MultipartAjaxInterceptor"></bean> 
    </mvc:interceptors> 

그런 다음 X가-요청-로하면 요격 시험을 볼 필요, 따라서 iframe이 아약스 게시물을 암시, 내 자바 스크립트 아약스로 전화를 플래그했지만 헤더이 변화를 반영하지 않은 경우 다음 태그를 추가 :

@Component 
    public class MultipartAjaxInterceptor extends HandlerInterceptorAdapter 
    { 
    @Override 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception 
    { 
    if(request.getParameter("isAjax") != null && request.getHeader("X-Requested-With") == null) 
     response.getWriter().write("<textarea>"); 

    return true; 
    } 

    @Override 
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception 
     { 
     if(request.getParameter("isAjax") != null && request.getHeader("X-Requested-With") == null) 
      response.getWriter().write("</textarea>"); 
     } 
    } 
이제

내가 우연히 분명히 문제

가 당신 수없는 칼 l 응답의 getWriter 또는 OutputStream이 두 번 이상 반복되면이 문제를 해결하는 올바른 방법을 찾고 있지만 여기에서 어디로 가야할지 모릅니다.

답변

1

여기에 대한 답변이 조금 늦다는 것을 알고 있지만 최근에 비슷한 문제가 있었으며 결과를 공유하고 싶습니다. HandlerInterceptor를 사용하여 올바른 방향으로 가고 있었지만 getWriter() 메서드 대신 getOutputStream() 메서드를 사용해야했습니다. Javadoc for ServletReponse에 따르면로 getOutputStream이 이미 호출 된 경우

getOutputStream 

Throws: 
IllegalStateException - if the getWriter method has been called on this response 

마찬가지로,로 getWriter 방법은 IllegalStateException을 발생하지만, 하나 하나만큼 다른 하나는 호출되지 않습니다으로 여러 번 할 수 있습니다. Jackson은 JSON 데이터를 작성할 때 getOutputStream을 사용하는 것처럼 보입니다. 그래서 코드는 다음과 같은 수정 작업을해야합니다

@Component 
public class MultipartAjaxInterceptor extends HandlerInterceptorAdapter 
{ 
    @Override 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
     if(request.getParameter("isAjax") != null && request.getHeader("X-Requested-With") == null) 
      response.getOutputStream().write("<textarea>".getBytes(response.getCharacterEncoding())); 

     return true; 
    } 

    @Override 
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 
     if(request.getParameter("isAjax") != null && request.getHeader("X-Requested-With") == null) 
      response.getOutputStream().write("</textarea>".getBytes(response.getCharacterEncoding())); 
    } 
} 

또한 응답이 원래 "응용 프로그램/JSON"로 전송 된 경우 postHandle에로 setContentType 메소드를 사용하여 응답의 내용 유형을 변경하는 것이 도움이 될 수있다.

1

게시 하시겠습니까?이 문제를 해결하는 방법 (잘 모름)은 입니다. 프론트 엔드에서 Dojo를 사용하고 Dojo는 파일 업로드에 dojo.io.iframe.send을 사용합니다. 폼 포스트를 다루는 JS 함수는 다음과 같습니다.

제 경우
function ioIframeGetJson(){ 
    var td = dojo.io.iframe.send({ 
     url: "${pageContext. request. contextPath}/switch/add", 
     form: "frmSwitchTypeAdd", 
     method: "post", 
     preventCache: true, 
     handleAs: "json", 
     load: function(response, ioArgs){ 
       clearSwitchTypeForm(); 
      }, 

      error: function(response, ioArgs){ 
      } 
    }); 
} 

은 또한 업로드 된 파일을 포함하는 형태가 제출 처리 컨트롤러 방법은 아래와 같다 (찾는 I 보관 한 (I 세트 "handleAs '재산권'json '같다 봐) 내 반환 문자열에 형)

@RequestMapping(value="/add",method=RequestMethod.POST) 
    @ResponseBody 
    public String add(HttpServletRequest request) { 
     . . . . . 
     //I call the toString method of the model I want to return in Response 
     return fromModel(switchType).toString(); 
} 

그리고 toString() 방법은 내가 JSON 문자열이 <textarea>

public String toString() { 
     return "<textarea>{name:'" + name + "', code:'" + code 
       + "', className:'" + className + "', dynamic:" + dynamic+"}</textarea>"; 
    } 
+0

결국 그렇게 될 수도 있습니다. JsonSerializer를 사용할 수 있기를 기대하고 있었기 때문에 도움이되었지만 옵션이 아닐 수도 있습니다. – Mark

0
에 둘러싸여 만들어, 다음과 같이 코딩

내가 도착한 대답은 여기에있다. 그것은 Ravi의 대답과 비슷하지만 좀 더 나은 것으로 보인다. 우선 @ResponseBody의 문자열을 변경하는 것이 었습니다. 이것은 <textarea /> 태그를 사용하여 수동으로 응답을 둘러싼다고 가정합니다.

public class JsonResponseSerializer 
{ 
private HttpServletRequest request; 

public JsonResponseSerializer(HttpServletRequest request) 
{ 
    this.request = request; 
} 

public String serialize(JsonResponse jsonResponse) throws IOException 
    { 
    String response = ""; 

    ObjectMapper mapper = new ObjectMapper(); 

    response = mapper.writeValueAsString(jsonResponse); 

    if(request.getParameter("isAjax") != null && request.getHeader("X-Requested-With") == null) 
    { 
     response = "<textarea>" + response + "</textarea>"; 
    } 

    return response; 
    } 
} 

가 그럼 난 여기에 내 대답의의 반환 문을 변경 : : 다음 다음과 같이 새로운 클래스가 보였다 JsonResponseSerializer라고했다 본질적으로

return new JsonResponseSerializer(request).serialize(jsonResponse); 

, 나는 ServletRequest의가있는 유틸리티 메소드를 만들어 주사 한 다음 잭슨에게 객체를 직렬화하도록 요청한 다음 필요한 경우 <textarea />으로 둘러 쌉니다.

관련 문제