diff --git a/examples/boot-api/pom.xml b/examples/boot-api/pom.xml
index 5804df7c..868fbf1c 100644
--- a/examples/boot-api/pom.xml
+++ b/examples/boot-api/pom.xml
@@ -22,6 +22,7 @@
1.4.6
1.10
2.2.0
+
1.3.176
1.7
@@ -124,6 +125,17 @@
org.springframework.boot
spring-boot-maven-plugin
+
+ org.flywaydb
+ flyway-maven-plugin
+ 3.1
+
+ org.h2.Driver
+ jdbc:h2:file:~/.h2/bootapi;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1;
+ sa
+
+
+
diff --git a/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/AccountEndPoint.java b/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/AccountEndPoint.java
index f026556a..e9640d91 100644
--- a/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/AccountEndPoint.java
+++ b/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/AccountEndPoint.java
@@ -1,15 +1,18 @@
package org.springside.examples.bootapi.api;
+import java.util.Collections;
+import java.util.Map;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
-import org.springside.examples.bootapi.api.support.RestException;
import org.springside.examples.bootapi.service.AccountService;
+import org.springside.examples.bootapi.service.ServiceException;
+import org.springside.examples.bootapi.service.exception.ErrorCode;
import org.springside.modules.web.MediaTypes;
// Spring Restful MVC Controller的标识, 直接输出内容,不调用template引擎.
@@ -21,14 +24,16 @@ public class AccountEndPoint {
@Autowired
private AccountService accountServcie;
- @RequestMapping(value = "/api/accounts/login", produces = MediaTypes.TEXT_PLAIN_UTF_8)
- public String login(@RequestParam("email") String email, @RequestParam("password") String password) {
+ @RequestMapping(value = "/api/accounts/login", produces = MediaTypes.JSON_UTF_8)
+ public Map login(@RequestParam("email") String email, @RequestParam("password") String password) {
if (StringUtils.isEmpty(email) || StringUtils.isEmpty(password)) {
- throw new RestException("User or password empty", HttpStatus.BAD_REQUEST);
+ throw new ServiceException("User or password empty", ErrorCode.BAD_REQUEST);
}
- return accountServcie.login(email, password);
+ String token = accountServcie.login(email, password);
+
+ return Collections.singletonMap("token", token);
}
@RequestMapping(value = "/api/accounts/logout")
@@ -41,7 +46,7 @@ public class AccountEndPoint {
@RequestParam("password") String password) {
if (StringUtils.isEmpty(email) || StringUtils.isEmpty(name) || StringUtils.isEmpty(password)) {
- throw new RestException("User or name or password empty", HttpStatus.BAD_REQUEST);
+ throw new ServiceException("User or name or password empty", ErrorCode.BAD_REQUEST);
}
accountServcie.register(email, name, password);
diff --git a/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/BookEndpoint.java b/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/BookEndpoint.java
index 24c76983..9e34e00c 100644
--- a/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/BookEndpoint.java
+++ b/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/BookEndpoint.java
@@ -18,6 +18,8 @@ import org.springside.examples.bootapi.dto.BookDto;
import org.springside.examples.bootapi.service.AccountService;
import org.springside.examples.bootapi.service.BookAdminService;
import org.springside.examples.bootapi.service.BookBorrowService;
+import org.springside.examples.bootapi.service.ServiceException;
+import org.springside.examples.bootapi.service.exception.ErrorCode;
import org.springside.modules.mapper.BeanMapper;
import org.springside.modules.web.MediaTypes;
@@ -53,7 +55,7 @@ public class BookEndpoint {
@RequestMapping(value = "/api/books", method = RequestMethod.POST, consumes = MediaTypes.JSON_UTF_8)
public void createBook(@RequestBody BookDto bookDto,
@RequestParam(value = "token", required = false) String token) {
-
+ checkToken(token);
// 使用Header中的Token,查找登录用户
Account currentUser = accountService.getLoginUser(token);
@@ -67,6 +69,7 @@ public class BookEndpoint {
@RequestMapping(value = "/api/books/{id}/modify", method = RequestMethod.POST, consumes = MediaTypes.JSON_UTF_8)
public void modifyBook(@RequestBody BookDto bookDto,
@RequestParam(value = "token", required = false) String token) {
+ checkToken(token);
Account currentUser = accountService.getLoginUser(token);
Book book = BeanMapper.map(bookDto, Book.class);
adminService.modifyBook(book, currentUser.id);
@@ -74,6 +77,7 @@ public class BookEndpoint {
@RequestMapping(value = "/api/books/{id}/delete")
public void deleteBook(@PathVariable("id") Long id, @RequestParam(value = "token", required = false) String token) {
+ checkToken(token);
Account currentUser = accountService.getLoginUser(token);
adminService.deleteBook(id, currentUser.id);
}
@@ -81,6 +85,7 @@ public class BookEndpoint {
@RequestMapping(value = "/api/books/{id}/request")
public void applyBorrowRequest(@PathVariable("id") Long id,
@RequestParam(value = "token", required = false) String token) {
+ checkToken(token);
Account currentUser = accountService.getLoginUser(token);
borrowService.applyBorrowRequest(id, currentUser);
}
@@ -88,6 +93,7 @@ public class BookEndpoint {
@RequestMapping(value = "/api/books/{id}/cancel")
public void cancelBorrowRequest(@PathVariable("id") Long id,
@RequestParam(value = "token", required = false) String token) {
+ checkToken(token);
Account currentUser = accountService.getLoginUser(token);
borrowService.cancelBorrowRequest(id, currentUser);
}
@@ -95,6 +101,7 @@ public class BookEndpoint {
@RequestMapping(value = "/api/books/{id}/confirm")
public void markBookBorrowed(@PathVariable("id") Long id,
@RequestParam(value = "token", required = false) String token) {
+ checkToken(token);
Account currentUser = accountService.getLoginUser(token);
borrowService.markBookBorrowed(id, currentUser);
}
@@ -102,6 +109,7 @@ public class BookEndpoint {
@RequestMapping(value = "/api/books/{id}/reject")
public void rejectBorrowRequest(@PathVariable("id") Long id,
@RequestParam(value = "token", required = false) String token) {
+ checkToken(token);
Account currentUser = accountService.getLoginUser(token);
borrowService.rejectBorrowRequest(id, currentUser);
}
@@ -109,12 +117,14 @@ public class BookEndpoint {
@RequestMapping(value = "/api/books/{id}/return")
public void markBookReturned(@PathVariable("id") Long id,
@RequestParam(value = "token", required = false) String token) {
+ checkToken(token);
Account currentUser = accountService.getLoginUser(token);
borrowService.markBookReturned(id, currentUser);
}
@RequestMapping(value = "/api/mybook", produces = MediaTypes.JSON_UTF_8)
public List listMyBook(@RequestParam(value = "token", required = false) String token, Pageable pageable) {
+ checkToken(token);
Account currentUser = accountService.getLoginUser(token);
List books = adminService.listMyBook(currentUser.id, pageable);
return BeanMapper.mapList(books, BookDto.class);
@@ -123,8 +133,15 @@ public class BookEndpoint {
@RequestMapping(value = "/api/myborrowedbook", produces = MediaTypes.JSON_UTF_8)
public List listMyBorrowedBook(@RequestParam(value = "token", required = false) String token,
Pageable pageable) {
+ checkToken(token);
Account currentUser = accountService.getLoginUser(token);
List books = borrowService.listMyBorrowedBook(currentUser.id, pageable);
return BeanMapper.mapList(books, BookDto.class);
}
+
+ private void checkToken(String token) {
+ if (token == null) {
+ throw new ServiceException("No token in request", ErrorCode.NO_TOKEN);
+ }
+ }
}
diff --git a/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/support/RestException.java b/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/support/RestException.java
deleted file mode 100644
index b32e6eaa..00000000
--- a/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/support/RestException.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.springside.examples.bootapi.api.support;
-
-import org.springframework.http.HttpStatus;
-
-public class RestException extends RuntimeException {
-
- private static final long serialVersionUID = -8634700792767837033L;
-
- public HttpStatus status;
-
- public RestException(String message, HttpStatus status) {
- super(message);
- this.status = status;
- }
-}
diff --git a/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/support/RestExceptionHandler.java b/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/support/RestExceptionHandler.java
deleted file mode 100644
index 5f27d46e..00000000
--- a/examples/boot-api/src/main/java/org/springside/examples/bootapi/api/support/RestExceptionHandler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.springside.examples.bootapi.api.support;
-
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.ControllerAdvice;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.context.request.WebRequest;
-import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
-import org.springside.modules.web.MediaTypes;
-
-@ControllerAdvice
-public class RestExceptionHandler extends ResponseEntityExceptionHandler {
-
- @ExceptionHandler(value = { RestException.class })
- public final ResponseEntity> handleException(RestException ex, WebRequest request) {
- logger.error(ex.getMessage(), ex);
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.parseMediaType(MediaTypes.TEXT_PLAIN_UTF_8));
- return new ResponseEntity