@ResponseBody

반응형

안녕하세요 무작정 일단 따라 해 보는 Spring 커뮤니티 만들기 4탄 시작합니다.

 

환경

Eclipse 2019-9 Jee
JDK 1.8_231
Apache Tomcat 8.5.47
MariaDB 10.4.10
MyBatis 3.2.2
+ JSTL 1.2
+ jackson 2.9.4

오늘의 할 일

1.URL 8080,프로젝트 명 제거
2.JSTL,EL 설정
3.게시판 CRUD 기능 만들기

 

시작하기에 앞서 지금 상태에서 Run on Server 하시면

http://localhost:8080/springEx01/ 이렇게 8080이랑 springEx01이라는 프로젝트명이 붙는걸 보시게 되는데요

이걸 안보이게 하려면 설정을 조금 해줘야합니다.

 

 

8080 포트와 프로젝트명 URL에서 없애기

이클립스 하단 Servers 클릭 -> Tomcat v8.5 Server at localhost 더블 클릭 -> Overview 클릭 -> HTTP/1.1 PortNumber 8080에서 80으로 변경


그리고 저장 바로 Modules 클릭 -> 해당 프로젝트 클릭 Edit… 버튼 클릭 -> Path 프로젝트명 지우고 "/" 만 남기고 저장 "/" 남겨야 합니다.

짜잔! URL 깔끔해진 모습

index.jsp a 태그 href <a href="/view/dashboard">대시보드 보러가기</a> 이렇게 변경해줍니다.

 

현재 인덱스 페이지와 대시보드 페이지만 존재하고 있는데요.

일단 대시보드 페이지에 게시판 리스트를 보여주고 작성,수정,삭제는 다른 페이지에서 진행하겠습니다.

로그인은 다음 5장에서 다룹니다.

 

먼저 JSP에서 Java 코드<%= %> 쓴다면 가독성이 매우 떨어지므로 저희는 JSTL & EL ${} 이라는걸 사용하겠습니다.

 

새로운 라이브러리를 추가할 ? 정답! pom.xml

pom.xml 디펜던시<dependency> 추가

<!-- jstl dependecy -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

<dependency> 추가 후

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 문구를 JSTL & EL 태그를 사용 할

JSP 파일 최상단에 넣어주면 되는데요. Prefix="c"말고도 여러 개가 있으므로

include 전용 JSP 만들어줍니다.

 

 

views -> jstlHeader.jsp 생성


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

 

이제 JSTL,EL 태그를 사용할 JSP 페이지 <!DOCTYPE html> 위에 넣어주시면 됩니다.

<%@ include file="/WEB-INF/views/jstlHeader.jsp" %>

 

그럼 준비가 끝났으니 본격적으로 게시판 만들기 CRUD 시작합니다.

먼저 CRUD R(read)부터 만들겠습니다.

 

대시보드에 들어가면 제일 먼저 게시판 리스트가 보이도록 만들 예정입니다.

리스트를 보여주려면 먼저 DB에서 데이터를 Select 해와야겠죠


ViewController.java

@RequestMapping("view/dashboard") 
public ModelAndView dashboard() { 
List result = boardService.getBoardList();  
ModelAndView mav = new ModelAndView(); 

mav.addObject("result",result); 

return mav; 
}

BoardService.java

List getBoardList();

BoardServiceImpl.java

public List<Board> getBoardList() {
return boardDAO.getBoardList(); }

BoardDAO.java

public List<Board> getBoardList() {	
return sqlSession.selectList("getBoardList"); }

board-Mapper.xml

<select id="getBoardList" resultType="board">
SELECT * FROM board order BY id DESC;
</select>

 

원래 작성 순서는 Mapper -> DAO -> Service -> Controller 순이지만 일단 익숙지 않은 분들을 위해 Controller부터 작성하였습니다.

dashboard.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/jstlHeader.jsp" %>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>dashboard</title>
<style>
  table {
    width: 100%;
    border: 1px solid #444444;
  }
  th, td {
    border: 1px solid #444444;
  }
</style>
</head>
<body>
<p>dashboard</p>
<div>게시글 리스트</div>
<table>
<thead><tr>
<td>제목</td>
<td>조회수</td>
<td>좋아요</td>
<td>첨부파일</td>
<td>글 작성 날짜</td>
</tr></thead>

<c:forEach var="b" items="${result }">
<fmt:formatDate value="${b.create_time}" pattern="yyyy-MM-dd HH:MM:ss" var="dateFormat_cr"/>
<tr>
<td>${b.subject }</td>
<td>${b.views }</td>
<td>${b.likes }</td>
<td>${b.attachments }</td>
<td>${dateFormat_cr }</td>
</tr>
</c:forEach>
</table>
<div> <a href="/view/boardwrite">글 작성하기</a></div>
</body>
</html>

 

UI는 아직 허접하지만 일단 게시판 리스트가 잘 출력되는 모습입니다.

이제 글 작성하기 링크를 누르면 글을 작성할 수 있게 C(Create)를 만들어봅시다.


 

먼저 작성을 다 한 후 jQuery ajax를 이용한 POST 방식을 사용할 겁니다.

views -> view -> boardwrite.jsp 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> 
<meta charset="UTF-8">
<title>글 작성</title>
<script type="text/javascript">

function boardValidation(){
	
	var subject = $("#subject").val();
	var content = $("#content").val();
	
	if(!subject){
		alert("제목 입력은 필수입니다.");
		$("#subject").focus();
		return false;
	}else if(!content){
		alert("내용 입력은 필수 입니다.");
		$("#content").focus();
		return false;
	}else {
		boardWrite(subject,content);
	}
	
}

function boardWrite(sub,con){
	
	$.ajax({
		
		url : "/jquery/boardwrite",
		type:'POST',
		data : {
			subject : sub,
			context : con
		},
		success:function(data){
			if(data == 1){
				alert("글 등록이 완료되었습니다.");
				location.href="/view/dashboard";
			}else {
				alert("글 등록 실패");
			}
		},error:function(){
			console.log("error");
		}
		
	})
	
}

</script>
</head>
<body>
<form>
<table>
        <caption>게시판 글쓰기 </caption>
    <tbody>
            <tr>
                <th>제목: </th>
                <td><input type="text" placeholder="제목을 입력하세요. " id="subject"/></td>
            </tr>
            <tr>
                <th>내용: </th>
                <td><textarea cols="30" rows="10" placeholder="내용을 입력하세요. " id="content"></textarea></td>
            </tr>
           <!--  <tr>
                <th>첨부파일: </th>
                <td><input type="text" placeholder="파일을 선택하세요. " name="filename"/></td>
            </tr> -->
            <tr>
                <td colspan="2">
                    <input type="button" value="등록" onclick="boardValidation()"/>
                    <input type="button" value="뒤로" onclick="javascript:location.href='dashboard'"/>
                </td>
            </tr>
    </tbody>
</table>
</form>
</body>
</html>

jQuery 플러그인이 필요하겠죠 저희는 *CDN 방식으로 받겠습니다.

boardwrite.jsp <head></head>안에 넣어줍니다.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

*CDN :콘텐츠 전송 네트워크(Content delivery network)는 콘텐츠를 효율적으로 전달하기 위해 여러 노드를 가진 네트워크에 데이터를 저장하여 제공하는 시스템을 말한다. 인터넷 서비스 제공자에 직접 연결되어 데이터를 전송하므로, 콘텐츠 병목을 피할 수 있는 장점이 있다


 

하지만 Spring 입장에선 boardwrite.jsp를 못 찾겠죠?

무조건 jsp를 view로 등록할 땐 Controller에서 받아줘야 합니다.

 

ViewController.java

@RequestMapping(value="view/boardwrite",method = RequestMethod.GET)
	public ModelAndView boardwrite() {
		ModelAndView mav = new ModelAndView();
		return mav; }

그리고 위에 boardWrite() 메서드를 보시면 URL를 /jquery/boardwrite로 보내고 있죠

저희는 Controller의 용도를 나눠서 가독성이 좋도록 할 겁니다.

 

ViewController.java : View를 보여주는(연결해주는) Controller

JqueryController.java : jquery + ajax를 이용한 메서드들

 

자 그럼 JqueryController.java를 만들어야겠죠

src/main/java -> controller -> JqueryController.java 생성

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.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.company01.springEx01.logic.Board;
import com.company01.springEx01.service.BoardService;

@Controller
@RequestMapping("jquery/*")
public class JqueryController {

	@Autowired
	BoardService boardService;
	
	@RequestMapping(value="jquery/boardwrite",method = RequestMethod.POST)
	@ResponseBody
	public int boardwrite(Board board) {
		int result = 0; 
		result = boardService.boardwrite(board); 
		return result;
	}
	
}

@ResponseBody : json으로 응답해주는 어노테이션

 

여기서 보면 boardwrite 메서드의 리턴 타입이 int라고 돼있는데

어라? 저는 int로 리턴하면 String or Object로 리턴하라고 에러가 나던데요? 네 맞습니다.

 

원래 스프링은 Model 객체를 리턴해 "view"를 보여주려고 하는 성질이 존재하는데,

갑자기 int를 리턴해버리면 처음부터 형태가 맞지 않다며 예외를 뱉습니다.

 

그럼 아예 값을 리턴해주는 JSON 형태로 던져주면 어떨까요? 네 바로 그 작업을 하는 것입니다.

 

 

pom.xml

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>

BoardService.java

int boardwrite(Board board);

BoardServiceImpl.java

@Override
public int boardwrite(Board board) {
return boardDAO.boardwrite(board);}

BoardDAO.java

public int boardwrite(Board board) {
return sqlSession.insert("boardwrite",board);
}

board-Mapper.xml

<insert id="boardwrite">
insert into board (id,subject,context,attachments,likes,views,create_time,update_time) 
values(#{id},#{subject},#{context},#{attachments},#{likes},#{views},now(),null);
</insert>

만들었으니 한번 해볼까요?

대시보드에 있는 글 작성하기 버튼(링크)을 클릭합니다.


글 작성 UI

일단 첨부파일은 로직이 조금 필요하므로 나중에 하고 제목, 내용만 입력하도록 하였습니다.


글 작성 후 등록


대시보드

짠! 잘 들어왔죠 이제 저 글 제목을 클릭하면 내용을 볼 수 있고, 조회수가 1씩 증가하도록 해보겠습니다.


dashboard.jsp

제목 부분에 a 태그 링크 추가

<td><a href="/view/boardDetail?id=${b.id }">${b.subject }</a></td>

/view/boardDetail 페이지가 없죠? 새로운 페이지 추가 Controller는 뭐였죠??

네 맞습니다!!

ViewController.java

@RequestMapping(value="view/boardDetail",method = RequestMethod.GET)
	public ModelAndView boardDetail(int id) {
		boardService.viewsUpdate(id);
		Board result = boardService.getBoardDetail(id);
		ModelAndView mav = new ModelAndView();
		mav.addObject("result",result);
		return mav;
	}

매개변수 int id : get으로 넘어오는 "id" 매개변수를 받는다.

viewUpdate : 조회수 추가 메서드

getBoardDetail : 특정 글 하나의 데이터를 조회하는 메서드

 

views -> view -> boardDetail.jsp 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/jstlHeader.jsp" %>
<!DOCTYPE html>
<html>
<head>
   
<meta charset="UTF-8">
<title>글 내용</title>
<style>
  table {
    width: 100%;
    border: 1px solid #444444;
  }
  th, td {
    border: 1px solid #444444;
  }
</style>
<script type="text/javascript">
function boardDelete(){
	
	
}

function boardUpdate(){
	
	
}
</script>
</head>
<body>
<form>
<table>
        <caption>게시판 글 내용 </caption>
    <tbody>
            <tr>
                <th>제목: </th>
                <td>${result.subject}</td>
            </tr>
            <tr>
                <th>내용: </th>
                <td>${result.context}</td>
            </tr>
            
            <tr>
                <th>조회수: </th>
                <td>${result.views}</td>
            </tr>
            <tr>
                <th>좋아요: </th>
                <td>${result.likes}</td>
         	</tr>
         	
            <tr>
                <td colspan="2">
                    <input type="button" value="수정" onclick="boardDelete()"/>
                    <input type="button" value="삭제" onclick="boardUpdate()"/>
                    <input type="button" value="목록보기" onclick="javascript:location.href='dashboard'"/>
                </td>
            </tr>
    </tbody>
</table>
</form>
</body>
</html>

 

BoardService.java

Board getBoardDetail(int id);
void viewsUpdate(int id);

BoardServiceImpl.java

@Override
public Board getBoardDetail(int id) {
return boardDAO.getBoardDetail(id);}

@Override
public void viewsUpdate(int id) {
boardDAO.viewUpdate(id);}

BoardDAO.java

public Board getBoardDetail(int id) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("id",id);
		return sqlSession.selectOne("getBoardDetail",map);
	}

public void viewUpdate(int id) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("id",id);
		sqlSession.update("viewUpdate", map);
	}

board-Mapper.xml

<select id="getBoardDetail" resultType="board">
SELECT * FROM board where id = #{id};
</select>

<!-- update -->
<update id="viewUpdate">
UPDATE board SET views = views+1 WHERE id = #{id}
</update>

대시보드

제목에 클릭할 수 있는 링크가 생겼습니다.


글 내용(boardDetail)

내용 페이지에서 새로고침을 하게 되면 조회수가 1씩 증가하는 걸 볼 수 있습니다.

 

삭제와 수정은 아무나 하면 안 되기 때문에 다음 글인 로그인 구현하기를 하고 진행하도록 하겠습니다.

귀찮아서 그런 거 아닙니다.

그럼 다음은 회원가입 그리고 로그인 후 세션 저장까지 해보겠습니다.


최종 Project Explorer

 

반응형

[Spring] annotations 정리

2019. 10. 16. 14:15
반응형

Annotation(어노테이션 || 애너테이션 || 애노테이션)이란?

아하영어사전 - 애너테이션

http://aha-dic.com/View.asp?word=Annotation

대중적인 발음 - 어노테이션

여기선 어노테이션이라 칭하겠음

 

1.본래 주석이란 뜻으로 사용됨

2.인터페이스를 기반으로 문법

3.클래스에 특별한 의미 부여 || 기능 주입 가능

 

종류

1.built-in annotation

) Override

2.Meta annotation

) @Target

3.Custom annotation

)public @interface AnnotationName{}

 

쨋든 글에서 다루어볼것은 Spring 프레임워크에 들어있는 자주쓰이는 기본 어노테이션들을 다루어 보겠습니다.

 

[@Controller]

해당 클래스가 Controller임을 나타내기 위한 어노테이션

 

[@RequestParam]

Controller 메소드의 파라미터와 웹요청 파라미터와 맵핑하기 위한

어노테이션

 

[@ModelAttribute]

Controller 메소드의 파라미터나 리턴값을 Model 객체와 바인딩하기 위한 어노테이션

 

[@SessionAttributes]

Model 객체를 세션에 저장하고 사용하기 위한 어노테이션

 

[@RequestPart]

Multipart 요청의 경우, 웹요청 파라미터와 맵핑 가능한 어노테이션

 

[@CommandMap]

Controller메소드의 파라미터를 Map형태로 받을 때 웹요청 파라미터와 맵핑하기 위한 어노테이션(egov 3.0부터 추가)

 

[@ControllerAdvice]

Controller를 보조하는 어노테이션으로 Controller에서 쓰이는 공통기능들을 모듈화하여 전역으로 쓰기 위한 어노테이션(egov 3.0, Spring 3.2.X부터 추가)

 

[@RequestMapping]

 

이름

타입

설명

value

String[]

URL 값으로 매핑 조건을 부여 (default)

method

RequetMethod[]

HTTP Request 메소드 값을 매핑 조건으로 부여

사용 가능한 메소드는 GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE (7개)

params

String[]

HTTP Request 파라미터를 매핑 조건으로 부여

consumes

String[]

설정과 Content-Type request 헤더가 일치할 경우에만 URL이 호출됨

produces

String[]

설정과 Accept request 헤더가 일치할 경우에만 URL이 호출됨

 

 

[@ResponseBody

이 어노테이션이 붙으면 View Page를 리턴하는게 아니고 '데이터'를 리턴합니다.

즉, return type이 String이며 "home"이라는 문자열을 되돌려준다고 가정해볼께요.

@ResponseBody 어노테이션을  안붙이면 "home.jsp" 페이지를 보여주지만

어노테이션을 붙이게되면 "home"이라는 문자열 자체를 보여주게됩니다. 

 

[@RequestBody]

보통 AJAX + JSON을 사용할때 사용하는 어노테이션

요청받은 데이터의 Body(내용)의 전체내용을 파라메터로 받습니다.

 

View페이지의 AJAX요청의 contentType이 "application/json"이면 @RequestBody 어노테이션을 통해서만

웹서버에서 내용을 받을 수 있어요.

 

※주의 ResponseBody,RequestBody 문법 헷갈림 

 

[@RestController]

 

스프링 4 부터 @RestController 애노테이션의 경우 기존의 특정한 JSP 같은 뷰를 만들어 내는 것이 아닌REST

  식의 데이터 자체를 서비스하는 것을 말한다.

  - 스프링 3에는 해당 메소드의 리턴 타입에 @ResponseBody 애노테이션을 추가하는 형태로 작성되었다.

  - 기능은 달라진것이 없지만컨트롤러 자체의 용도를 지정한다는 점에서 변화가 있다고   있다.

  - URI 원하는 리소스를 의미한다.(복수형으로 작성)

  - URI에는 식별할  있는 데이터를 같이 전달하는 것이 일반적이다.

 

  // 컨트롤러 위에 어노테이션을 붙혀서 사용한다.

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

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

 

 @RestController

 @RequestMapping("/sample")

 public class RestControllerExampleController {

 

 }

 

 만약 import 오류가 발생하면 maven webmvc 버전을 확인하라.

 

 @RestController JSP 같은 뷰를 만들어 내지 않는 대신에 데이터 자체를 반환하는데이때 주로 사용되는 것은 단순 문자열과 JSON, XML, 등으로 나누어   있다.

 

 

이상 글을 마칩니다. 글은 계속해서 공부하고 싶은 어노테이션들이 추가될 예정입니다.

반응형

+ Recent posts