Download presentation
Presentation is loading. Please wait.
1
Spring 4 기반의 RESTful Web Service 구현
Oct. 2015 Youn-Hee Han
2
RESTful Server
3
Spring 프로젝트 내 pom.xml 수정 REST Web Service 구현을 위한 pom.xml 수정
객체를 XML/JSON로 변환하거나 그 역변환을 위한 라이브러리(의존성) 추가 … <!-- XML and JSON --> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.6.2</version> </dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <artifactId>jackson-databind</artifactId> </dependencies>
4
웹 서비스 Server 구축 (Spring 기반)
Resource 정보 구축 온도 센서 정보를 Resource로 활용 MySQL 활용 Temperature 테이블 내 다음과 같은 정보 저장 온도 센서 HTTP Reqeuest HTTP Response 온도 자원을 활용하는 웹 서비스 Client 온도 자원을 구축하고 있는 자원 서버 + 웹 서비스 Server 구축 (Spring 기반)
5
Resource 정보 구축 온도 센서 정보를 Resource로 활용
현재 사용중인 DB 스키마 (예: wsc)에 Temperature 테이블 생성 및 가상 온도 정보 입력 프로젝트 소스 내 다음 파일 참고 src/main/resources/common/rest.sql DROP TABLE IF EXISTS `temperature`; CREATE TABLE `temperature` ( `ID` int(32) unsigned NOT NULL AUTO_INCREMENT, `sensor_id` varchar(45) NOT NULL, `temperature` float NOT NULL, `datetime` datetime NOT NULL, `location` varchar(500) NOT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; INSERT INTO `temperature` VALUES (1, 'temp1', 32.4, ' :18:24', '1st Floor, 4th Engineering Building, KoreaTech'), (2, 'temp2', 34.9, ' :10:54', '3st Floor, 2th Engineering Building, KoreaTech');
6
Domain 객체 클래스 구성 Temperature 클래스 구성 온도 정보를 담아서 전달시킬 수 있는 기본 클래스
웹 서비스 Server가 Client로 전달할 때 Json 포맷으로 변환됨 프로젝트 소스 내 다음 파일 참고 src/main/java/koreatech/cse/domain/rest/Temperature.java package koreatech.cse.domain.rest; import java.sql.Date; public class Temperature { private int id; private String sensorId; private float temperature; private Date datetime; private String location; public int getId() { return id; } …
7
Repository 객체 클래스 구성 MyBatis기반 TemperatureMapper 인터페이스 구성
src/main/java/koreatech/cse/repository/rest/TemperatureMapper.java package koreatech.cse.repository.rest; … @Repository public interface TemperatureMapper { @Insert("INSERT INTO TEMPERATURE (SENSOR_ID, TEMPERATURE, DATETIME, LOCATION) VALUES (#{sensorId}, #{temperature}, #{datetime}, #{location})") @SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id", before = false, resultType = int.class) void insert(Temperature temperature); @Update("UPDATE TEMPERATURE SET TEMPERATURE = #{temperature}, DATETIME = #{datetime}, LOCATION = #{location} WHERE ID = #{id}") void update(Temperature temperature); @Select("SELECT * FROM TEMPERATURE WHERE ID = #{id}") Temperature int id); @Delete("DELETE FROM TEMPERATURE WHERE ID = #{id}") void int id); @Select("SELECT * FROM TEMPERATURE WHERE SENSOR_ID = #{sensorId}") Temperature String sensorId); @Select("SELECT * FROM TEMPERATURE WHERE LOCATION LIKE CONCAT('%', #{location}, '%')") List<Temperature> String location); }
8
RestController 구성 Spring 4 기반의 RestController 구성
을 활용하여 접근 패스 지정 {Context Root}/thermometer 이전에 생성한 Repository 로 주입받음 프로젝트 소스 내 다음 파일 참조 src/main/java/koreatech/cse/controller/rest/ TemperatureRestController.java package koreatech.cse.controller.rest; … public class TemperatureRestController { @Inject private TemperatureMapper temperatureMapper; … }
9
RestController 구성 GET 서비스 – 1
Path: {Context Root}/thermometer/temperature/{sensorId} 센서 아이디를 받아서 해당 센서의 센싱 정보를 JSON 포맷으로 전달 서비스 요청 예 센서 ID에 해당하는 ‘temp1’은 PathVariable 형태로 활용됨 @Transactional @RequestMapping(value="/temperature/{sensorId}", method=RequestMethod.GET, produces = "application/json") public ResponseEntity<Temperature> String sensorId) { Temperature temperature = temperatureMapper.findOneBySensorId(sensorId); if (temperature == null) { System.out.println("Temperature sensor with id (" + sensorId + “) is not found"); return new ResponseEntity<Temperature>(HttpStatus.NOT_FOUND); } return new ResponseEntity<Temperature>(temperature, HttpStatus.OK);
10
RestController 구성 GET 서비스 – 2
Path: {Context Root}/thermometer/xml/temperature/{sensorId} 센서 아이디를 받아서 해당 센서의 센싱 정보를 XML 포맷으로 전달 서비스 요청 예 method=RequestMethod.GET, produces="application/xml") public ResponseEntity<Temperature> String sensorId) { Temperature temperature = temperatureMapper.findOneBySensorId(sensorId); if (temperature == null) { System.out.println("Temperature sensor with id " + sensorId + " is not found"); return new ResponseEntity<Temperature>(HttpStatus.NOT_FOUND); } return new ResponseEntity<Temperature>(temperature, HttpStatus.OK); }
11
RestController 구성 GET 서비스 – 3
Path: {Context Root}/thermometer/temperature/location/{location} 센서 위치 정보를 받아서 해당 위치 정보를 지니고 있는 센서들의 센싱 정보를 JSON 포맷으로 전달 서비스 요청 예 위치 정보에 해당하는 ‘KoreaTech’는 PathVariable 형태로 활용됨 @Transactional @RequestMapping(value="/temperature/location/{location}", method=RequestMethod.GET, produces="application/json") public ResponseEntity<List<Temperature>> temperatureByLocation( @PathVariable("location") String location) { List<Temperature> temperatureList = temperatureMapper.findByLocation(location); if (temperatureList.size() == 0) { System.out.println("Temperature sensors with location of " + location + " are not found"); return new ResponseEntity<List<Temperature>>(HttpStatus.NOT_FOUND); } return new ResponseEntity<List<Temperature>>(temperatureList, HttpStatus.OK);
12
RestController 구성 GET 서비스 – 4
Path: {Context Root}/thermometer/xml/temperature/location/{location} 센서 위치 정보를 받아서 해당 위치 정보를 지니고 있는 센서들의 센싱 정보를 XML 포맷으로 전달 서비스 요청 예 method=RequestMethod.GET, produces="application/xml") public ResponseEntity<List<Temperature>> temperatureByLocationXml( @PathVariable("location") String location) { List<Temperature> temperatureList = temperatureMapper.findByLocation(location); if (temperatureList.size() == 0) { System.out.println("Temperature sensors with location of " + location + " are not found"); return new ResponseEntity<List<Temperature>>(HttpStatus.NOT_FOUND); } return new ResponseEntity<List<Temperature>>(temperatureList, HttpStatus.OK); }
13
RestController 구성 POST 서비스 (Create a Temperature Resource)
Path: {Context Root}/temperature 새로운 센서 정보를 서버의 자원으로 생성 @Transactional @RequestMapping(value = "/temperature/", method = RequestMethod.POST) public ResponseEntity<Void> Temperature temperature, UriComponentsBuilder ucBuilder) { if (temperatureMapper.findOneBySensorId(temperature.getSensorId()) != null) { System.out.println("A temperature sensor with id (" + temperature.getSensorId() + ") already exists"); return new ResponseEntity<Void>(HttpStatus.CONFLICT); } temperatureMapper.insert(temperature); HttpHeaders headers = new HttpHeaders(); headers.setLocation( ucBuilder.path("/temperature/{sensorId}").buildAndExpand(temperature.getSensorId()).toUri()); return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
14
RestController 구성 PUT 서비스 (Update a Temperature Resource)
Path: {Context Root}/temperature/{sensorId} 기존 센서 정보를 업데이트 @Transactional @RequestMapping(value = "/temperature/{sensorId}", method = RequestMethod.PUT) public ResponseEntity<Void> String sensorId, @RequestBody Temperature temperature) { Temperature storedTemperature = temperatureMapper.findOneBySensorId(sensorId); if (storedTemperature == null) { System.out.println("No temperature sensor with id (" + sensorId + " not found"); return new ResponseEntity<Void>(HttpStatus.NOT_FOUND); } storedTemperature.setTemperature(temperature.getTemperature()); storedTemperature.setLocation(temperature.getLocation()); storedTemperature.setDatetime(temperature.getDatetime()); temperatureMapper.update(storedTemperature); return new ResponseEntity<Void>(HttpStatus.OK);
15
RestController 구성 DELETE 서비스 (Delete a Temperature Resource)
Path: {Context Root}/temperature/{sensorId} 기존 센서 정보를 삭제 @Transactional @RequestMapping(value = "/temperature/{sensorId}", method = RequestMethod.DELETE) public ResponseEntity<Temperature> String sensorId) { Temperature storedTemperature = temperatureMapper.findOneBySensorId(sensorId); if (storedTemperature == null) { System.out.println("No temperature sensor with id (" + sensorId + " not found"); return new ResponseEntity<Temperature>(HttpStatus.NOT_FOUND); } temperatureMapper.delete(storedTemperature.getId()); return new ResponseEntity<Temperature>(HttpStatus.NO_CONTENT);
16
RESTful Client
17
RestClient 생성 Spring 4에서 지원하는 RestTemplate 클래스 활용 서버와 별개의 프로젝트로서 구성
org.springframework.web.client.RestTemplate 서버와 별개의 프로젝트로서 구성 콘솔창에서 임의의 폴더로 이동하여 아래 명령어 수행 새로운 프로젝트 폴더 (restful_client)를 IntelliJ 프로젝트로서 등록 mvn archetype:generate -DgroupId=koreatech.link -DartifactId=restful_client -Dpackage=koreatech.cse.rest.client -Dversion=1.0
18
Spring 프로젝트 내 pom.xml 수정 RestTemplate 활용을 위한 라이브러리(의존성) 추가 …
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.2.1.RELEASE</version> </dependency> </dependencies>
19
Spring 프로젝트 내 pom.xml 수정 객체를 XML/JSON로 변환하거나 그 역변환을 위한 라이브러리(의존성) 추가 …
<!-- XML and JSON --> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.6.2</version> </dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <artifactId>jackson-databind</artifactId> </dependencies>
20
Domain 객체 클래스 구성 Temperature 클래스 구성 온도 정보를 담아서 전달시킬 수 있는 기본 클래스
클라이언트 프로젝트 소스 내 다음 파일 참고 src/main/java/koreatech/cse/rest/client/domain/Temperature.java package koreatech.cse.rest.client.domain; import java.sql.Date; public class Temperature { private int id; private String sensorId; private float temperature; private Date datetime; private String location; public int getId() { return id; } …
21
Domain 객체 클래스 구성 Temperature 클래스내에 toString() 구성
IntelliJ의 코드 자동 생성 기능 사용 서버로 부터 받은 온도 정보 객체를 클라이언트에서 출력하기 위한 목적 @Override public String toString() { return "Temperature{" + "id=" + id + ", sensorId='" + sensorId + '\'' + ", temperature=" + temperature + ", datetime=" + datetime + ", location='" + location + '\'' + '}'; }
22
Domain 객체 클래스 구성 Temperature 클래스내에 toString() 구성
IntelliJ의 코드 자동 생성 기능 사용 서버로 부터 받은 온도 정보 객체를 클라이언트에서 출력하기 위한 목적 @Override public String toString() { return "Temperature{" + "id=" + id + ", sensorId='" + sensorId + '\'' + ", temperature=" + temperature + ", datetime=" + datetime + ", location='" + location + '\'' + '}'; }
23
RESTful Client – CRUD 요청 코드
Spring 4 기반의 RestTemplate 활용 서버의 기본 URI 지정 package koreatech.cse.rest.client; import koreatech.cse.rest.client.domain.Temperature; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import java.net.URI; import java.util.Date; import java.util.List; public class App { public static final String REST_SERVICE_URI = " … }
24
RESTful Client – CRUD 요청 코드
GET 서비스 요청 – 1 private static void getTemperature() { System.out.println("Testing GET METHOD (1) "); RestTemplate restTemplate = new RestTemplate(); try { ResponseEntity<Temperature> temperatureResponseEntity = restTemplate.getForEntity(REST_SERVICE_URI + "/temperature/temp1", Temperature.class); Temperature temperature = temperatureResponseEntity.getBody(); System.out.println(temperature); } catch (HttpClientErrorException e) { System.out.println(e.getStatusCode() + ": " + e.getStatusText()); }
25
RESTful Client – CRUD 요청 코드
GET 서비스 요청 – 2 private static void getTemperatureXml() { System.out.println("Testing GET METHOD (2) "); RestTemplate restTemplate = new RestTemplate(); try { ResponseEntity<Temperature> temperatureResponseEntity = restTemplate.getForEntity(REST_SERVICE_URI + "/xml/temperature/temp1", Temperature.class); Temperature temperature = temperatureResponseEntity.getBody(); System.out.println(temperature); } catch (HttpClientErrorException e) { System.out.println(e.getStatusCode() + ": " + e.getStatusText()); } }
26
RESTful Client – CRUD 요청 코드
GET 서비스 요청 – 3 private static void getTemperatureByLocation() { System.out.println("Testing GET METHOD (3) "); RestTemplate restTemplate = new RestTemplate(); try { ResponseEntity<List> listResponseEntity = restTemplate.getForEntity(REST_SERVICE_URI + "/temperature/location/KoreaTech", List.class); List<Temperature> temperatureList = listResponseEntity.getBody(); for (int i = 0; i < temperatureList.size(); i++) { System.out.println(temperatureList.get(i)); } } catch (HttpClientErrorException e) { System.out.println(e.getStatusCode() + ": " + e.getStatusText()); } }
27
RESTful Client – CRUD 요청 코드
GET 서비스 요청 – 4 private static void getTemperatureByLocationXml() { System.out.println("Testing GET METHOD (4) "); RestTemplate restTemplate = new RestTemplate(); try { ResponseEntity<List> listResponseEntity = restTemplate.getForEntity(REST_SERVICE_URI + "/xml/temperature/location/KoreaTech", List.class); List<Temperature> temperatureList = listResponseEntity.getBody(); for (int i = 0; i < temperatureList.size(); i++) { System.out.println(temperatureList.get(i)); } } catch (HttpClientErrorException e) { System.out.println(e.getStatusCode() + ": " + e.getStatusText()); } }
28
RESTful Client – CRUD 요청 코드
POST 서비스 요청 private static void createTemperature() { System.out.println("Testing POST METHOD "); RestTemplate restTemplate = new RestTemplate(); Temperature temperature = new Temperature(); temperature.setSensorId("temp3"); temperature.setTemperature((float)37.0); temperature.setDatetime(new Date()); temperature.setLocation("2nd Floor, 4th Engineering Building, KoreaTech"); try { URI uri = restTemplate.postForLocation( REST_SERVICE_URI + "/temperature/", temperature, Temperature.class); System.out.println("Location : " + uri.toString()); } catch (HttpClientErrorException e) { System.out.println(e.getStatusCode() + ": " + e.getStatusText()); }
29
RESTful Client – CRUD 요청 코드
PUT 서비스 요청 private static void updateTemperature() { System.out.println("Testing PUT METHOD "); RestTemplate restTemplate = new RestTemplate(); Temperature temperature = new Temperature(); temperature.setSensorId("temp1"); temperature.setTemperature((float)31.1); temperature.setDatetime(new Date()); temperature.setLocation("1st Floor, 4th Engineering Building, KoreaTech"); try { restTemplate.put(REST_SERVICE_URI + "/temperature/temp1", temperature); System.out.println("PUT METHOD - SUCCESS!"); } catch (HttpClientErrorException e) { System.out.println(e.getStatusCode() + ": " + e.getStatusText()); }
30
RESTful Client – CRUD 요청 코드
DELETE 서비스 요청 private static void deleteTemperature() { System.out.println("Testing DELETE METHOD "); RestTemplate restTemplate = new RestTemplate(); try { restTemplate.delete(REST_SERVICE_URI + "/temperature/temp2"); System.out.println("DELETE METHOD - SUCCESS!"); } catch (HttpClientErrorException e) { System.out.println(e.getStatusCode() + ": " + e.getStatusText()); }
31
크롬 앱을 활용한 Rest Client 테스트
Advanced Rest Client 크롬 앱 활용
32
크롬 앱을 활용한 Rest Client 테스트
GET 요청 테스트
33
크롬 앱을 활용한 Rest Client 테스트
POST 요청 테스트
34
크롬 앱을 활용한 Rest Client 테스트
PUT 요청 테스트
35
크롬 앱을 활용한 Rest Client 테스트
DELETE 요청 테스트
Similar presentations