Spring 3/jQuery AJAX

jQuery AJAX with Spring

Soul-Learner 2014. 9. 22. 17:26

Spring , jQuery, AJAX 를 함께 사용하여 로그인/응답을 구현한 예


스프링 콘트롤러에서 자동으로 응답 데이터를 JSON 형식으로 변경하여 클라이언트에게 전송하는 예는 다른 페이지를 참조하세요


개요


Spring 3.1 부터는 JSR-303 Validation 기능이 지원되며 다양한 Annotation을 사용하여 브라우저에서 전송된 데이터를 간편하게 검증할 수 있다.

여기서는 JSR-303 Validation 방법을 사용하여 로그인 폼 데이터를 검증하고 그 결과를 AJAX 요청에 대한 응답으로 클라이언트에게 전송하는 예제를 작성해본 것이다.

아래의 코드에서 LoginBean 의 id, pwd 속성에 적용한 Annotation 의 메시지는 디폴트로 클라이언트에게 전달되는 검증오류 메시지로 사용되지만 개발자가 messages_properties 파일을 작성해서 사용한다면 그 디폴트 검증오류 메시지는 쉽게 오버라이드되어 messages_properties 파일에 있는 검증오류 메시지가 웹브라우저에 전달될 것이다



결과화면




web.xml

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

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"

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

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">


    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>/WEB-INF/spring/root-context.xml</param-value>

    </context-param>


    <!-- Creates the Spring Container shared by all Servlets and Filters -->

    <listener>

        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>


    <!-- Processes application requests -->

    <servlet>

        <servlet-name>appServlet</servlet-name>

        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>

            <param-name>contextConfigLocation</param-name>

            <param-value>/WEB-INF/spring/servlet-context.xml</param-value>

        </init-param>

        <load-on-startup>1</load-on-startup>

    </servlet>


    <servlet-mapping>

        <servlet-name>appServlet</servlet-name>

        <url-pattern>/</url-pattern>

    </servlet-mapping>


    <filter>

<filter-name>encodingFilter</filter-name>

<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param>

    </filter>

    <filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>/*</url-pattern>

    </filter-mapping>


</web-app>



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 -->

    <mvc:annotation-driven/>


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

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


    <!-- 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>

위의 내용중 굵게 표현한 <resources mapping="/resources/**" location="/resources/" />  요소의 의미는 요청 URL이 /resources/ 으로 시작하면 콘트롤러를 호출하지 말고 바로 해당 정적 리소스가 저장된 경로(location="/resources/")를 참조하여 클라이언트에게 전달하도록 설정하는 것이다. 즉, webapp/resources/ 안에 저장된 정적 리소스는 콘트롤러를 경유하지 않고도 바로 클라이언트에게 전달되도록 설정하는 것이며 resources 가 아닌 다른 디렉토리도 설정할 수 있다


LoginController.java

package org.kdea.java;


import javax.validation.Valid;


import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.validation.BindingResult;

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

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


@Controller

public class LoginController {


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

public String login(Model model){

model.addAttribute("loginBean", new LoginBean());

return "ajax_login_request";

}

@RequestMapping(value="/login.htm", method=RequestMethod.POST)

public String login(Model model, @Valid LoginBean loginBean, BindingResult result){

if(result.hasErrors()){

System.out.println(result);

}else{

model.addAttribute("success", "로그인 결과 : 로그인 성공");

}


return "ajax_login_response";

}

}



LoginBean.java

package org.kdea.java;


import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotEmpty;


public class LoginBean {


@Size(min=1,max=10, message="1~10 자 사이")

private String id;

@NotEmpty(message="필수입력")

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_login_request.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>로그인 폼</title>

<style type="text/css">

.errorMsg { color: red; }

</style>

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

<script type="text/javascript">

$(document).ready(function(){

$('#loginForm').on('submit', function(e){

e.preventDefault();

ajax_request();

});

});


function ajax_request(){

var usrId = $('#loginForm #id').val();

var usrPwd = $('#loginForm #pwd').val();

$.ajax( 

{

url:'login.htm',

type:'POST',

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

dataType:'text',

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

success :function(resData){

//alert(resData);

var jsonObj = eval('('+resData+')');

if(jsonObj.success){

alert(jsonObj.success);

location.href="home.do";

}

$('#idErr').empty();

$('#idErr').html(jsonObj.idErr);


$('#pwdErr').empty();

$('#pwdErr').html(jsonObj.pwdErr);

},

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

}

);

}

</script>

</head>

<body>

<h2>로그인 폼(AJAX 테스트)</h2>


<form id="loginForm" action="login.htm" method="post">

I D <input type="text" id="id" name="id"><span class="errorMsg" id="idErr"></span><br>

PWD <input type="password" id="pwd" name="pwd"><span class="errorMsg"  id="pwdErr"></span><br>

<input type="submit" value="Login">

</form>


</body>

</html>



WEB-INF/views/ajax_login_request.jsp

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

    pageEncoding="UTF-8"%>

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

{"success":"${success}", "idErr":<spring:bind path="loginBean.id">

"${status.errorMessage}"

</spring:bind>,"pwdErr":<spring:bind path="loginBean.pwd">

"${status.errorMessage}"

</spring:bind>}




WEB_INF/classes/messages/messages_ko.properties

NotEmpty.loginBean.pwd=\uC554\uD638\uB294 \uD544\uC218\uD56D\uBAA9\uC785\uB2C8\uB2E4

Size.loginBean.id=\uC544\uC774\uB514\uB294 1~10\uC790 \uC0AC\uC774\uB85C \uC785\uB825\uD574\uC8FC\uC138\uC694


위의 메시지 리소스 파일의 내용은 유니코드 숫자로 입력된 상태인데 한글로 검증오류 메시지를 입력하면 자동으로 유니코드로 변환되고 실제 브라우저에 출력될 때는 원래의 한글로 출력된다.