RESTful(7) - RESTful server구현해보기 (간단예제!)
2019. 11. 26. 11:30ㆍ🔴 Spring
300x250
RESTful로 구현한다는 것은
: 하나의 RESTful server → 여러개 APP (=client program)가 접속하도록 만든다는 뜻이다
환경설정
<pom.xml>
<!-- Mybatis설정 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- JSON 사용하기 -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<!-- @Responsebody를 쓰면 객체를 Json으로 반환할 수 있도록 해줌 -->
<version>2.9.8</version>
</dependency>
<servlet-context.xml>
<!-- Mybatis설정 : dataSource, mapper경로 -->
<beans:bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="mapperLocations"
value="classpath:com/bitcamp/mm/mapper/mybatis/*.xml">
</beans:property>
</beans:bean>
<beans:bean id="sqlSession"
class="org.mybatis.spring.SqlSessionTemplate">
<beans:constructor-arg index="0"
ref="sqlSessionFactory" />
</beans:bean>
DAO
DAO interface
package com.bitcamp.mm.member.dao;
import java.util.List;
import java.util.Map;
import com.bitcamp.mm.member.domain.MemberInfo;
import com.bitcamp.mm.member.domain.SearchParam;
public interface MemberSessionDao {
public MemberInfo selectMemberById(String userId);
public int insertMember(MemberInfo memberInfo);
public int selectTotalCount(SearchParam searchParam);
public List<MemberInfo> selectList(Map<String,Object>params);
public List<MemberInfo> selectAllList(); // 전체 리스트 받아옴
public int memberDelete(int id);// 회원 정보 삭제
}
Mapper로 처리 <memberMapper.xml>
<?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">
<!-- DAO interface의 full name을 namespace의 속성으로 사용 -->
<mapper namespace="com.bitcamp.mm.member.dao.MemberSessionDao">
<!-- DB와 이름 맞추기 -->
<resultMap type="com.bitcamp.mm.member.domain.MemberInfo" id="memberResultmap">
<id property="idx" column="idx"/>
<result property="uId" column="uid"/>
<result property="uPw" column="upw"/>
<result property="uName" column="uname"/>
<result property="uPhoto" column="uphoto"/>
<result property="regDate" column="regdate"/>
</resultMap>
<select id="selectMemberById"
resultMap="memberResultmap">
select * from member where uid = #{uId}
</select>
<insert id="insertMember"
parameterType="com.bitcamp.mm.member.domain.MemberInfo">
insert into member (uid, uname, upw, uphoto) values
(#{uId}, #{uName},#{uPw}, #{uPhoto})
</insert>
<select id="selectList" parameterType="map"
resultMap="memberResultmap">
select * FROM member limit #{index}, #{count}
</select>
<select id="selectTotalCount"
parameterType="com.bitcamp.mm.member.domain.SearchParam"
resultType="int">
select count(*) from member
<if test="_parameter != null">
<where>
<if test="'both'.equals(type)">
uid like CONCAT ('%', #{keyword} ,'%')
or uname like CONCAT ('%', #{keyword} ,'%')
</if>
<if test="'id'.equals(type)">
uid like CONCAT ('%', #{keyword} ,'%')
</if>
<if test="'name'.equals(type)">
uname like CONCAT ('%', #{keyword} ,'%')
</if>
</where>
</if>
</select>
<!-- 전체 회원 리스트 구하기 -->
<select id="selectAllList"
resultMap="memberResultmap"
>
select * from member order by uname
</select>
<delete id="memberDelete">
delete from member where idx = #{idx}
</delete>
</mapper>
CONTROLLER
<MemberRestApiController.java>
package com.bitcamp.mm.member.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.bitcamp.mm.member.domain.MemberInfo;
import com.bitcamp.mm.member.domain.MemberRestApiRegRequest;
import com.bitcamp.mm.member.domain.RequestMemberRegist;
import com.bitcamp.mm.member.service.MemberDeleteService;
import com.bitcamp.mm.member.service.MemberListService;
import com.bitcamp.mm.member.service.MemberRegService;
// /rest-api/members GET ---> 전체 리스트, 페이징 처리된 리스트
// /rest-api/members/{id} GET ---> 회원 한명의 정보를 반환(memberInfo객체)
// /rest-api/members POST ---> 회원 정보를 저장
// /rest-api/members/{id} PUT ---> 회원 정보를 수정
// /rest-api/members/{id} DELETE ---> 회원 정보를 삭제
@Controller //
@RequestMapping("/rest-api/members")
public class MemberRestApiController {
@Autowired
private MemberListService listService;
@Autowired
private MemberRegService regService;
@Autowired
private MemberDeleteService deleteService;
// @RequestMapping("/{id}") // = /rest-api/members/{id}
// @CrossOrigin("https://www.naver.com", ...) // 접속 허용 범위 설정
@CrossOrigin
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public List<MemberInfo> getAllList() {
return listService.getAllList();
}
@CrossOrigin
@ResponseBody
@RequestMapping(method = RequestMethod.POST)
public String regMember(@RequestBody RequestMemberRegist regRequest, HttpServletRequest request) {
System.out.println(regRequest);
int result = regService.memberInsert(request,regRequest);
//return "success";
return result>0?"success":"fail";
}
@CrossOrigin
@ResponseBody
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public String deleteMember(
@PathVariable("id") int idx
) {
System.out.println(idx);
int result = deleteService.memberDelete(idx);
return result>0?"success":"fail";
}
}
SERVICE
- getAllList
<MemberListService.java>
package com.bitcamp.mm.member.service;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bitcamp.mm.jdbc.ConnectionProvider;
import com.bitcamp.mm.member.dao.MemberDao;
import com.bitcamp.mm.member.dao.MemberJdbcTemplateDao;
import com.bitcamp.mm.member.dao.MemberSessionDao;
import com.bitcamp.mm.member.domain.ListViewData;
import com.bitcamp.mm.member.domain.MemberInfo;
import com.bitcamp.mm.member.domain.SearchParam;
@Service("listService")
public class MemberListService implements MemberService {
/*
* @Autowired private MemberDao dao;
*/
@Autowired
// private MemberJdbcTemplateDao dao;
private SqlSessionTemplate template;
private MemberSessionDao dao;
final int MEMBER_CNT_LIST = 3;
public ListViewData getListData(int currentPageNumber, SearchParam searchParam) {
// dao 생성
dao = template.getMapper(MemberSessionDao.class);
ListViewData listData = new ListViewData();
// 현재 페이지 번호
listData.setCurrentPageNumber(currentPageNumber);
// 전체 게시물 개수
// int totalCnt = dao.selectTotalCount(conn, searchParam);
int totalCnt = dao.selectTotalCount(searchParam);
int totalPageCnt = 0;
// 전페 페이지 개수
if (totalCnt > 0) {
totalPageCnt = totalCnt / MEMBER_CNT_LIST;
if (totalCnt % MEMBER_CNT_LIST > 0) {
totalPageCnt++;
}
}
listData.setPageTotalCount(totalPageCnt);
// 구간 검색을 위한 index
// 1 -> 0, 2->3, 3->6, 4->9
int index = (currentPageNumber - 1) * MEMBER_CNT_LIST;
// 회원 정보 리스트
// listData.setMemberList(dao.selectList(conn, index, MEMBER_CNT_LIST));
// map으로 삽입
Map<String, Object> params = new HashMap<String, Object>();
params.put("index",index);
params.put("count",MEMBER_CNT_LIST);
listData.setMemberList(dao.selectList(params));
List<MemberInfo> memberList = null;
// 1. 검색 조건이 없는 경우 : selectList -> 전체 회원의 리스트
// 2. id로 검색 : where like uid '%?%'
// 3. name으로 검색 : where like uname '%?%'
// 4. id 또는 name : where like uname '%?%' or like uid '%?%'
// 1-> 9-0 = 9
// 2 -> 9-3 = 6
int no = totalCnt - index;
listData.setNo(no);
listData.setTotalCount(totalCnt);
return listData;
}
public List<MemberInfo> getAllList(){
dao = template.getMapper(MemberSessionDao.class);
List<MemberInfo> list = dao.selectAllList();
return list;
}
}
- regMember
<MemberRegService.java>
package com.bitcamp.mm.member.service;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import com.bitcamp.mm.jdbc.ConnectionProvider;
import com.bitcamp.mm.member.dao.MemberDao;
import com.bitcamp.mm.member.dao.MemberJdbcTemplateDao;
import com.bitcamp.mm.member.dao.MemberSessionDao;
import com.bitcamp.mm.member.domain.MemberInfo;
import com.bitcamp.mm.member.domain.RequestMemberRegist;
@Service("registService")
public class MemberRegService implements MemberService {
/*
* @Autowired private MemberDao dao;
*/
@Autowired
// private MemberJdbcTemplateDao dao;
private SqlSessionTemplate template;
private MemberSessionDao dao;
public int memberInsert(HttpServletRequest request, RequestMemberRegist regist) {
// dao 생성
dao = template.getMapper(MemberSessionDao.class);
// 서버경로
String path = "/uploadfile/userphoto";
// 절대경로
String dir = request.getSession().getServletContext().getRealPath(path);
MemberInfo memberInfo = regist.toMemberInfo();
int resultCnt = 0;
// Connection conn = null;
String newFileName = "";
try {
if (regist.getuPhoto() != null) {
// 새로운 파일 이름 생성
newFileName = memberInfo.getuId() + "_" + regist.getuPhoto().getOriginalFilename();
// conn = ConnectionProvider.getConnection();
// 파일 서버의 지정 경로에 저장
regist.getuPhoto().transferTo(new File(dir, newFileName));
// 데이터베이스 저장을 하기 위한 파일 이름 set
memberInfo.setuPhoto(newFileName);
}
// DB저장
// resultCnt = dao.insertMember(conn, memberInfo);
resultCnt = dao.insertMember(memberInfo);
} catch (IllegalStateException e) {
// TODO: handle exception
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* catch (SQLException e) { // TODO Auto-generated catch block
* e.printStackTrace(); new File(dir, newFileName).delete(); }
*/
return resultCnt;
}
public char idCheck(String id) {
char chk = dao.selectMemberById(id) == null ? 'Y' : 'N';
return chk;
}
public String idCheck1(String id) {
return dao.selectMemberById(id) == null ? "Y" : "N";
}
}
- deleteMember
<MemberDeleteService.java>
package com.bitcamp.mm.member.service;
import java.sql.Connection;
import java.sql.SQLException;
import javax.inject.Inject;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bitcamp.mm.jdbc.ConnectionProvider;
import com.bitcamp.mm.member.dao.MemberDao;
import com.bitcamp.mm.member.dao.MemberSessionDao;
@Service("deleteService")
public class MemberDeleteService implements MemberService {
//@Autowired
//private MemberDao dao;
private MemberSessionDao dao;
@Inject
private SqlSessionTemplate template;
public int memberDelete(int id) {
dao = template.getMapper(MemberSessionDao.class);
return dao.memberDelete(id);
}
}
여러개 client APP
<rest-client.html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<style>
div.card {
float: left;
margin: 2px;
width: 33%;
border: 3px solid;
}
div#memberlist {
overflow: hidden;
}
</style>
</head>
<body>
<h1>회원리스트</h1>
<hr>
<div id="memberlist">
</div>
<script>
$(document).ready(function() {
list();
});
function del(idx) {
if (confirm('삭제하시겠습니까?')) {
$.ajax({
url: 'http://localhost:9090/mm/rest-api/members/' + idx,
type: 'DELETE',
success: function(data) {
//alert(JSON.stringify(data));
if (data == 'success') {
alert('삭제되었습니다');
list();
}
}
});
}
}
function list() {
$.ajax({
url: 'http://localhost:9090/mm/rest-api/members',
type: 'GET',
success: function(data) {
//alert(JSON.stringify(data));
var html = '';
for (var i = 0; i < data.length; i++) {
html += '<div class="card">\n';
html += 'idx : ' + data[i].idx + '<br>\n';
html += 'uId : ' + data[i].uId + '<br>\n';
html += 'uName : ' + data[i].uName + '<br>\n';
html += 'uPhoto : ' + data[i].uPhoto + '\n';
html += '<button onclick="del(' + data[i].idx + ')">삭제하기</button><br>\n';
html += '</div>\n';
}
$('#memberlist').html(html);
}
});
}
</script>
</body></html>
<rest-reg.html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<style>
div.card {
float: left;
margin: 2px;
width: 33%;
border: 3px solid;
}
div#memberlist {
overflow: hidden;
}
</style>
</head>
<body>
<h1>회원가입</h1>
<hr>
<form id="form">
아이디 <input type="text" name="uId" id="uId"><br>
비밀번호 <input type="password" name="uPw" id="uPw"><br>
이름 <input type="text" name="uName" id="uName"><br>
<input type="submit" value="가입">
</form>
<script>
$(document).ready(function() {
/*var list = {
uId: 'idididid',
uPw: 'passsssss',
uName: '홍길동'
};*/
$('#form').submit(function() {
$.ajax({
url: 'http://localhost:9090/mm/rest-api/members',
type: 'POST',
data: JSON.stringify({ //JavaScript 값이나 객체를 JSON 문자열로 변환
uId: $('#uId').val(),
uPw: $('#uPw').val(),
uName: $('#uName').val()
}),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function(data) {
alert(data);
}
});
return false;
});
});
</script>
</body></html>
300x250
'🔴 Spring' 카테고리의 다른 글
RESTful(9) - @RequestEntity, RestTemplate 사용하기 (0) | 2020.05.12 |
---|---|
RESTful(8) - @RequestBody & @ResponseBody란? (0) | 2019.11.26 |
RESTful(6) - @ResponseBody써서 Json형태 객체로 반환해주기 + 상태값 설정 (0) | 2019.11.26 |
RESTful(5) - @JsonIgnore (0) | 2019.11.26 |
RESTful(4) - @RestController 사용하기 (단순문자열, 객체타입, List타입, Map타입) (0) | 2019.11.26 |