前言:

其实很早就想写这篇文章了,因为我觉得这会对很多新手有指引作用,当初自己也是瞎子过河的摸索着过来的。目前后台开发比较流行的MVC框架中使用Spring MVC还是比较多的,当然还有Spring Boot,Spring Boot是基于 Spring4 的条件注册的一套快速开发整合包,说白了就是简化开发流程。大家可以尝试一下,但是这里还是以Spring MVC为例子。

之所以使用jwt(json web token),是因为做后台不同于做web,app因为是长时间的登录至少都是一两个月不操作任然处于登录状态,所以目前国内大多是都是使用token做鉴权而不是使用session。而jwt是一个不错的token技术。restful就不用多说了,现在比较流行的编程风格,多个客户端(安卓,ios, mobile,web)调用同一套后台接口,而这就使得这套后台接口尽量不附带太多业务逻辑,而是面向资源的风格。而swaggerui则是提供一个rest api的可视化接口文档,并且在开发完后,可以很轻松的测试。

当然你可以只整合jwt或者swaggerui,教程都是没问题的。

所有使用到的代码可以在这里查看:https://github.com/minchangchen/springmvc-jwt-swaggerui

1.Spring MVC

Spring MVC框架是有一个MVC框架,通过实现Model-View-Controller模式来很好地将数据、业务与展现进行分离。从这样一个角度来说,Spring MVC和Struts、Struts2非常类似。Spring MVC的设计是围绕DispatcherServlet展开的,DispatcherServlet负责将请求派发到特定的handler。通过可配置的handler mappings、view resolution、locale以及theme resolution来处理请求并且转到对应的视图。这里就不做太多介绍,开始想在维基百科上搜索下spring mvc的,结果发现并没有这个条目,百度是有的。所以说有时候盈利的并不是都不好。

2.JWT(Json Web Tokens)

定义:JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准( RFC 7519 ),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。

说明:传统的鉴权机制是基于session-cookies,而随着认证用户的增多,服务端的开销会明显增大,且不适合做app应用验证。因为app是一次登录,退出后不需登录,所以现在主流的鉴权验证都是使用token验证。而jwt是一种不错的基于token的鉴权机制。

基本流程:

用户使用用户名密码来请求服务器

服务器进行验证用户的信息

服务器通过验证发送给用户一个token

客户端存储token,并在每次请求时附送上这个token值

服务端验证token值,并返回数据

推文:http://www.jianshu.com/p/576dbf44b2ae

3.RestFul

定义:网络应用程序,分为前端和后端两个部分。当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备......)。因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信。这导致API构架的流行,甚至出现"API First"的设计思想。RESTful API是目前比较成熟的一套互联网应用程序的API设计理论。

说明:restful风格,就是一种面向资源服务的API设计方式,它不是规范,不是标准,它一种设计模式。以前流行的web service服务都是面向过程,基于RPC协议的SOAP协议,对于现在或者未来,更多的人了解并且深受SOA思想影响,以面向服务为目标,而现在的SOAP虽然支持SOA,但存在很很大的差别,所以,慢慢就流行基于restful风格的web service。说简单一点,就是它纯粹面向资源,面向服务的思想,目前J2EE6的JAX-RS就是这种restful风格实现的新技术。

例子:

获取用户列表 GET:http://project.company.com/api/v1/users
获取单个用户 GET:http://project.company.com/api/v1/users/{uid:.{32}}
创建单个用户 POST:http://project.company.com/api/v1/users/{uid:.{32}}
完全替换用户 PUT:http://project.company.com/api/v1/users/{uid:.{32}}
局部更新用户 PATCH:http://project.company.com/api/v1/users/{uid:.{32}}
删除单个用户 DELETE:http://project.company.com/api/v1/users/{uid:.{32}}

推文:http://www.ruanyifeng.com/blog/2014/05/restful_api.html

4.Swagger UI

定义:Swagger的目标是为REST APIs 定义一个标准的,与语言无关的接口,使人和计算机在看不到源码或者看不到文档或者不能通过网络流量检测的情况下能发现和理解各种服务的功能。当服务通过Swagger定义,消费者就能与远程的服务互动通过少量的实现逻辑。类似于低级编程接口,Swagger去掉了调用服务时的很多猜测。

说明:swagger ui用于管理项目中API接口,属当前最流行的API接口管理工具。是后端开发人员提供给app开发人员的一个查看、测试、的一个可视化,可操作的接口文档,在这里你可以知道需要给都太传入什么参数,使用哪种请求,以及返回的数据等等,这种就省去app端人员写测试接口。

图示:

代码:

1.maven

<!-- Spring -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>4.3.4.RELEASE</version>
	<exclusions>
		<!-- Exclude Commons Logging in favor of SLF4j -->
		<exclusion>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
	<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-test</artifactId>
	<version>4.3.4.RELEASE</version>
</dependency>

<!-- springfox-swagger2 -->
<dependency>
	 <groupId>io.springfox</groupId>
	 <artifactId>springfox-swagger2</artifactId>
	 <version>2.5.0</version>
</dependency>
 <dependency>
	 <groupId>io.springfox</groupId>
	 <artifactId>springfox-swagger-ui</artifactId>
	 <version>2.5.0</version>
 </dependency>

 <!-- Jwt -->
<dependency>
	<groupId>io.jsonwebtoken</groupId>
	<artifactId>jjwt</artifactId>
	<version>0.7.0</version>
</dependency>

2.JWT

这里我不再解释下jwt了,looking this :http://www.jianshu.com/p/576dbf44b2ae 一定要看哦!

我先说下jwt使用流程:

a:用户登录server

b:server验证通过,生成token并返回

c:app端接收到token存起来,下去请求放在reuqest的header里面

d:server接收到app的请求,在拦截器中判断url是否为需要鉴权的路径,然后去验证token

e:当token过期时,且没有超过刷新期。自动添加一个新的token返回给app

拦截器:

public abstract class BaseWebInterceptor extends HandlerInterceptorAdapter {

	public static final String RedirectPrefix = "redirect:";
	private static Logger log = LoggerFactory.getLogger(BaseWebInterceptor.class);

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		if (isNeedJwtUrl(request.getRequestURI())) {	//判断这个url是否需要jwt验证 ,比如login就不需要
			String token = request.getHeader("x-access-token");		//从request中获取token,key是自定义的,当然app端存也要是这个key
			ETokenState state = JwtUtil.validateJWT(token);			//验证token,ETokenState这是我自定义的一个类,JwtUtil这也是自己写的一个类
			switch (state) {
			case invalid:		//验证错误
				log.info(String.format("URL:%s need login, but the token is null or invalid... ", request.getRequestURL().toString()));
				response.setStatus(401);
				return false;
			case expired:		//token过期
				if (refreshTokenHandler(request, response, token)) {
					break;
				} else {
					log.info(String.format("URL:%s need login, but the token is expired... ", request.getRequestURL().toString()));
					response.setStatus(403);
					return false;
				}
			case valid:		//有效的
				break;
			default:
				break;
			}
		}
		return super.preHandle(request, response, handler);
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
		super.afterCompletion(request, response, handler, ex);
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
		super.postHandle(request, response, handler, modelAndView);
	}

	/**
	 * 刷新token,子类重载
	 *
	 * @author chenmc
	 * @date 2017年5月9日 下午3:41:05
	 * @param token
	 * @return
	 */
	protected boolean refreshTokenHandler(HttpServletRequest request, HttpServletResponse response, String token) {
		return false;
	}

	/**
	 * 需要登录的uri
	 *
	 * @param requestURI
	 * @return
	 */
	private boolean isNeedJwtUrl(String requestURI) {
		return MappingConf.isNeedJwtUrls(requestURI);
	}

}

这里需要说明的是,一般的login和register的url是不拦截的,自己可以配置。关于jwt生成和验证的代码,请点击这里https://github.com/minchangchen/springmvc-jwt-swaggerui

2.Swagger UI

配置文件:

1,springmvc.xml

<!-- swagger2 -->
	<context:component-scan base-package="com.gionee.swagger.conf"/>
	<bean class="com.company.swagger.conf.SwaggerConfig"/>
	<!-- Swagger资源重定向(仅作为后台使用不提供静态资源) -->
    <mvc:resources location="classpath:/META-INF/resources/" mapping="swagger-ui.html"/>
    <mvc:resources location="classpath:/META-INF/resources/webjars/" mapping="/webjars/**"/>

2,SwaggerConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

//@Configuration
@EnableSwagger2
@EnableWebMvc
@ComponentScan("com.company.web")
public class SwaggerConfig {

    @Bean
    public Docket api(){
    	ParameterBuilder tokenPar = new ParameterBuilder();
    	List<Parameter> pars = new ArrayList<Parameter>();
		//增加一个request的header参数
    	tokenPar.name("x-access-token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
    	pars.add(tokenPar.build());
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.any())
            .paths(PathSelectors.regex("/api/.*"))//对所有请求中包含api的url拦截
            .build()
            .globalOperationParameters(pars)
            .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("后台接口文档与测试")
            .description("这是一个给app端人员调用server端接口的测试文档与平台")
            .version("1.0.0")
            .termsOfServiceUrl("http://terms-of-services.url")
            //.license("LICENSE")
            //.licenseUrl("http://url-to-license.com")
            .build();
    }

}

3,Controller

@Api(value="登录接口")
@Controller
@RequestMapping("/api/v1")
public class LoginInterface extends BaseController {

	@Autowired
	UserSO so;

	@ApiOperation(value="验证密文,并添加user", notes="密文和amigoInfo")
	@RequestMapping( value = {"/login"}, method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	@ResponseBody
	public String login(HttpServletRequest request, @RequestParam String fields, @PathVariable String useruid) {
		// do something
	}

	/*
	*api开头的注解都是swagger的注解
	*方法参数上加有@RequestParam的参数会显示在swagger
	*所以上述login方法的三个参数只有fields会显示在swagger中
	*当然还有一个请求头的参数,存放token的那是在SaggerConfig.java中配置的
	*/
}

4,放开swagger的url不拦截

当你配置了jwt,因为jwt对url进行拦截,这里我们不能对swagger的URL进行拦截,这样页面才能正常显示。只整合swaggerui的可以忽略。

noNeedJwtUrls=.*swagger.*|.*docs.*|.*test.*|.*/index.*|.*/register.*|.*/login.*

至此,swaggerui已配置完成,请求访问http://localhost:8080/proj-name/swagger-ui.html即可得到以下页面

3.RestFul API

请参照以下这种方式来定义接口

获取用户列表 GET:http://proj.company.com/api/v1/users

获取单个用户 GET:http://proj.company.com/api/v1/users/{uid:.{32}}

创建单个用户  POST:http://proj.company.com/api/v1/users/{uid:.{32}}

完全替换用户 PUT:http://proj.company.com/api/v1/users/{uid:.{32}}

局部更新用户 PATCH:http://proj.company.com/api/v1/users/{uid:.{32}}

删除单个用户 DELETE:http://proj.company.com/api/v1/users/{uid:.{32}}

至此,所有配置应该都已经贴出,代码可在这里查找:https://github.com/minchangchen/springmvc-jwt-swaggerui


若有遗失或错误希望大家提出!过段时间我会写一些与docker有关的教程,这段时间觉得自己对docker的使用还不够全及精,所以暂时不写!

SpringMVC+JWT+Swagger UI+RestFul的更多相关文章

  1. SpringMVC融合Swagger UI使用

    相信大家都很熟悉springmvc,在用其进行开发工作的时候,有没有遇到几个小问题?比如: 1.前后端分离的模式下,前端开发人员如何得知后端的开发进度,有哪些接口可用? 2.后端开发人员在测试自己的接 ...

  2. gRPC helloworld service, RESTful JSON API gateway and swagger UI

    概述 本篇博文完整讲述了如果通过 protocol buffers 定义并启动一个 gRPC 服务,然后在 gRPC 服务上提供一个 RESTful JSON API 的反向代理 gateway,最后 ...

  3. Swagger UI 与SpringMVC的整合 II

    pom.xml <!-- swagger开始 --> <dependency> <groupId>io.springfox</groupId> < ...

  4. 使用 Swagger UI 与 Swashbuckle 创建 RESTful Web API 帮助文件

    作者:Sreekanth Mothukuru 2016年2月18日 本文旨在介绍如何使用常用的 Swagger 和 Swashbuckle 框架创建描述 Restful API 的交互界面,并为 AP ...

  5. 使用 Swagger UI 与 Swashbuckle 创建 RESTful Web API 帮助文件(转)

    作者:Sreekanth Mothukuru2016年2月18日 本文旨在介绍如何使用常用的 Swagger 和 Swashbuckle 框架创建描述 Restful API 的交互界面,并为 API ...

  6. springMVC整合swagger(亲自试验完全可用)

    swagger是什么: [plain] view plain copy Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件.本文简单介绍了在项目中集成swagger的方法和一 ...

  7. Swagger: 一个restful接口文档在线生成+功能测试软件

    一.什么是 Swagger? Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件.Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 ...

  8. Yii2+Swagger搭建RESTful风格的API项目

    在现有的Advanced Template上搭建RESTful API项目的步骤: 本案例前提说明: 本例中不使用\yii\rest\ActiveController自动创建的API,而是自定义一个A ...

  9. spring-mvc集成 swagger

    问题1:spring-mvc集成 swagger, 配置好后界面 404, 原因: dispatcher-servlet.xml 文件中, 要在这上面 <!-- 启用spring mvc 注解 ...

随机推荐

  1. Extjs6.2 项目学习系列(一)

     1. Extjs开发准备  (1).下载ExtJS  SDK GPL版 (本测试用版本 ext-6.2.0) : https://www.sencha.com/legal/gpl/ (2).下载Se ...

  2. 咸鱼入门到放弃13--监听器(Listener)

    一.监听器介绍 1.1.监听器的概念

  3. SpringBoot的Web开发

    一.创建Web项目 创建的时候勾选对应web选项即可,会自动引入相应的starter,pom如下: <dependency> <groupId>org.springframew ...

  4. E - Elevator

    E - Elevatorhttp://codeforces.com/gym/241680/problem/E同余最短路,从0~a-1中每一个i向(i+b)%a连一条权值为b的边,向(i+c)%a连一条 ...

  5. Interpreting NotifyCollectionChangedEventArgs zz

    If you’ve ever consumed INotifyCollectionChanged.CollectionChanged, then you’ve run into some inadeq ...

  6. STM8L052低功耗模式

    Stm8L系列单片机的低功耗有五种模式: § wait模式 § Lowpower run模式 § Lowpower wait模式 § Active-haltwith full RTC模式 § Halt ...

  7. Shell 编程注意点

    (一)判断语句 [$# -lt 4 ]判断语句,格式[空格 比较对象1 比较符号 比较对象2] $# 启动脚本时携带参数个数;参数个数总数. $1 代表第一个参数. $? 最后一次执行名命令的退出状态 ...

  8. idea设置调用方法时提示方法注释

    如图所示:打开file-->setting-->Editor-->General,搜索show,然后勾选上Show quick documentation on mouse move ...

  9. 性能测试学习 第七课 --loadrunner中JavaVuser脚本的编写

    1.环境准备:      LoadRunner11----->对应JDK1.6版本(32位) LoadRunner12----->对应JDK1.7版本(32位) (一).JDK下载安装完成 ...

  10. Hadoop源码分析:Hadoop编程思想

    60页的ppt讲述Hadoop的编程思想 下载地址 http://download.csdn.net/detail/popsuper1982/9544904