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