티스토리 뷰
1. @ResponseBody
이 Annotation 이 쓰여 있는 메소드에서 리턴 되는 값은 View 를 통해서 출력 되지 않고 HTTP Response Body 에 직접 쓰인다.
이 때, 쓰여지기 전에 리턴 되는 데이터 타입에 따라 MessageConverter 에서 변환이 이뤄진 후 쓰여지게 됩니다.
MessageCover 의 종류
- StringHttpMessageConverter
- FromHttpMessageConverter
- ByteArrayMessageConverter
- MarshallingHttpMessageConverter
- SourceHttpMessageConverter
- BufferedImagedHttpMessageConverter
- MappingJacksonHttpMessageConverter
Jackson's ObjectMapper 를 사용하여 Request, Response 를 JSON 으로 변환할 때 사용 되는 MessageConverter 이다.
Jackson Mapper 와 Core 를 받기 위해서 jar 파일을 검색하였다.
Data Mapper for Jackson 라이브러리만 추가해도 Maven 이 Core 를 하위 라이브러리로 가지고 있으므로, Mapper 만 추가해도 자동으로 Spring 에서 다운 받는다.
안 받아 질 때는 직접 받으면 된다.
본격적으로, @ResponseBody 를 이용한 JSON 데이터 전송을 이용해보자.
댓글을 관리하는 Controller 소스 파일이다.
메소드에 @ResponseBody Annotation 이 추가 되어있다.
comment-Controller.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 com.ktds.comment.controller; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import com.ktds.comment.service.CommService; import com.ktds.comment.vo.CommentVO; @Controller public class Comm_Controller { @Autowired CommService cs; ModelAndView mav; @RequestMapping("showComment.ktds") @ResponseBody public List<CommentVO> showComment(HttpServletRequest req, @RequestParam int article_num) { return cs.getAllComment(article_num); } @RequestMapping("writeComment.ktds") @ResponseBody public List<CommentVO> writeComment(HttpServletRequest req) { int article_num = Integer.parseInt((req.getParameter("article_num"))); String comment = req.getParameter("comment"); HttpSession ss = req.getSession(); String id = (String) ss.getAttribute("id"); cs.insertComm(article_num, comment, id); List<CommentVO> commList = cs.getAllComment(article_num); return commList; } @RequestMapping("delComment.ktds") @ResponseBody public List<CommentVO> delComment(HttpServletRequest req, @RequestParam int article_num, @RequestParam int comment_num) { HttpSession ss = req.getSession(); String id = (String) ss.getAttribute("id"); cs.delComm(comment_num, id); List<CommentVO> commList = cs.getAllComment(article_num); return commList; } } |
comment-servlet.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.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-3.1.xsd"> <context:component-scan base-package="com.ktds.comment"></context:component-scan> <mvc:annotation-driven/> </beans> |
bean scan을 위한 component-scan 과 annotation 을 읽기 위한 annotation-driven 을 추가한다.
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <servlet> <servlet-name>commServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/comment-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>commServlet</servlet-name> <url-pattern>/comment/*</url-pattern> </servlet-mapping> |
comment.js ( 스크립트 소스 코드 )
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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | $(document).ready(function() { printResult = function(data){ var result = JSON.stringify(data); alert(result); };
$('#comm_show').click(function() { $.ajax({ type : "POST", url : "/bbs2/comment/showComment.ktds", async : true, dataType : "json", data : { article_num : $('#article_num').val() }, success : function(data) { // printResult(data); var html = "<table width='600' border='1'>"; //껍질이 하나 더 생겨서 들어올 때는, data에 해당 리스트에 대한 이름을 직접 지정 // $.each(data.commentList, function(entryIndex, entry) { $.each(data, function(entryIndex, entry) { html += '<tr class="bbb">'; html += '<td class="bgcolor1">' + entry.id + '</td>'; html += '<td class="bgcolor2">' + entry.comment_content + '</td>'; html += '<td class="bgcolor2">' + entry.write_date + '</td>'; html += '<td id="abc" class="bgcolor2"><input type="button" onclick="rowDelete(this)" value='+ entry.comment_num+'></td>'; html += '</tr>'; }); html += '</table>'; $("#show_comment").html(html); }, error : function(xhr) { alert("error html = " + xhr.statusText); } }); }); $('.writer').click(function() { $.ajax({ type : "POST", url : "/bbs2/comment/writeComment.ktds", async : true, dataType : "json", data : { article_num : $('#article_num').val(), comment : $('.textcomment').val() }, success : function(data) { // json으로 넘어오므로 파싱이 필요없음 data=JSON.parse(data); var html = "<table width='600' border='1'>"; $.each(data, function(entryIndex, entry) { html += '<tr class="bbb">'; html += '<td class="bgcolor1">' + entry.id + '</td>'; html += '<td class="bgcolor2">' + entry.comment_content + '</td>'; html += '<td class="bgcolor2">' + entry.write_date + '</td>'; html += '<td class="bgcolor2"><input type="button" onclick="rowDelete(this)" value='+ entry.comment_num+'></td>'; html += '</tr>'; }); html += '</table>'; $("#show_comment").html(html);
$('.textcomment').val(''); }, error : function(xhr) { alert("error html = " + xhr.statusText); } }); });
var flag = false; $('#btnwrite').click(function() {
if (flag == true) { $('#write_show').attr('style', 'display:none'); flag = false; } else { $('#write_show').attr('style', 'display:inline'); flag = true; }
}); }); function rowDelete(obj){ $.ajax({ type : "POST", url : "/bbs2/comment/delComment.ktds", async : true, dataType : "json", data : { article_num : $('#article_num').val(), comment_num : $(obj).val() }, success : function(data) { // json으로 넘어오므로 파싱이 필요없음 data=JSON.parse(data); var html = "<table width='600' border='1'>"; $.each(data, function(entryIndex, entry) { html += '<tr class="bbb">'; html += '<td class="bgcolor1">' + entry.id + '</td>'; html += '<td class="bgcolor2">' + entry.comment_content + '</td>'; html += '<td class="bgcolor2">' + entry.write_date + '</td>'; html += '<td class="bgcolor2"><input type="button" onclick="rowDelete(this)" value='+ entry.comment_num+'></td>'; html += '</tr>'; }); html += '</table>'; $("#show_comment").html(html); }, error : function(xhr) { alert("error html = " + xhr.statusText); } }); } |
위 설정은 Http 요청의 바디 정보를 Controller 메소드의 인수로서 받아, HTTP 응답의 바다에
설정할 정보를 직접 Return 하는 방식이다.
HTTP 요청/응답의 바디와 자바 객체를 서로 변환해줄 필요가 있다. 이 때, 이 변환을 해주는 것이 HttpMessageConverter 객체이다. 이 객체가 Http 메시지를 서로 변환해주는 객체이다.
보통 <context:annotation-config/>
HttpMessageConverter 를 위해 <mvc:annotation-driven/> 을 사용한다.
이는 HttpMessageConverter 를 기본적으로 자동 등록하기 때문이다
이 방법에 단점은 날짜가 제대로 출력 되지 않는 점이다.
클라이언트 측에서 날짜를 변경해도 보안 상의 문제가 없을 경우에는
script 를 이용해서 변환해주면 되고, 보안 상의 문제가 있을 경우에는 서버 단에서
포맷을 설정하여 전송하면 된다
먼저, Json 사용을 위한 라이브러리 두 개를 위에서 다운로드 하였으므로, 바로 진행한다.
commtentVO.java 中
1 2 3 4 | @JsonSerialize(using=Write_Formatting.class) public Timestamp getWrite_date() { return write_date; } |
포맷을 설정하기 위한 VO(또는 DTO) 에 시간의 getter 에 @JsonSerialize Annotation을 위와 같이 설정한다.
해당 클래스의 대한 내용은 아래와 같다.
Write_Formatting.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import java.io.IOException; import java.sql.Timestamp; import java.text.SimpleDateFormat; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.map.JsonSerializer; import org.codehaus.jackson.map.SerializerProvider; public class Write_Formatting extends JsonSerializer<Timestamp> { @Override public void serialize(Timestamp comment_date, JsonGenerator gen, SerializerProvider arg2) throws IOException, JsonProcessingException { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:SS"); String formattedDate = formatter.format(comment_date); gen.writeString(formattedDate); } } |
이 부분만 구현하여 사용하면 정상적인 시간 값을 출력해 줄 수 있다.
포맷은 SimpleDateFormat 에서 알아서 원하는 표현 식으로 사용하면 된다.
TIP.
<context:annotation-config/>
@autowired, @resource를 이용할 때의 선언이다.
context:component-scan 이나 mvc:adnnotation-driven이 bean 정의 파일에 기술되어 있으면 생략할 수 있다.
2. MappingJacksonJSONView( 대소문자 오류 남 )
- BeanNameViewResolver
Controlloer 의 소스의 일부분을 보면 아래와 같다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @RequestMapping("writeComment.ktds") public ModelAndView writeComment(HttpServletRequest req) { int article_num = Integer.parseInt((req.getParameter("article_num"))); String comment = req.getParameter("comment"); HttpSession ss = req.getSession(); String id = (String) ss.getAttribute("id"); cs.insertComm(article_num, comment, id); mav = new ModelAndView(); mav.addObject("commentList", cs.getAllComment(article_num)); mav.setViewName("JSON"); return mav; } |
ModelAndView에 List를 담고 setViewName에 "JSON"이라 명하고 리턴한다.
여기서 중요한 점은 MappingJacksonJSONView 에서의 id를 "JSON"과 맞추는 것이다. 설정 파일을 보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.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-3.1.xsd"> <context:component-scan base-package="com.ktds.comment"></context:component-scan> <mvc:annotation-driven /> <bean id="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean id="JSON" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"> <property name="extractValueFromSingleKeyModel" value="true" /> </bean> </beans> |
BeanNameViewReslover 와 MappingJacksonJsonView 를 등록해줘야 결과를 얻을 수 있다.
BeanNameViewResolver
- Bean의 이름(ID)를 이용해서, View로 대신 사용하기 위한 Bean을 찾는 클래스
- setViewName 의 이름을 bean 중에서 찾는다.
MappingJacksonJsonView
- Model 의 저장된 Object를 JSON 형태로 변환하여 View 로 만들어주는 클래스
한 가지 중요한 TIP으로, extractValueFromSingleKeyModel 의 value를 true 하는 부분이다.
실제로 저 property가 존재 하지 않을 경우에는 ModelAndView에서 addObject시 이름을 지정하는 부분으로 JSON Data 를 한번 감싸서 전송한다. 이것에 대한 처리는 스크립트에서 처리 할 수 있지만, 기존의 사용하던 여러 Data가 전송될 때, 바로 사용하기 위해서 위 Property를 이용하면 된다.
다른 방법은 MappingJacksonJsonView 를 상속 받은 클래스를 직접 만들어서,
filter를 수정하는 방법이 있는데 이는, 인터넷 검색을 해보도록 한다.
2. PathVariable ( 나중에 더 공부 )
Path 에 넘어 오는 값을 이용한 처리를 할 때 필요한 Annotation
Id, 또는 그 url 자체에 기능에 따라 필요한 주소를 넘길 수가 있다.
'생활코딩 > Spring' 카테고리의 다른 글
스프링 - 파일 다운로드 (0) | 2014.03.04 |
---|---|
스프링 배우기 - Bean Factory (0) | 2014.03.03 |
스프링 배우기 - pom.xml , JDBC Template (1) (0) | 2014.03.03 |
스프링 배우기 - JDBC Template (2) (0) | 2014.03.03 |
스프링 배우기 - 파일 업로드 (1) | 2014.03.03 |
- Total
- Today
- Yesterday
- @Access
- learning javascript
- 스프링 부트
- log4jdbc
- summernote
- 정적 파일
- 한성키보드
- AngularJS
- Spring
- jsonify
- telegram bot
- Spring Boot
- Excel
- static resources
- mybatipse
- 자바스크립트
- 쿼리 로그
- bootstrap
- AOP
- offline.js
- jQuery 삽입
- 오프라인 확인
- java
- spring jpa
- GO1104 LED
- 초대장
- @Temporal
- 브라우저 콘솔
- WYSIWYG
- RollingFileAppender
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |