Spring Boot + Gradle + Websocket 构建推送服务
2016-05-11 17:26
846 查看
Spring Boot + Gradle + Websocket 构建推送服务
介绍
Spring Boot经过长期的发展,已经逐渐成为我微服务开发的首选,本文以构建推送微服务为例,演示如何使用spring boot进行高效的微服务开发。使用的相关技术
gradlespring boot及其starters
websocket
mongodb
apns
docker
Gradle
作为后起之秀,既支持原有的Maven仓库,又拥有简洁的语法,不仅仅可以做依赖管理,更是一个便捷的构建工具。可以说是不二之选。build.gradle
buildscript { repositories { jcenter() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE") } } apply plugin: 'java' apply plugin: 'spring-boot' repositories { jcenter() } dependencies { compile("org.springframework.boot:spring-boot-starter-web") testCompile("org.springframework.boot:spring-boot-starter-test") }
Sprnig Boot
Starter
使用Spring boot比较简单,只要引用需要的starter即可。spring-boot-starter-web web项目必选,自动包含了tomcat及spring-webmvc
spring-boot-starter-data-mongodb 我们使用mongodb数据库,直接使用spring data的mongodb支持,声明式的数据库访问,效率大大提升。
spring-boot-starter-websocket websocket支持
spring-boot-starter-security spring security支持,通用选择
spring-boot-starter-actuator 生产特性支持,这个也是利器,devops首选。
Dev tools
优秀的框架首先是对开发者友好,spring boot在这方面做的不错,Hot swapping特性使得开发时不用频繁启动服务。本人使用的是IntelliJ IDEA,稍微麻烦些,IDEA的自动编译功能在程序运行或调试时不起作用,只能用Ctrl+F9
Hot swapping 在IDEA的配置如下:
build.gradle
buildscript { repositories { jcenter() } dependencies { classpath "org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE" classpath "org.springframework:springloaded:1.2.6.RELEASE" } } ... apply plugin: 'idea' idea { module { inheritOutputDirs = false outputDir = file("$buildDir/classes/main/") } }
这样,每次修改代码后手动Ctrl+F9就直接生效了。不过如果涉及到方法接口改变等还是需要重启服务的。
应用配置
spring boot支持properties和yaml两种方式,本人推荐使用yaml方式,缩进方式更易读。application.yaml
spring: data: mongodb: uri: mongodb://localhost:27017/onepush pushserver: env: DEV #开发或正式 server: port: 8080 ...
引用自定义配置也特别容易,直接使用@ConfigurationProperties即可。
如:PushServerConfig.java
@ConfigurationProperties(prefix="pushserver") public class PushServerConfig { private String env; get,set methods... }
就会自动引用pushserver下相同名称的配置项。
validation
Spring 提供了Validator支持,提供了一些辅助类帮助开发者实现自定义校验逻辑。实现步骤:
- 实现自定义校验类
PushValidator.java
@Component public class PushValidator implements Validator{ @Override public boolean supports(Class<?> clazz) { return UserDevice.class.equals(clazz) || PushRequest.class.equals(clazz); } @Override public void validate(Object obj, Errors e) { ValidationUtils.rejectIfEmptyOrWhitespace(e, "appId", "field.required", new String[]{"appId"}); ... } }
在controller中启用,将validator增加到binder中,使用@Valid … BindingResult bindResult即可
PushController.java
@InitBinder public void initBinder(DataBinder binder) { binder.setValidator(validator); } @RequestMapping(value="/register", method= RequestMethod.POST) Map<String,String> register(@Valid @RequestBody UserDevice userDevice, BindingResult bindResult) { if (bindResult.hasErrors()) { throw new PushParameterException(getErrorString(bindResult)); } ...
异常处理
定义两类应用异常:PushParameterException – 请求参数错误类异常
PushServiceException – 服务处理类异常
区分这两类异常的主要作用是方便客户端针对不同异常可能会采用不同的错误处理机制。
如对于参数错误类异常提醒用户修改参数重新请求,对于服务处理类异常可以采用重试机制。
针对这两类异常,实现一个统一的应用异常处理程序。
PushExceptionAdvice.java
@ControllerAdvice public class PushExceptionAdvice extends ResponseEntityExceptionHandler{ @ExceptionHandler(PushParameterException.class) public ResponseEntity<ErrorResponse> handleParameterException(PushParameterException e) { ErrorResponse er = null; if (pushServerConfig.isProd()) { er = new ErrorResponse(e.getCode(),e.getMessage(),null); } else { er = new ErrorResponse(e.getCode(),e.getMessage(),e.getCause()); } return new ResponseEntity<ErrorResponse>(er, HttpStatus.BAD_REQUEST); } @ExceptionHandler(PushServiceException.class) public ResponseEntity<ErrorResponse> handleServiceException(PushServiceException e) { ErrorResponse er = null; if (pushServerConfig.isProd()) { er = new ErrorResponse(e.getCode(),e.getMessage(),null); } else { er = new ErrorResponse(e.getCode(),e.getMessage(),e.getCause()); } return new ResponseEntity<ErrorResponse>(er, HttpStatus.SERVICE_UNAVAILABLE); } }
其它
本项目已经上传到github,欢迎下载。相关文章推荐
- JDBC批处理---(java 对数据库的回滚) .
- 使用Spring进行切面(AOP)编程
- java jaxbContext convert bean to xml
- Char 转int JAVA
- java
- 解决JAVA调用mysqldump备份数据库时文件为空的问题
- [置顶] java 笑脸代码
- Java LinkedHashMap工作原理及实现(二)
- JAVA中this用法小结
- java多线程的实现
- Struts基础
- java性能优化之三 优雅平滑的结束quarts 任务
- Java读取txt文件编码格式
- java常用的编辑器之kindeditor
- 算法提高 身份证号码升级 JAVA
- java动态编译
- eclipse总是报错:Building workspace has encountered a problem.errors occurred
- spring 根上下文和 spring dispatcherServlet 上下文的关系
- java.io.Reader 和 java.io.InputStream的区别
- javaw.exe是什么?两个class文件可以同事运行