본문 바로가기

Spring 3/@ResponseBody Err Msg

Error Msg to JSON

Spring 에서 데이터 검증 오류를 JSON 문자열로 클라이언트에게 전송하는 예



개요

클라이언트에서 AJAX 요청을 하는 경우에는 화면의 일부를 갱신할 목적이기 때문에 응답 데이터의 포맷으로 JSON 형식을 선택하는 것이 보통일 것이다.

스프핑에서는 콘트롤러 클래스에서 @ResponseBody 라는 Annotation 을 사용하면 리턴되는 Map 이나 도메인 오브젝트의 속성들이 자동으로 JSON 형식으로 변환되어 클라이언트에게 전달되는 기능이 있다.

여기서는 서버로 데이터를 전송할 경우 그 데이터를 JSR-303 검증을 거쳐 오류가 있을 때는 오류 메시지를 JSON 으로 전송하는 기능을 작성해보려고 한다.



WEB-INF/spring/servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/mvc"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:beans="http://www.springframework.org/schema/beans"

    xmlns:mvc="http://www.springframework.org/schema/mvc"

    xmlns:context="http://www.springframework.org/schema/context"

    xsi:schemaLocation="http://www.springframework.org/schema/mvc 

    http://www.springframework.org/schema/mvc/spring-mvc.xsd

        http://www.springframework.org/schema/beans 

        http://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context 

        http://www.springframework.org/schema/context/spring-context.xsd">


    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Process annotations on registered beans like @Autowired... -->

    <context:annotation-config/>

    

    <!-- Enables the Spring MVC @Controller programming model -->

    <annotation-driven/>


    <context:component-scan base-package="org.kdea.java" />

    <context:component-scan base-package="org.kdea.service" />

    <context:component-scan base-package="org.kdea.hibernate" />

    <context:component-scan base-package="org.kdea.json" />


    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->

    <resources mapping="/resources/**" location="/resources/" />


    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->

    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

        <beans:property name="prefix" value="/WEB-INF/views/" />

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

        <beans:property name="contentType" value="text/html; charset=UTF-8"/>

    </beans:bean>


    <beans:bean id="messageSource

  class="org.springframework.context.support.ResourceBundleMessageSource">

    <beans:property name="basename" value="messages/messages"/> 

    </beans:bean>

<beans:bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />


</beans:beans>


메시지 리소스를 이용하는 방법은 다른 페이지를 참조하세요


pom.xml

<dependency>

    <groupId>com.fasterxml.jackson.core</groupId>

    <artifactId>jackson-core</artifactId>

    <version>2.0.4</version>

</dependency>

<dependency>

    <groupId>com.fasterxml.jackson.core</groupId>

    <artifactId>jackson-databind</artifactId>

    <version>2.0.4</version>

</dependency>



JsonController.java

package org.kdea.json;


import java.util.List;

import java.util.Locale;

import java.util.*;


import javax.validation.Valid;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.MessageSource;

import org.springframework.stereotype.Controller;

import org.springframework.validation.BindingResult;

import org.springframework.validation.FieldError;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.ResponseBody;

/*

Jackson 라이브러리를 설치한다

메소드에 @ResponseBody 를 적용한다

<mvc:annotation-driven/> 을 servlet-context.xml 에 선언한다

이렇게 설정하면 스프링은 리턴되는 객체(도메인 오브젝트, Map 등)를 json 문자열로 자동으로

변환하여 클라이언트에게 전송한다.

이 경우 별도의 jsp 와 같은 View를 연결하지 않아도 된다

*/


@Controller

public class JsonController {

private MessageSource messageSource;

@Autowired

public JsonController(MessageSource messageSource) {

this.messageSource = messageSource;

}


@RequestMapping(value="/json/login", method=RequestMethod.GET)

public String login() {

return "json/ajax_client";

}

@RequestMapping(value="/json/login", method=RequestMethod.POST, produces="application/json; charset=utf8")

@ResponseBody //이 메소드가 리턴하는 값을 json 문자열로 변환하여 클라이언트에게 전송한다

public Map<String,String> login(@Valid User user, BindingResult result) {


// 데이터 검증실패의 경우, 오류 메시지를 JSON 문자열로 클라이언트에게 전송한다

Map<String,String> map = null;

if(result.hasErrors()){

map = new HashMap<String,String>();

List<FieldError> list = result.getFieldErrors();

for(int i=0;i<list.size();i++) {

FieldError fe = list.get(i);

System.out.println("오류필드:"+fe.getField());

if(fe.getField().equals("id")){

String idErr = messageSource.getMessage("NotEmpty.user.id", null, Locale.getDefault());

map.put("idErr", idErr);


}

if(fe.getField().equals("pwd")){

String pwdErr = messageSource.getMessage("NotEmpty.user.pwd", null, Locale.getDefault());

map.put("pwdErr", pwdErr);

}

}

return map;

}

//데이터 검증오류가 없는 경우, 입력한 아이디, 암호를 JSON 문자열로 전송한다

map = new HashMap<String,String>();

map.put("id", user.getId());

map.put("pwd", user.getPwd());

return map; // 뷰가 연결되는 것이 아니라 응답 데이터에 해당하는 객체를 리턴한다

}


}



User.java

package org.kdea.json;


import org.hibernate.validator.constraints.NotEmpty;


public class User {


@NotEmpty

private String id;

@NotEmpty

private String pwd;

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getPwd() {

return pwd;

}

public void setPwd(String pwd) {

this.pwd = pwd;

}

}



ajax_client.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

<script src="<c:url value="/resources/jquery-2.1.1.min.js"/>"></script>

<script type="text/javascript">

function toJson_submit(){

ajax_request();

}

function ajax_request(){

var usrId = loginForm.id.value;

var usrPwd = loginForm.pwd.value;

$.ajax

{

url:'login.do',

type:'POST',

data:{'id':usrId, 'pwd':usrPwd},

dataType:'json',

                        contentType: 'application/x-www-form-urlencoded; charset=UTF-8',

success :function(resData){

if(resData.idErr || resData.pwdErr) {

alert("에러:"+resData.idErr+','+resData.pwdErr);

}else{

alert("성공:"+resData.id+','+resData.pwd);

}

},

error :function(errMsg){ alert("에러:"+errMsg); }

}

);

}

</script>

</head>

<body>


<form name="loginForm">

ID <input type="text" name="id">

PWD <input type="password" name="pwd">

<input type="button" value="SUBMIT" onclick="toJson_submit()">

</form>

</body>

</html>