본문 바로가기
JAVA/Spring

Spring MVC - ajax + responseBody

by 설총이 2018. 9. 17.

먼저 설정해주어야하는것부터 시작한다.


[pom.xml]


1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib-ext-spring -->
<dependency>
    <groupId>net.sf.json-lib</groupId>
    <artifactId>json-lib-ext-spring</artifactId>
    <version>1.0.2</version>
</dependency>
cs


'JSONObject'를 사용할 수 있게 해주는 소스.

Maven Repository 사이트에서 artifactId로 검색하면 상위에 뜬다.





[dispatcher-servlet.xml]



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    <context:annotation-config />
    <context:component-scan
        base-package="spring.controller,spring.service,spring.common,
             spring.interceptor,ajax.controller" /
     <!-- ajax.controller를 bean객체로 만들기 위해 scan에 추가한다. -->
    
 
    <mvc:annotation-driven>
        <mvc:message-converters>
            <!-- @ResponseBody로 String 처리할때 한글처리하기위한 bean -->
            <bean
                class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <!-- property들을 앞에 붙히고 뒤에붙혀서 뷰 경로를 만들어준다 -->
 
</beans>
 
cs




[mybatis.xml]



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!-- 프로퍼티 파일로부터 데이터를 읽어온다. -->
<context:property-placeholder
    location="classpath:db.properties" />
 
<!-- 커넥션 풀을 만들기위한 과정. db.properties에 있는 값을 가져와 EL로 꺼냄 -->
<bean id="dataSource"
    class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close">
    <property name="driverClass" value="${jdbc.driver}" />
    <property name="jdbcUrl" value="${jdbc.url}" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>
 
<bean id="sqlSessionFactory"
    class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mapperLocations" >
    <list>
        <value>classpath*:sql/*.xml</value
        <value>classpath*:mybatis/*.xml</value>
    </list>
    <!-- 여러경로의 맵퍼파일을 추가하고싶다면 list태그안에 value태그로 선언해준다. -->
    </property>
    <!-- ampperLocations에는 맵퍼파일의 경로를 잡는다
     value에 와일드카드를써서 여러개의 파일을 한번에 지정할 수 있다. -->
</bean>
    
    
<bean id="cityDAO" class="ajax.controller.CityDAO">
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<!-- bean객체로 올릴 DAO 클래스 선언.
CityDAO 타입을 받아서 쓸수있는 Autowired속성 추가하는것을 잊지말자. -->
cs



이부분에서 중요한건, classpath는 resources 밑에서부터 받아오는 파일 경로를 의미하고,

여러 경로에 있는 mapper파일을 추가하고싶다면, 위와같은 방법으로도 사용할 수 있다.


또한, DB연결해서 받아올 DAO클래스를 type에 맞춰서 bean 컨테이너에 올려놓은것과 연결하기위해

@Autowired속성 사용하는것도 잊지말자.




[city.jsp]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
    String cp = request.getContextPath();// /springMvc
    request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html>
<head>
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
</head>
<body>
<select id="sido" onchange="cityList()">
<option value = "" >::시도선택::</option>
</select>
 
<select id="city">
  <option value="">::도시선택::</option>
</select>
 
<input type="button" value=" 확인 " onclick="result()">
 
</body>
</html>
cs




[script 부분]



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<script>
    $(function(){
        //body로딩이 다 된후에 바로 실행되는 레디펑션 로직.
        //시도테이블의 list가져오기위한 로직.
        
        var url = "<%=cp%>/city/sidoList.do";
        // /프로젝트명/city/sidoList.do 를 받아오는 url.
        // 프로젝트명은 맨위에 스크립트릿으로 받아옴.
        
        var params = "dumi="+new Date();
        //dumi=Mon Sep 17 2018 17:15:07 GMT+0900 (한국 표준시) 형식으로뜬다.
        //실행한 그때의 현재시간으로.
        
        console.log("params : " , params);
        
        $.ajax({
            'type' : "post",
            'url' : url, 
// ==> /프로젝트명/city/sidoList.do에서
// ==> /프로젝트명제거 + 확장자 .do 제거되고 실행되면서 Controller로 요청후 이동.
            'data' : params,
            dataType : "json",
            
            success : function(args){
                //성공하면 args라는 변수에 담겨오는데
//파고드는게 불편하다면 var result = args.data; 로 선언하고 result.length로 꺼내도 가능하다.
                console.log("성공한 데이터 : " , args)
                for(var i=0; i < args.data.length; i++){
                    
        $("#sido").append("<option value='"+args.data[i]+"'>"+args.data[i]+"</option>");
        //id가 sido인 요소선택
        //append로 기존 셀렉터로 선택된 요소 다음에 다음내용이 들어감
        //<option value='0'>서울</option> 이런식으로 sido의 요소안에 자식으로 들어감
        // args.data[i] : args 는 function(args)의 인자. 
        //data는 controller.java에서 json객체에 넣어준 key(여기서는 list가 값이 된다). 
        //[i]는 list의 몇번쨰 데이터를 가져올지 배열을 나타냄
                }
            },
            
            error : function(err){
                alert("첫번째 ajax로직 : " , err.responseText);
            }
        });
    });
 
    function cityList(){
        var snum = $("#sido").val();
        if(snum==''){
            $("#city option").each(function(){
                $("#city option:eq(1)").remove();
            // city option의 1번째를 계속 삭제(0번째만 남기고 모두 지우게 된다) , 
            // eq : 지정된 index 번째의 엘리먼트 선택
            });
            //$("#city").append("<option value=''>::도시선택::</option>");    
            // 위의 반복문으로 모두 삭제되어 있으므로 추가해준다.
            // 위의 명령문은 바로 위의 엘리먼트가 1이아닌 0이었을 때 사용하면 됨.
            return;
        }
        
        var url = "<%=cp%>/city/cityList.do";
        var params = "snum="+snum+"&dumi="+new Date();
        
        $.ajax({
            'type' : "post",
            'url' : url,
            'data' : params,
            'dataType' : 'json',
            
            success : function(args){
                $("#city option").each(function(){
                    $("#city option:eq(0)").remove();
                });
 
                $("#city").append("<option value = ''>::도시선택::</option>");
                
                for(var i=0; i<args.data1.length; i++){
                    var area2 = args.data1[i];
                    
                    $("#city").append("<option value='"+area2['AREA2']+"'>"+area2['AREA2']+"</option>");
                    
//$("#city").append("<option value='"+args.data1[i]['AREA2']+"'>"+args.data1[i]['AREA2']+"</option>");
//이런 형태도 가능
                }
            },
            
            error : function(err){
                alert("두번째 ajax 로직 : ", err.responseText);
            }
        });
    }
    
    //확인 버튼을 누르면 실행될 로직.
    function result(){
        var sido = $("#sido :selected").text();
        var city = $("#city :selected").text();
        //선택자를 찾아가서, 선택된 옵션의 text를 뽑아오는 변수들.
        
        var s = sido + " " + city;
        alert("sido + city 출력 : " + s);
    }
    
</script>
cs




[CityController.java]



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Controller
public class CityController {
 
    @Autowired
    private CityService service;
 
    public void setService(CityService service) {
        this.service = service;
    }
    
    @RequestMapping(value = "/city/city.do")
    public String city() throws Exception {
        return "ajax/city";
    }
    
    @RequestMapping(value="/city/sidoList.do" , method = RequestMethod.POST)
    public void sidoList(HttpServletResponse response) throws Exception {
        List<String> list = service.listSido();
        //service.listSido()는 CityService를 구현한 CityServiceImpl에 있는 메서드를 실행한다.
        //그 메서드에서 데이터베이스에서 selectList로 가져온 list를 저장하는 로직을 사용한 후 list 저장하고 리턴.
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("data", list);
        //그 데이터를 담은 list를 key값 'data'라는 이름으로 list를 담음.
        //이것이 가능한 이유는 JSON객체는 {String, Object} 타입으로 받을 수 있기 때문이다.
        
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print(jsonObject.toString());
 
    }
    
    //produces 부분은 잘 안먹을때도 있어서 xml에서 설정하는게 좋다고 함.
    @RequestMapping(value = "/city/cityList.do" , method = RequestMethod.POST,produces="text/plain;charset=UTF-8")
    @ResponseBody
    public String cityList(HttpServletResponse response, @RequestParam("snum"String city) throws Exception {
        response.setContentType("text/html; charset=UTF-8");
        List<Map<String,Object>> list = service.listCity(city);
        System.out.println("cityList메서드에있는 Map으로 받은 List 내용 : " + list);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("data1", list);
        return jsonObject.toString();
        //위의 sidoList메서드는 데이터를 담아서 값을 던져주고 끝내는것이기때문에 void 메서드로 사용하는 1회성이고.
        //이 cityList메서드는 데이터를 담은 값을 다시 responseBody로 보내기위해 return 타입을 String으로 받아온다.
    }
    
    
}
 
cs




실제로 .listSido() 와, .listCity(city) 가 실행되는 클래스



[CityServiceImple.java]



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package ajax.controller;
 
import java.util.List;
import java.util.Map;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@Component
public class CityServiceImpl implements CityService{
 
    @Autowired
    private CityDAO cityDAO;
 
    public void setCityDAO(CityDAO cityDAO) {
        this.cityDAO = cityDAO;
    }
    
    public List<String> listSido(){
        List<String> list = null;
        
        try {
            list = cityDAO.getListData("city.listSido");
        }catch(Exception e) {
            System.out.println("String으로 받아온 메서드 : " +e.toString());
        }
        
        return list;
    }
    
    public List<Map<String,Object>> listCity(String city){
        List<Map<String,Object>> list = null;
        
        try {
            list = cityDAO.getListData("city.listCity", city);
        } catch (Exception e) {
            System.out.println("Map으로 받아온 메서드 : "+ e.toString());
        }
        
        return list;
    }
    
}
 
cs



getListData 사용되는 클래스


[CityDAO.java]


1
2
3
4
5
6
7
8
9
10
11
12
public class CityDAO extends SqlSessionDaoSupport{
 
    public List<String> getListData(String string){
        List<String> sido = getSqlSession().selectList(string);
        return sido;
    }
    
    public List<Map<String,Object>> getListData(String string, String city){
        List<Map<String,Object>> selectCity = getSqlSession().selectList(string, city);
        return selectCity;
    }
}
cs


getSqlSession()이 맨 처음 mybatis.xml에서 지정한 sql/*.xml에 있는 mapper파일을 읽어들여서

그 안에 선언한 select를 실행해서 데이터를 담아서 List에 저장한다.

그 mapper파일은 밑에와 같다.


[cityMapper.xml]



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="city">
    <select id="listSido" resultType="String">
        select distinct area1 from zipcode order by area1 asc
    </select>
 
    <select id="listCity" parameterType="String" resultType="Map">
        select distinct area2 from zipcode 
        where area1 = #{area1} order by area2 asc
    </select>
 
</mapper>
cs


'JAVA > Spring' 카테고리의 다른 글

Spring MVC - 두번째 LoginController  (0) 2018.09.19
String MVC - 뷰(ViewResolver) 원칙  (0) 2018.09.19
Spring MVC - BindingResult 사용법  (0) 2018.09.13
Spring - RESTful 예제  (2) 2018.09.13
@ModelAttribute 추가 공부내용.  (0) 2018.09.12