我的编程空间,编程开发者的网络收藏夹
学习永远不晚

利用Spring Boot开发REST服务的案例

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

利用Spring Boot开发REST服务的案例

这篇文章主要介绍了利用Spring Boot开发REST服务的案例,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

REST服务介绍

RESTful service是一种架构模式,近几年比较流行了,它的轻量级web服务,发挥HTTP协议的原生的GET,PUT,POST,DELETE。 REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。例如,Amazon.com提供接近REST风格的Web服务进行图书查找;雅虎提供的Web服务也是REST风格的。REST 并非始终是正确的选择。 它作为一种设计 Web 服务的方法而变得流行,这种方法对专有中间件(例如某个应用程序服务器)的依赖比基于 SOAP 和 WSDL 的方法更少。 在某种意义上,通过强调URI和HTTP等早期 Internet 标准,REST 是对大型应用程序服务器时代之前的 Web 方式的回归。

如下图示例:

利用Spring Boot开发REST服务的案例

使用REST的关键是如何抽象资源,抽象得越精确,对REST的应用就越好。

REST服务关键原则:

       1. 给一切物体一个ID

       2.连接物体在一起

       3.使用标准方法

       4.资源多重表述

       5.无状态通信

本文介绍如何基于Spring Boot搭建一个简易的REST服务框架,以及如何通过自定义注解实现Rest服务鉴权

搭建框架

pom.xml

首先,引入相关依赖,数据库使用mongodb,同时使用redis做缓存

注意:这里没有使用tomcat,而是使用undertow

 <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter</artifactId> </dependency> <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope> </dependency> <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId>  <exclusions>  <exclusion>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-tomcat</artifactId>  </exclusion>  </exclusions> </dependency> <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-undertow</artifactId> </dependency> <!--redis支持--> <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--mongodb支持--> <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>

引入spring-boot-starter-web支持web服务

引入spring-boot-starter-data-redis 和spring-boot-starter-data-mongodb就可以方便的使用mongodb和redis了

配置文件

profiles功能

为了方便 区分开发环境和线上环境,可以使用profiles功能,在application.properties里增加
spring.profiles.active=dev

然后增加application-dev.properties作为dev配置文件。

mondb配置

配置数据库地址即可

spring.data.mongodb.uri=mongodb://ip:port/database?readPreference=primaryPreferred

redis配置

spring.redis.database=0 # Redis服务器地址spring.redis.host=ip# Redis服务器连接端口spring.redis.port=6379 # Redis服务器连接密码(默认为空)spring.redis.password=# 连接池最大连接数(使用负值表示没有限制)spring.redis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制)spring.redis.pool.max-wait=-1 # 连接池中的最大空闲连接spring.redis.pool.max-idle=8 # 连接池中的最小空闲连接spring.redis.pool.min-idle=0 # 连接超时时间(毫秒)spring.redis.timeout=0

数据访问

mongdb

mongdb访问很简单,直接定义接口extends MongoRepository即可,另外可以支持JPA语法,例如:

@Componentpublic interface UserRepository extends MongoRepository<User, Integer> { public User findByUserName(String userName);}

使用时,加上@Autowired注解即可。

@Componentpublic class AuthService extends BaseService { @Autowired UserRepository userRepository; }

Redis访问

使用StringRedisTemplate即可直接访问Redis

@Componentpublic class BaseService { @Autowired protected MongoTemplate mongoTemplate; @Autowired protected StringRedisTemplate stringRedisTemplate; }

储存数据:

.stringRedisTemplate.opsForValue().set(token_key, user.getId()+"",token_max_age, TimeUnit.SECONDS);

删除数据:

stringRedisTemplate.delete(getFormatToken(accessToken,platform));

Web服务

定义一个Controller类,加上RestController即可,使用RequestMapping用来设置url route

@RestControllerpublic class AuthController extends BaseController { @RequestMapping(value = {"/"}, produces = "application/json;charset=utf-8", method = {RequestMethod.GET, RequestMethod.POST}) @ResponseBody public String main() { return "hello world!"; }}

现在启动,应该就能看到hello world!了

服务鉴权

简易accessToken机制

提供登录接口,认证成功后,生成一个accessToken,以后访问接口时,带上accessToken,服务端通过accessToken来判断是否是合法用户。

为了方便,可以将accessToken存入redis,设定有效期。

  String token = EncryptionUtils.sha256Hex(String.format("%s%s", user.getUserName(), System.currentTimeMillis()));  String token_key = getFormatToken(token, platform);  this.stringRedisTemplate.opsForValue().set(token_key, user.getId()+"",token_max_age, TimeUnit.SECONDS);

拦截器身份认证

为了方便做统一的身份认证,可以基于Spring的拦截器机制,创建一个拦截器来做统一认证。

public class AuthCheckInterceptor implements HandlerInterceptor {}

要使拦截器生效,还需要一步,增加配置:

@Configurationpublic class SessionConfiguration extends WebMvcConfigurerAdapter { @Autowired AuthCheckInterceptor authCheckInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) {  super.addInterceptors(registry);  // 添加拦截器  registry.addInterceptor(authCheckInterceptor).addPathPatterns("@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface AuthCheck {  String[] roles() default {};}

检验逻辑:

只要接口加上了AuthCheck注解,就必须是登陆用户

如果指定了roles,则除了登录外,用户还应该具备相应的角色。

 String[] ignoreUrls = new String[]{   "/user/.*",   "/cat/.*",   "/app/.*",   "/error" }; public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {  // 0 检验公共参数  if(!checkParams("platform",httpServletRequest,httpServletResponse)){   return false;  }  // 1、忽略验证的URL  String url = httpServletRequest.getRequestURI().toString();  for(String ignoreUrl :ignoreUrls){   if(url.matches(ignoreUrl)){    return true;   }  }  // 2、查询验证注解  HandlerMethod handlerMethod = (HandlerMethod) handler;  Method method = handlerMethod.getMethod();  // 查询注解  AuthCheck authCheck = method.getAnnotation(AuthCheck.class);  if (authCheck == null) {   // 无注解,不需要   return true;  }  // 3、有注解,先检查accessToken  if(!checkParams("accessToken",httpServletRequest,httpServletResponse)){   return false;  }  // 检验token是否过期  Integer userId = authService.getUserIdFromToken(httpServletRequest.getParameter("accessToken"),    httpServletRequest.getParameter("platform"));  if(userId==null){   logger.debug("accessToken timeout");   output(ResponseResult.Builder.error("accessToken已过期").build(),httpServletResponse);   return false;  }  // 4、再检验是否包含必要的角色  if(authCheck.roles()!=null&&authCheck.roles().length>0){   User user = authService.getUser(userId);   boolean isMatch = false;   for(String role : authCheck.roles()){    if(user.getRole().getName().equals(role)){     isMatch = true;     break;    }   }   // 角色未匹配,验证失败   if(!isMatch){    return false;   }  }  return true; }

服务响应结果封装

增加一个Builder,方便生成最终结果

public class ResponseResult { public static class Builder{  ResponseResult responseResult;  Map<String,Object> dataMap = Maps.newHashMap();  public Builder(){   this.responseResult = new ResponseResult();  }  public Builder(String state){   this.responseResult = new ResponseResult(state);  }  public static Builder newBuilder(){   return new Builder();  }  public static Builder success(){   return new Builder("success");  }  public static Builder error(String message){   Builder builder = new Builder("error");   builder.responseResult.setError(message);   return builder;  }  public Builder append(String key,Object data){   this.dataMap.put(key,data);   return this;  }    public Builder setListData(List<?> datas){   this.dataMap.put("result",datas);   this.dataMap.put("total",datas.size());   return this;  }  public Builder setData(Object data){   this.dataMap.clear();   this.responseResult.setData(data);   return this;  }  boolean wrapData = false;    public Builder wrap(boolean wrapData){   this.wrapData = wrapData;   return this;  }  public String build(){   JSONObject jsonObject = new JSONObject();   jsonObject.put("state",this.responseResult.getState());   if(this.responseResult.getState().equals("error")){    jsonObject.put("error",this.responseResult.getError());   }   if(this.responseResult.getData()!=null){    jsonObject.put("data", JSON.toJSON(this.responseResult.getData()));   }else if(dataMap.size()>0){    if(wrapData) {     JSONObject data = new JSONObject();     dataMap.forEach((key, value) -> {      data.put(key, value);     });     jsonObject.put("data", data);    }else{     dataMap.forEach((key, value) -> {      jsonObject.put(key, value);     });    }   }   return jsonObject.toJSONString();  } } private String state; private Object data; private String error; public String getError() {  return error; } public void setError(String error) {  this.error = error; } public ResponseResult(){} public ResponseResult(String rc){  this.state = rc; }  public ResponseResult(String rc, Object result){  this.state = rc;  this.data = result; } public String getState() {  return state; } public void setState(String state) {  this.state = state; } public Object getData() {  return data; } public void setData(Object data) {  this.data = data; }}

调用时可以优雅一点

 @RequestMapping(value = {"/user/login","/pc/user/login"}, produces = "application/json;charset=utf-8", method = {RequestMethod.GET, RequestMethod.POST}) @ResponseBody public String login(String userName,String password,Integer platform) {  User user = this.authService.login(userName,password);  if(user!=null){   // 登陆   String token = authService.updateToken(user,platform);   return ResponseResult.Builder      .success()     .append("accessToken",token)     .append("userId",user.getId())     .build();  }  return ResponseResult.Builder.error("用户不存在或密码错误").build(); }  protected String error(String message){  return ResponseResult.Builder.error(message).build(); } protected String success(){  return ResponseResult.Builder    .success()    .build(); } protected String successDataList(List<?> data){  return ResponseResult.Builder    .success()    .wrap(true) // data包裹    .setListData(data)    .build(); }

感谢你能够认真阅读完这篇文章,希望小编分享的“利用Spring Boot开发REST服务的案例”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网行业资讯频道,更多相关知识等着你来学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

利用Spring Boot开发REST服务的案例

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

利用Spring Boot开发REST服务的案例

这篇文章主要介绍了利用Spring Boot开发REST服务的案例,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。REST服务介绍RESTful service是一种架构模式,
2023-05-30

Spring Boot应用开发的示例分析

这篇文章主要介绍了Spring Boot应用开发的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Spring Boot是由Pivotal团队提供的全新Spring开发
2023-06-20

Shadow DOM应用案例剖析:揭秘隐藏的开发利器

Shadow DOM是HTML5中的一项重要技术,它允许在DOM中创建并维护一个单独的DOM树,从而实现了网页的模块化和组件化。Shadow DOM拥有广泛的应用场景,如创建自定义元素、封装组件、构建UI库等。
Shadow DOM应用案例剖析:揭秘隐藏的开发利器
2024-02-22

利用MongoDB技术开发中遇到的事务处理问题的解决方案探究

利用MongoDB技术开发中遇到的事务处理问题的解决方案探究概述:随着应用程序的复杂性增加,数据库的事务处理变得愈加重要。在传统关系型数据库中,事务处理已经得到了广泛的支持和应用。然而,在MongoDB这样的非关系型数据库中,事务处理并不是
2023-10-22

利用阿里云服务器开发Python应用简单易学的教程

Python是一种广泛使用的编程语言,其简洁、易学的特性使得它在许多领域中得到了广泛应用,尤其是在服务器开发领域。阿里云作为国内领先的云计算服务提供商,提供了丰富的云服务器服务,使得开发者可以轻松地利用Python进行开发。本文将介绍如何利用阿里云服务器开发Python应用,包括安装Python、安装Python
利用阿里云服务器开发Python应用简单易学的教程
2023-10-31

利用VSCode进行远程Linux服务器、容器开发,达到ide开发项目的效果(最新推荐)

目录0 本地ide式开发1.0 局域网下远程终端开发1.1 局域网下远程ide式开发1.2 公网下远程ide式开发1、购买一个阿里云服务器2、阿里云服务器终端内2.1、先开放端口2.2、接下来配置frp2.3、设置自启动4、Win端ssh连
2022-12-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录