1

点赞

2

回复

1023

浏览

将JSP/Servlet项目转换为Spring Boot项目

创建SPRING BOOT应用 在基于Spring来重构JSP应用之前,我们先引入Spring Boot,使之成为一个Spring Boot应用。你只需要在原来的代码基础上,增加简单的配置和少量的代码即可引入Spring Boot,整个过程5分钟就能完成。 这里我们使用 Maven http://www.tianmaying.com/tutorial/maven basic 来管理依赖,因为我们需要增加Spring Boot相关的依赖。也可以在Eclipse或者IntelliJ中创建一个新的Maven项目。 在POM文件中加入Spring Boot相关的配置。 ...

JSPservletspringboot

0

点赞

0

回复

660

浏览

微信公众号开发:弹幕应用中接收消息

微信公众号大家都很熟悉了,当你拥有了微信公众号之后,你可以在 微信公众平台 https://mp.weixin.qq.com/ 中对你的公众号进行管理。 微信公众平台 https://mp.weixin.qq.com/ 为我们提供了很强大的管理功能,包括群发消息、自动回复、自定义菜单等等。但是,需求是多种多样的, 微信公众平台 https://mp.weixin.qq.com/ 中的功能必然不能满足所有的用户需求。今天,我们就来学习一下如何利用微信的开放接口来实现一个微信弹幕的简单后台。 申请微信公众号 第一步,我们首先得拥有一个微信公众号,进入 微信公众平台 https://mp.weixin.qq.com/ ,点击右上角【立即注册】进入注册页面: 按要求填写基本信息,激活邮箱、验证个人信息等等操作后,注册成功。此时,作为一个最简单的公众号,微信已经给我们了很多相应的权限,在【接口权限】页面中我们可以看到我们所拥有的所有权限: 浏览一下权限以及状态,我们可以看到,我们已经拥有了接收消息的相应的权限。现在,我们就来通过该接口在我们的程序中接收普通的消息。 服务器配置 接收微信公众号消息的流程是这样的:用户向公众号发送消息,微信接收消息,并向你的开发服务器发送一个POST请求,该请求包含了该消息的相关信息,如由谁发给谁、内容是什么等,最后开发服务器接收消息并进行相应的处理。 我们可以看到,微信会主动的向你的开发服务器推送相应的消息,很明显,我们需要在微信公众平台中进行相应的设置: 点击修改配置,此时需要填写以下四个信息: URL 微信将发送数据到该地址,该URL需要处理GET请求以及POST请求。GET请求用于微信验证该URL是否属于你,当你提交你的服务器配置时,微信会往该地址发送一个GET请求,只有当该请求返回结果正确时,你的修改才会成功,否则提示【token验证失败】。POST请求用于接收微信的相关信息,当有人往公众号发送信息时,微信将把相关信息通过POST请求发送到该地址 Token 用于加密的令牌,GET请求时验证微信身份时会用到,可以随意填写 EncodingAESKey 用于对信息加密,当使用安全模式时,微信发送过来的信息是用该字段进行加密后的字符串,你可以使用微信提供的算法对字符串进行解密,获取信息内容,直接随机生成即可 消息加密方式 明文模式 发送过来的消息不进行加密,直接使用即可 兼容模式 明文、密文共存,方便调试 安全模式 发送过来的消息只有密文,安全系数较高 这里,我们根据实际情况将URL、Token、EncodingAESKey填好,直接选择明文模式接收公众号的消息。 在介绍URL参数时我们也提到了,此时点击提交,由于我们未完成URL GET请求的处理,将提示【token验证失败】,因此,我们先把服务器配置的提交放一放,先来完成服务端的开发。 验证服务器地址 当我们提交服务器配置时,微信会向我们配置的URL发送一个验证请求,该请求包含下列四个参数: signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 timestamp 时间戳 nonce 随机数 echostr 随机字符串 我们接收到请求后,验证过程如下: 1. 将token、timestamp、nonce三个参数进行字典序排序 2. 将三个参数字符串拼接成一个字符串进行sha1加密 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信 4. 若该请求来源于微信,原样返回echostr,则接入成功,否则接入失败 Java代码如下: @Value("${weixin.token}")...

wechatspringbootweixinjava

3

点赞

2

回复

3709

浏览

通过Spring Boot三分钟创建Spring Web项目

SPRING BOOT简介 接下来我们所有的Spring代码实例将会基于 Spring Boot http://projects.spring.io/spring boot/ ,因此我们先来了解一下Spring Boot这个大杀器。 Spring早期使用XML配置的方式来配置Spring Beans之间的关系,比如AOP和依赖注入的配置。随着功能以及业务逻辑的日益复杂,应用便会伴随大量的XML配置文件以及复杂的Bean依赖关系。随着Spring 3.0的发布,Spring团队逐渐开始摆脱XML配置文件,并且在开发过程中大量使用“约定优先配置”(convention over configuration)的思想来摆脱Spring框架中各类纷繁复杂的配置。Spring就是在这样一种背景下被抽象出来的一个在Spring之上的开发框架。 Spring Boot的设计目的是用来简化新Spring应用的创建以及开发过程。从它的名字可以看出,其作用在于创建和启动新的基于 Spring 框架的项目,它能够帮助开发人员很容易的创建出基于Spring的独立运行和产品级别的应用。它包含的特性如下: 应用独立运行,对于Web应用直接嵌入应用服务器(Tomcat or Jetty) 根据项目的依赖(Maven or Gradle中定义的依赖)自动配置Spring框架的特性 提供生产环境中的监控功能——性能、应用状态信息等 不会生成繁琐的Java代码以及XML配置文件 Spring Boot并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。Spring Boot应用通常只需要非常少量的配置代码,而且有内嵌的Web服务器,让开发者能够更加专注于业务逻辑。在后面的开发过程中,我们能够逐渐感受到Spring Boot这些优秀特性给我们带来的好处。 第一个SPRING BOOT项目 接下来我们通过创建一个简单的Spring Boot项目来建立对初步的印象。一开始可能会遇到一些不太理解的地方,没关系,我们会在学习过程中我们会逐一搞定。 我们通过Maven来创建项目,【File】 【New】 【Others...】; 弹出的对话框中包含了一系列的项目类型,我们选择 Maven Project ;一个技巧是可以在 type filter text 中输入 Maven 进行搜索过滤,这样很快可以找到 Maven Project 。 选中后出现了新的对话框,勾选 Create a simple project (skip archetype selection) ,点击 Next 后,按照下图输入内容: 输入完成后点击 Finish ,第一个项目就创建成功了。 项目创建成功后,在Eclipse IDE左边的 Project Explorer 中会出现我们刚刚创建的项目,其中有一个 pom.xml 文件,我们先对它进行修改,增加一个依赖,内容变为: project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema instance"...

springbootspring

2

点赞

0

回复

3773

浏览

SpringBoot与JUnit+Mockito 单元测试

JUNIT和MOCKITO 对于JUnit,这里就不详细介绍了,网上的教程有很多,比如 这个 http://www.cnblogs.com/yangxia test/p/3991572.html 和 这个 http://huihai.iteye.com/blog/1986568 。 下面主要介绍一下 Mockito 。 什么是mock测试,什么是mock对象? 先来看看下面这个示例: 从上图可以看出如果我们要对A进行测试,那么就要先把整个依赖树构建出来,也就是BCDE的实例。 一种替代方案就是使用mocks 从图中可以清晰的看出: mock对象就是在调试期间用来作为真实对象的替代品 mock测试就是在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试 模拟的好处是什么? 提前创建测试; TDD(测试驱动开发) 如果你创建了一个Mock那么你就可以在service接口创建之前写Service Tests了,这样你就能在开发过程中把测试添加到你的自动化测试环境中了。换句话说,模拟使你能够使用测试驱动开发。 团队可以并行工作 这类似于上面的那点;为不存在的代码创建测试。但前面讲的是开发人员编写测试程序,这里说的是测试团队来创建。当还没有任何东西要测的时候测试团队如何来创建测试呢?模拟并针对模拟测试!这意味着当service借口需要测试时,实际上QA团队已经有了一套完整的测试组件;没有出现一个团队等待另一个团队完成的情况。这使得模拟的效益型尤为突出了。 你可以创建一个验证或者演示程序。 为无法访问的资源编写测试 这个好处不属于实际效益的一种,而是作为一个必要时的“救生圈”。有没有遇到这样的情况?当你想要测试一个service接口,但service需要经过防火墙访问,防火墙不能为你打开或者你需要认证才能访问。遇到这样情况时,你可以在你能访问的地方使用MockService替代,这就是一个“救生圈”功能。 Mock 可以分发给用户 隔离系统 知道什么是mock测试后,那么我们就来认识一下mock框架 Mockito。 Mockito区别于其他模拟框架的地方主要是允许开发者在没有建立“预期”时验证被测系统的行为。 Mockito相关教程: 5分钟了解Mockito http://liuzhijun.iteye.com/blog/1512780 Mockito:一个强大的用于Java开发的模拟测试框架 http://blog.csdn.net/zhoudaxia/article/details/33056093 学习Mocktio 利用ArgumentCaptor(参数捕获器)捕获方法参数进行验证 http://hotdog.iteye.com/blog/916364 使用Mockito进行单元测试【2】—— stub 和 高级特性 http://qiuguo0205.iteye.com/blog/1456528 (与此同时推荐一个东西, SpringOckito https://github.com/springockito/springockito , 不过已经2年没更新了。) MOCKITO入门实例 Maven依赖: Xml代码 ...

mockitospringbootjunit

1

点赞

2

回复

1268

浏览

猿帮帮之技术架构

猿帮帮技术架构 应用综述 我们希望打造一款应用,可以帮助非电气信息类专业的女大学生、中老年退休人员等一些缺乏电脑操作基本知识的人群解决一些基本的软件问题。 功能模块设计 猿帮帮一共包含问答、评论/回复、搜索、奖励几大模块,后面会展开讲各个功能模块。 猿帮帮的后台使用的是 Springboot http://projects.spring.io/spring boot/ 框架,它是新一代Spring应用的开发框架,它能够快速的进行应用开发,让人忘记传统的繁琐配置,更加专注于业务逻辑。了解 springboot 的详细内容可以参考 Spring Boot——开发新一代Spring应用 http://tianmaying.com/tutorial/spring boot overview 和 Spring Boot应用开发 http://tianmaying.com/tutorial/spring boot intro 两篇文章。 前端使用的是 AngularJS 框架,它是新兴的 JavaScript MVC 框架,它对模板化的创新实现和数据的双向绑定,这些特性使得它强大而易用,并且明显的缩减了项目所需要的代码量。更加详细的介绍请参看 AngularJS官网 https://angularjs.org/ 。 提问和评论模块 提问和评论是猿帮帮的两个重要的模块,都采用了 MVC 架构, Model 层负责处理数据和业务逻辑, View 层以支持的格式和布局向用户展示数据, Controller 层接收用户请求,并调用合适的资源来执行请求。 猿帮帮的 Model 层使用的是 Springboot 的 JPA ,在 pom 文件中添加依赖: ...

springbootdockerci

0

点赞

0

回复

937

浏览

敏捷亚博国际线上娱乐--任意三数字加yabo.com直达官网总结报告-shakespeare文字游戏引擎组

一、应用介绍 shakespeare是一款文字游戏引擎,面向人群是有剧本制作,游戏开发情结的人们。无需任何编程基础,通过markdown制作故事剧本即可一键生成可以在微信公众号,pc端浏览器和手机浏览器页面上运行的小游戏。 二、系统架构 下图是我们的系统框架图。 有游戏作者,文字游戏云和用户三方。 首先游戏作者本地用markdown语法编写游戏剧本,Engine模块处理后生成json数据包上传至游戏库。服务器应答来自微信公众号或者浏览器网页的请求,进行和游戏玩家的交互。 各部分功能 ENGINE Engine端负责将作者写的DSL游戏脚本转化为Json格式的游戏,并发送post请求到服务端容器完成建立游戏的工作。 它的处理流程是: 用户提交游戏 检查用户语法 检查用户的游戏是否有错误 检查无误后进行提交 发送POST请求道服务端容器 JSON游戏库 虽然叫做Json游戏库,但实际游戏是在关系型数据库中存储的,每个游戏都是一个有向图,通过 Point , Line , Selection , Game 等元素描述。 当服务端接收到 Engine 发送的游戏Json数据时,会首先将之转化为上述对象,检查无误后,格式化存储在Mysql中。当微信用户或浏览器用户发送请求到服务端时,服务端会从数据库中拿到游戏数据,并将之做相应的处理,返回相应的数据。 微信自动机 微信自动机负责完成微信公共号用户的游戏逻辑,用户发送命令给微信自动机,自动机会向游戏库中读取游戏数据还原游戏有向图,根据用户在图中的位置,及他以前及刚刚的选项判断下一步该去的节点,并将节点的内容及关联的选项返回给用户。 微信自动机除了负责自动机的相关逻辑外,它还要和腾讯的微信公共平台打交道,当用户向公共号发送一个消息时,消息会首先发送给腾讯的微信公共平台,腾讯会将之编码为XML格式转发给我们的微信自动机,微信自动机会解析XML,并转化为用户命令,完成逻辑后得到返回文字,并编码为XML格式返回给微信公共平台,完成整个通信过程。 网页版 网页版满足了浏览器用户的游戏需求,当用户访问网页时,浏览器端会向服务器端发送AJAX请求获取游戏数据,渲染出游戏内容,供用户进行游戏。 服务端 在下一部分我们将详细介绍上述各个模块的技术原理。 三、模块介绍 游戏引擎模块 负责人:何远舵 需求设想 我负责这部分的功能主要包括 接受用户输入 , 语法解析 , 语义解析 , 向后台通信 , 向用户反馈 。 方案尝试 上述 需求设想 需求设想 比较笼统,而涉及到具体的技术选择、制品的形态等就更是未知数了,因为不存在一个面向这类问题的通用框架或解决方案。因此在技术选择以及具体实现上,调研并尝试了许多可能的方案,所以下面介绍一下曾经尝试过的方案及其各自的优劣。 JAVA + ANTLR4 最开始设想从语言角度出发,因此首先调研了一些语法解析器生成器工具。一个比较好的选择是 Antlr4(ANother Tool for Language Recognition) 。 它是一个功能强大的解析器生成,可以实现读取、处理、执行、转义文本文件或二进制文件的功能。因此,它被广泛用于定制领域语言。很自然地,我也选择了用它去构建DSL。此外,虽然它支持输出多种语言,但是考虑到语言的统一,故全部采用了Java开发。 既然已经选择了Java和Antlr4,那么一个比较直接的产品形态就是作为后台的服务进程实现。因此,该产品应该是这样工作的,用户通过一个通道(HTTP Post)提交文本,该进程收到并进行语法语义检查,反馈用户成功或错误,如果成功则再把解析好的中间结果发送到其他服务用于生成游戏等。 但是该方案有如下 缺点 : 1. 开发上 :虽然使用了构建工具,但是使用Java以TDD的方式开发(先写单元测试),开发进度缓慢,也许是因为我不用IDE的缘故; 2. 开销 :作为后台服务存在,会占用后台的计算和IO资源; 3. 用户体验 :用户交互过程太过丑陋,或者说完全没考虑。 考虑到上述的缺点,便把这一版直接都丢了,残余代码在onboard的 engine 分支下。 RUBY + TREETOP + GRAPE 为了改进上述缺点,我尝试了Ruby、Treetop、Grape的技术架构。Ruby我更为熟悉,Treetop是ruby版本的dsl语言定制工具,而Grape则是一个Ruby的REST like API微框架。 很明显,这一套方案的选择侧重点在两个方面:一方面选择熟悉的技术语言Ruby作为开发语言有利于 提高生产效率 ,另一方面,相比较前一个解决方案完全没有考虑用户反馈的做法,该方案选择Grape则是开始把工作重心往 用户体验 方面挪,希望通过后台解析后得到结果的json,返回给前端,并在前端展示出成功与否或问题所在。当然这套方案依然将解析工作放到后端。 但是该方案有如下 缺点 : 1. 开销 :将解析工作放到后端做依然存在计算和IO开销的问题; 2. 用户体验 :虽然试图通过Grape提供前端展示的,但是用户体验依然不尽如人意,因为不能展示在用户编辑过程中进行反馈。亦即,用户编写剧本和用户提交剧本得到反馈这两个场景是剥离的,这样我认为很不好。 考虑到如上缺点,便把这一版直接都丢了。残余代码还没删,于近日push到了onboard下的 ruby treetop grape 分支。值得一提的是,其中并没有grape的代码,因为再实现了语法解析之后,在进一步调研grape的时候觉得会有如上问题就把该方案丢了。 JAVASCRIPT + EMBER.JS + PEG.JS 该技术方案 变革巨大 ,选用了Ember.js和PEG.js。Ember.js是一个构建ambitous web应用的重量级的前端MVC框架,PEG.js是一个Javascript的解析器生成器,它基于解析表达式语法形式化。 这一套方案的变革在于两点:它将 解析工作放到了浏览器里 进行,彻底解放了后台;此外,开发核心也 不再优先注重于语言 ,而是首先从用户的交互上开始。 该方案的期待场景是,用户在浏览器里面编辑,无需与后台交互便可以进行语法语义检查,而且借助于前端的渲染,可以很友好地展示出错误或当前写作的摘要等。 但是该方案有如下缺点: 1. 开发困难 :在前端实现富文本的编辑器太困难了,试图通过前端组件化来实现,但是…… 因为困难巨大,所以便把这一版直接都丢了。残余代码还没删,于近日push到了onboard下的 emberjs pegjs 分支。注意,这一版本首先构建的是展示部分,实现了故事的信息展示,在准备加入PEG.js的时候,想不出以后该怎么实现前端的 友好 展示,便把该方案丢了。 COFFEESCRIPT + ATOM + LINTER + PEG.JS 既然自己写不出来前端的富文本编辑器,拿一个现成的,然后再基于这个现成的开发适用于我的语言的插件,从而实现友好交互总是可以吧。感谢 github 。 Atom是一个基于chrome V8引擎的现代的可扩展的编辑器;Linter是一个Atom的包,依赖于这个包可以开发自己的实现自己定制语法的on fly解析和错误提示;开发Atom的包主要语言是Coffeescript(用起来超爽无比,但愿能跟ES6兼容)。 那么,这种技术方案的愿景是:用户在atom编辑器里写着故事,一边写的时候,如果出现不规范的地方会有红线标注的错误提示;写完后没有错误提示,一个快捷键就把解析好的文章(json)传到后端服务器。因此可以说,这一方案 完美地解决了用户的交互过程 , 将编辑与解析合二为一 ,同时 又不占用后台资源 。 但是,这一方案依然存在一个弊端: 1. 学习成本 :用户凭什么要学习一个新的语法,能够不能简单简单再简单 因为语法如何构建的问题,在初步实现了展示on fly的功能(fake错误)后,便把这一版丢弃了。关于这一版本的代码,onboard下 language story 分支是用于实现一个新的语言类型,用于通知liner进行解析,而另有一部分代码已经找不到了。 COFFEESCRIPT + ATOM + COMMONMARK + VUE.JS 光阴荏苒,还有三周结课了。为了解决上述的问题,选用了markdown语法的一个超简单的子集作为我的语法,以及Commonmark作为解析工具实现语法的解析。Vue.js用于实现插件展示层和模型层的分离。 该超简单的语法只包含下列三种标记: 是故事的名字 是场景的名字 1. 2. ... 并配合以 () 内链接 的方式实现跳转 综上所述,以上五种技术方案的演变大致是: 从 后端 向 前端 转移 从 语言构造 向 用户体验 转移 所以,虽然最后的方案看起来很简单,但是也是经历了多种考虑后的逐渐演变的结果。而且,最后一种方案目前我认为依然有可以进一步改进的地方,比如Vue.js的选择可以再斟酌,因为不需要数据双向绑定,单项绑定即可,也许可以用Handlerbars.js来替换等等。此外,语法部分还可以再借用markdown的语法进一步增强。 下面介绍最后一种方案的技术细节。 技术细节 代码组织结构 Atom插件开发基于npm规范,主要文件与文件夹如下: lib/ spec/ keymaps/ template/ styles/ menu/ package.json 其中,package.json文件定义插件的依赖、名称、描述等信息。lib文件夹存放主要代码,spec文件夹存放测试,keymaps、styles、menu文件夹是atom插件特有的,分别用于存放快捷键映射、样式、菜单栏信息等文件,template文件夹用于存放Vue.js的渲染模板。 主要文件及功能介绍 lib/parchment.coffee与lib/story/ .coffee parchment主要功能将commonmark解析后得到的ast删减,得到一个子集的解析,解析后的内容包括三个信息,分别是story,plot,option,这三个分别定义在lib/story/ 下;此外,parchment还将解析好的story,plot,option以json的形式发送到后端服务器。 lib/quill.coffee与lib/quill view.coffee 这两个文件主要实现了插件的运作功能,包括展示当前编辑的summary信息以及向后台提交完成的故事信息。quill定义了行为,quill view定义了向用户展示的UI。 lib/vue summary model.coffee与template/summary view.html 考虑到quill view实现UI的方式是通过DOM操作,为了提高效率,采用了Vue.js实现数据和展示分离。这两个文件分别是Vue的模型层和展示层。 sepc/ .coffee 这部分代码是基于Jasmine的BDD测试代码。其中,为了测试http请求,采用mitm.js mock工具,用于拦截http请求并返回测试结果。 敏捷实践 快速迭代 上述讨论的五个方案,基本每个迭代周期为2~3周,或者更准确地说,基本上存活周期为2~3周。利用2~3周时间快速搭建原型,并进一步思考下一步该如何去做的时候,便能够很快地发现这种方案下的困难,如果能克服就可以再做下去,但实在不行就可以毫无顾忌地直接抛弃。 测试驱动开发与重构 所有方案,除了ember.js相关的没有写测试外,其他所有方案基本上实践了测试驱动开发。测试驱动开发在这里并没有流于形式,因为我常常会重构代码,或者尝试乱七八糟的各种功能,测试驱动开发在这里就做了一个保障,确保无论怎么修改,只要能跑过测试,基本上该atom插件是可以work的。这大概也是为什么敏捷宣言里面敢说『拥抱变化』,这是因为有测试在保证吧。 服务器模块 负责人:邢亮 主要工作 主要负责服务端功能的实现以及Devops的相关工作。 服务端的工作有: 内置自动机逻辑令用户可以使用公众号进行文字交互式游戏 传输给前端需要的游戏数据 接收json数据来创建游戏 负责服务端开发的同时,邢亮也负责Devops的相关工作,主要体现在: 阿里云服务的配置 持续部署服务 Crash Report服务 容器管理服务 技术介绍 SPRING BOOT 我们的服务端使用spring boot微框架来搭建。spring boot可以说是一个非常棒的框架,作为一个规模不大的服务端软件来说,使用spring boot进行搭建会节省很多的人力成本。 它本身具有嵌入式的应用服务器,支持打包fat jar,在部署时仅仅需要一个Java虚拟机使用java jar即可启动服务器,方便快捷。 另一方面,spring boot完美的继承了spring 框架的特征,对AOP,IOC熟悉的开发人员可以很快上手。 JPA 引入spring boot的同时,我们也引入了官方推荐的spring jpa ORM框架,它可以通过代码来关联数据库表,不需要写繁杂的配置文件及SQL脚本,减少了我们很多的工作量和维护成本。 DOCKER docker是最近非常火爆的虚拟化技术,我们引入docker来将我们的服务构建成docker镜像,大幅度的减轻了我们服务部署、回滚、维护的压力。 我们会在下一节进一步介绍我们对docker的应用。 模型设计 为了将游戏形式化,我们将之抽象为一个有向图,用户通过遍历有向图即可完成游戏进程。对于有向图的每个点,我们将之称之为游戏段落。用户在每个段落中可以进行选择,根据不同的选择他会踏向不同的后续段落,如果这个段落对应的节点的度只有1的话,那么游戏就结束了,可能是好结局也有可能使BAD END. 为了让关系型数据库可以存储有向图,我们将有向图进一步进行了抽象,将之分为几个Model,分别为: Game 游戏 point 段落 Selection 选项 Line 段落跳转 User 用户 Game 中主要存储有游戏id,游戏名称,创建者的id,创建时间,以及第一个段落的id。 Point 中主要存储了段落id,段落文本,对应游戏id,创建时间以及是否已经结束。 Selection 中主要存储了选项id,选项文本,对应游戏id,及对应段落id。 Line 中主要存储来源段落id,目标段落id,游戏id,及这条线需要的条件即用户当前及过去所选择的选项。 User 中主要存储了用户信息,及他所处的段落,以及他选过的选项等。 完成模型的设计后,我们就可以将游戏存储在数据库当中,并方便随时将之转化为有向图进行遍历。 微信接口的使用过程 在设计自动机过程中的一个主要工作就是与微信公共平台的通信了。微信使用XML作为通信格式。 为了使用微信接口,我们注册了一个微信公共号 文字游戏云 ,申请通过后腾讯给我们一个key,方便我们与之通信。 在接口调用前,腾讯需要验证我们的服务器是否正常运行,它会向服务器80端口的某个url发送一个GET请求,附带有时间戳等信息,我们将我们的令牌,时间戳组装成一个string,并使用SHA 1进行签名,与请求进行比对,如若无误我们返回请求的一个字段即可完成验证。 这部分操作主要是腾讯为了方便我们验证微信公共平台身分所设立的操作。 在后续的通信过程中,它都会用这一操作做为第一步。 如果微信公共号收到了用户的一条消息后,它会进一步的向服务器相同url的地址发送POST请求, 附带XML编码的用户消息。 用户消息中主要有用户的微信号,消息类型,内容等。我们就可以使用这部分信息进行自动账号注册, 游戏进程控制等功能了。 游戏进程控制 为了完成游戏进程控制,我们将用户的状态分为: 新用户(NEW_USER) 老用户又来玩(JUST_COME) 选择游戏(SELECT_GAME) 游戏中(GAMING) 在用户发送消息后,我们会根据它发送信息的属性,判断他所处的状态。比如这个用户从来没有发送过信息,我们就会将之归类为新用户。比如他上次发送信息与这个发送信息时间差距太久,我们就会将之归为JUST_COME。其他状态会根据游戏进程的不同情况进行判断。 获取状态后,我们根据不同状态会指派不同的服务来处理用户的请求,比如它处在游戏状态中,我们就会使用游戏自动机来判断他的下一个段落是什么,或者游戏是否结束等等。 DEVOPS 负责人:邢亮 代码管理 我们使用了Git来管理代码,成员的代码都会提交到onboard当中。与传统方式不同的是,我们有四位成员,我们会使用不同分支来管理各自的代码。 持续部署 我们使用阿里云作为我们的服务器。我们引入了Jenkins来做持续部署工具。 首先我们使用Maven Docker插件,来构建我们服务的镜像。Jenkins检测到代码仓库有变动时,会使用 mvn clean package docker:build 命令完成服务镜像的构建,并放置在本地docker仓库。接下来Jenkins会将本地启动的上一版本的容器删除,并使用docker run指令新建一个容器将最新的服务跑到docker引擎中,并暴露相应的接口。完成持续部署过程。 CRASH REPORT管理 我们搭建了Sentry服务来帮助我们进行Crash Report的管理,当我们的引擎服务有日志输出时,判断它的级别,如果是warning以上级别,我们会将日志发送到Sentry当中,并通知我们这些开发人员,出现了bug。之后我们会根据情况及时修复。 容器管理 我们引入了希云管理我们的docker镜像和容器,持续部署过程是有风险的,我们经常会出现部署的版本有bug的情况,所以我们需要有迅速回滚的能力,我们在本地保存了5天内持续部署过程生成的镜像,并将之存储在本地仓库中,让希云管起来。 当我们需要迅速进行回滚时,我们仅仅需要删除现在的容器,并启动生成上一版本的容器即可完成回滚。 前端页面 负责人:靳灿灿 功能目标 首先介绍下前端页面实现的功能目标。 前端部分实现的主要功能是向后台请求游戏数据(json格式),实现在手机和pc端的浏览器网页上展示游戏列表,并正确渲染每个小游戏。 对于该功能,需要实现以下基本需求: 一个单页面应用即可, 游戏列表界面,点击选择游戏。 友好地适配各种手机终端。 参考橙光游戏的游戏界面,希望故事情节的展示具有逐字打印的效果 考虑一些提高功能:好感度,插图,配乐等,提高用户体验。 项目进展回顾: 以中期检查为时间点,中期之前,我通过jquery,css,html5等基础前端语言,实现了一个只有四五个章节的超简易的小游戏的页面渲染。该游戏可以在手机及pc端浏览器页面上正确运行,并且故事情节的展示具有逐字打印效果。游戏界面如图1。 图1:游戏界面 逐字打印效果的实现原理是先隐藏故事段落,根据字数长度,定时调用追加一个字符的函数,直至段落完全显示。 图2:逐字打印效果代码 此后,开始尝试新的故事剧本,很快发现代码逻辑不够清晰,段落跳转频频出错。此时接触到angularjs的双向数据绑定特性(bi directional data binding)。例如,在Input里设置属性ng model=”yourcontent”将文本输入框绑定到名为yourcontent的模型变量。在其他位置使用改模型变量就会得到该变量的实时数据,输入框的任何更改会立即反应到模型变量上。angularjs通过作用域来保持数据模型和视图界面UI的双向同步,一旦模型状态发生改变,angularjs会立即刷新反映在视图界面。与上面通过jquery实现的代码相比,使用angularjs,可以不再需要专门注册事件侦听器或者添加事件处理程序,减少了大量代码,极大地节约开发时间。 鉴于此,后期使用angularjs对前端代码进行了重构。页面核心代码如图3。通过用户不同点击行为,改变当前展示的故事段落。同时,对页面的样式等也做了调整,最终的页面较之之前更加美观,适配性也更好。访问地址: http://115.28.225.159/ http://115.28.225.159/ 。 图3:angualrjs核心代码展示 敏捷实践 根据上面的介绍,项目开发中接触到了代码重构(refactor)。项目开发前期注重功能的实现,完成了需求之后,却发现代码不精炼,冗余且结构混乱。通过重构,系统运行的正确性没有受到影响,但是实现的代码更精炼和易于维护了。借助angularjs的数据双向绑定,页面的跳转可以简单地通过绑定变量实现,大大精简了代码。 单元测试 负责人:周鸿博 JUNIT和MOCKITO 对于JUnit,这里就不详细介绍了,网上的教程有很多,比如 这个 http://www.cnblogs.com/yangxia test/p/3991572.html 和 这个 http://huihai.iteye.com/blog/1986568 。 下面主要介绍一下 Mockito 。 什么是mock测试,什么是mock对象? 先来看看下面这个示例: 从上图可以看出如果我们要对A进行测试,那么就要先把整个依赖树构建出来,也就是BCDE的实例。 一种替代方案就是使用mocks 从图中可以清晰的看出: mock对象就是在调试期间用来作为真实对象的替代品 mock测试就是在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试 模拟的好处是什么? 提前创建测试; TDD(测试驱动开发) 如果你创建了一个Mock那么你就可以在service接口创建之前写Service Tests了,这样你就能在开发过程中把测试添加到你的自动化测试环境中了。换句话说,模拟使你能够使用测试驱动开发。 团队可以并行工作 这类似于上面的那点;为不存在的代码创建测试。但前面讲的是开发人员编写测试程序,这里说的是测试团队来创建。当还没有任何东西要测的时候测试团队如何来创建测试呢?模拟并针对模拟测试!这意味着当service借口需要测试时,实际上QA团队已经有了一套完整的测试组件;没有出现一个团队等待另一个团队完成的情况。这使得模拟的效益型尤为突出了。 你可以创建一个验证或者演示程序。 为无法访问的资源编写测试 这个好处不属于实际效益的一种,而是作为一个必要时的“救生圈”。有没有遇到这样的情况?当你想要测试一个service接口,但service需要经过防火墙访问,防火墙不能为你打开或者你需要认证才能访问。遇到这样情况时,你可以在你能访问的地方使用MockService替代,这就是一个“救生圈”功能。 Mock 可以分发给用户 隔离系统 知道什么是mock测试后,那么我们就来认识一下mock框架 Mockito。 Mockito区别于其他模拟框架的地方主要是允许开发者在没有建立“预期”时验证被测系统的行为。 MOCKITO入门实例 Maven依赖: Xml代码 ...

javascriptspringboot敏捷开发文字游戏引擎

9

点赞

16

回复

30848

浏览

基于Spring MVC的 Websocket在线聊天室

每天大家都在使用QQ等即时聊天工具,今天我们就使用Spring框架以及websocket技术在网页端简单的实现一个在线聊天的功能。 关于Spring MVC的知识这里不会详述,请大家参考 Spring MVC实战入门训练 https://course.tianmaying.com/spring mvc 。 添加MAVEN依赖 在线聊天室使需要使用到的技术或者框架包括: maven作为构建工具 spring boot作为后端框架 spring websocket作为即时消息通讯工具 thymeleaf作为模板引擎 angular作为前端框架 因此,我们首先在 pom.xml 中添加上述依赖: ...

javaspring-mvcspringboot

1

点赞

0

回复

4865

浏览

Spring Boot命令行界面的使用

Spring Boot提供了命令行界面(Command Line Interface, CLI),可以用来运行和测试Spring Boot应用。Spring Boot及其CLI可以在Spring仓库中手动 下载和安装 http://docs.spring.io/spring boot/docs/current SNAPSHOT/reference/htmlsingle/ getting started installing spring boot ,更简单的方式时通过 Groovy环境管理器 http://gvmtool.net/ (Groovy enVironment Manager,GVM)。 基于CLI可以极速创建一个Web应用。接下来我们看看如何创建一个Spring MVC应用,以及如何支持在前端中使用Thymeleaf模板引擎和jQuery。我们将使用Groovy来创建项目,你会发现,一切简单得醉了! 安装SPRING BOOT CLI CLI是Spring Boot自带的,首先我们要来安装Spring Boot。 安装有多种方式,我们可以先通过GVM来安装: curl s get.gvmtool.net | bash GVM安装之后( 注意这里要重启启动一个Terminal),Spring Boot的安装就非常简单了: gvm install springboot 执行 spring version 应该可以看到输出: Spring CLI v1.2.5.RELEASE...

javaspringbootspring

0

点赞

6

回复

17383

浏览

整合Spring Data JPA与Spring MVC:使用@Query标注自定义查询语句

在 使用JPA访问关系型数据库 http://tianmaying.com/tutorial/spring boot jpa 和 Spring Data Jpa: 分页和排序 http://tianmaying.com/tutorial/spring jpa page sort 两篇文章中我们学会了如何使用Spring Data Jpa 进行简单的查询以及分页等功能,Spring Data Jpa本身所支持的功能已经非常强大了,也能够支持大部分的场景。但是,现实场景永远比想象的要复杂,有时候我们确实需要像Sql语句这样更加强大以及灵活的方式来进行查询。Spring Data Jpa 当然给我们提供了这样的方式,我们可以使用 @Query 标注轻松的使用类似sql查询的功能。今天我们来尝试一下如何使用 @Query 标注来自定义查询吧。 基础对象 Spring Data Jpa所提供的通过方法名进行查询的功能已经能够覆盖绝大多数单表查询了。但是,我们的查询绝不仅限于单表查询,很多时候我们还是需要进行多表查询的,因此我们今天设计两个表, blog 以及 user ,通过这两个表的联合查询来试验 @Query 标注。 @Entity...

javaspringspringbootjpa

1

点赞

0

回复

3015

浏览

基于Spring提供支持不同设备的页面

基于Spring来检测访问Web页面的设备是很简单的,在这个 经验 http://tianmaying.com/tutorial/spring device detection 中我们讲到过。通常不同的设备访问我们是通过响应式设计来统一处理各种设备的尺寸的。但是如果希望针对不同的设备,显示不同的内容呢? Spring对于这一点同样提供了很好的支持,来看看如何实现。 准备工作 我们通过一个简单的例子来演示,基于Spring MVC来实现一个简单的HTTP GET请求,访问的地址是: http://localhost:8080/sayHello http://localhost:8080/sayHello 如果从桌面浏览器访问这个地址,则返回的页面中显示: Say hello from desktop 如果从手机浏览器访问这个地址:则返回的页面中显示 Say hello from mobile 如果从平板电脑访问这个地址:则返回的页面中显示 Say hello from tablets 先该准备好开发环境: IDE+Java环境(JDK 1.7或以上版本) Maven 3.0+(Eclipse和Idea IntelliJ内置,如果使用IDE并且不使用命令行工具可以不安装) Maven POM文件的设置 pom.xml ...

javaspringspringboot

5

点赞

5

回复

8538

浏览

在Docker容器中运行Spring Boot应用

Spring Boot简化了Spring应用的开发过程,遵循约定优先配置的原则提供了各类开箱即用(out of the box)的框架配置。另一方面,Spring Boot还具备将代码直接构建为可执行jar包的能力,这个jar包是一个可以独立运行的部署单元。基于以上特性,现在普遍认为 Spring Boot http://www.infoq.com/articles/microframeworks1 spring boot 提供了一种快速构造 微服务(Micro Service) http://martinfowler.com/articles/microservices.html 的能力。 DOCKER与SPRING BOOT Docker https://www.docker.com/ 是一种Linux容器的实现,Linux容器是基于进程的轻量级资源隔离技术,每一个容器对应操作系统中的一个进程,但是它又会有自己的网络空间、文件系统、PID等。Docker除了实现Linux容器,还使得容器具有“社会化”的功能,用户可以将容器镜像发布在 Docker Hub https://hub.docker.com 与其他开发者共享、协作。安装Docker的教程请参考 官方文档 https://docs.docker.com/ Spring Boot应用通常被构建为一个可单独执行的jar包,通过 java jar ... 运行,但是框架本身并没有提供以服务形式运行在后台的方法,通常需要借助Systemd, Supervisord等进程管理工具来实现。另一方面,虽然应用运行环境非常的简单,但是将他们容器化为Docker容器镜像并运行,对于自动化部署、运维都是非常有利的。 本文将以一个最简单的Spring Boot开发的Web应用为例,讲解如何将其容器化运行。本文的重点是构建Docker镜像、运行Docker容器,关于Spring Boot开发Web应用可以参考 Spring Boot应用开发 http://tianmaying.com/tutorial/spring boot intro 构建并SPRING BOOT应用 在应用代码编写完成后,可以直接将其打包并运行: Maven: mvn package && java jar target/spring boot docker 0.1.0.jar Gradle: gradle build && java jar build/libs/gs spring boot docker 0.1.0.jar 在浏览器地址栏种输入 http://localhost:8080/ http://localhost:8080/ ( http://localhost:8080/ http://localhost:8080/ ) 可以访问应用 DOCKERFILE构建镜像 Docker提供了 Dockerfile https://docs.docker.com/reference/builder/ 格式的文件来构建应用镜像,现在开始创建一个Spring Boot应用的Dockerfile: FROM java:8...

dockerspringbootjava

0

点赞

3

回复

3956

浏览

测试Spring MVC应用

Spring的依赖注入使得我们的代码非常容易进行单元测试—— @Controller , @Service , @Entity 等注解标注的类基本都是POJO(plain old Java object),也就是说很少依赖于Spring容器本身的API。我们可以非常容易地使用 JUnit http://junit.org/ 或 TestNG http://testng.org/ 编写测试代码。另一方面,对于三层架构的Spring Web应用(Controller, Service, DAO),使用Mock活Stub方法也能够更好的来测试我们的代码逻辑。例如Service层代码的单元测试中,依赖的DAO(或Repository)对象都是根据应用测试需求Mock出来的,而不需要真正去访问数据库。 SPRING WEB测试 在对Spring Web应用中的 @Controller 代码进行单元测试的过程中,一般的方法是创建 @Controller 对象,同时将它依赖的一些Mock对象——例如 MockHttpServletRequest , MockHttpServletResponse (都由 spring test 模块提供,无需自己编写)作为 @Controller 方法的参数。但是对于处理Web请求的 @Controller 代码来说,仅仅测试Handler方法里的代码是远远不够的,对于一个处理HTTP请求的 @Controller ,我们还需要测试: @RequestMapping 路由是否正确 数据绑定、类型转换、校验逻辑是否正确——数据包括URL参数、表单、 @PathVariable 等 @InitBinder , @ModelAttribute , @ExceptionHandler 等注解的方法或属性计算过程 上述过程贯穿于HTTP请求处理的生命周期中,所以对于Spring Web应用中 @Controller 代码单元测试的概念,应该做一些扩充——不仅仅局限于代码本身,也要结合MVC框架中的各个处理过程。 本文接下来的内容代码,都以Spring Boot为例,首先假设我们通过Spring Boot创建了一个最简单的Web Mvc应用——包含了一个最简单的Conroller,处理 /users/{id} 对应的HTTP请求,返回值是 id={id} (通过 String.format() 方法),那么可以为它创建如下测试代码: import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;...

springspringbootspring-mvcjava

11

点赞

8

回复

13888

浏览

基于Spring的微信第三方登录实现

在前几篇文章中,我们介绍了 OAuth2.0认证和授权机制讲解 http://tianmaying.com/tutorial/oAuth login ,并实现了 基于Spring的Github第三方登录 通用化的第三方登陆实现 http://tianmaying.com/tutorial/OAuth login impl ,之后,我们基于该通用化的框架,介绍了国内的两个比较流行的第三方登录平台: 基于Spring的新浪微博第三方登录实现 http://tianmaying.com/tutorial/OAuth login weibo 和 基于Spring的QQ第三方登录实现 http://tianmaying.com/tutorial/OAuth login QQ 。以上几个第三方登录平台都严格遵守了OAuth2.0协议。但是,近来作者发现微信的第三方登录确不是那么严格的遵守通用化的OAuth2.0协议,有些细节实现不太一样(例如获取AccessToken时其他OAuth平台用的字段名为client_id,但是微信中是appid),这就导致了之前的通用化框架在微信登录时遇到了很多问题,今天我们就来介绍一下微信的第三方登录,并重构一下我们的通用化框架,使之在遇到其他不那么严格遵守OAuth协议的平台依然简单实用。 申请第三方应用 接下来我们首先来看看如何在 微信开放平台 https://open.weixin.qq.com 中申请一个第三方应用。 首先,我们需要完善开发者资质认证,在导航栏选择【账号中心】,然后选择【开发者资质认证】,我们会看到如下页面: 从页面信息介绍中的第二点我们可以知道,通过开发者资质认证后,我们就能够获得微信第三方登录的能力。需要注意:个人是不能申请第三方认证的,必须为以下机构或者团体才能进行认证,每次审核需要花费300元: 开发者资质认证提交并缴费后,会在两个工作日内进行审核,如果有问题会有客服人员电话沟通。 审核完成后,进入【管理中心】 【网站应用】。 点击【创建网站应用】,按照其提示填写相关内容即可: 提交完成后,如果你的开发者资质已经通过,就可以直接进行开发上线啦。现在,让我们看看如何添加微信第三方登录的代码。 第三方登录通用架构 现在,我们将 基于Spring的Github第三方登录 通用化的第三方登陆实现 https://open.weixin.qq.com/cgi bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=78aa41f9fac1f47ca6d3bd20fe9e2ad7681e9e3c&lang=zh_CN 中的通用化架构添加到代码中来,以此为基础添加微信登录的相关功能: 微信第三方登录服务分析 首先,让我们我们看看 微信登录开发文档 https://open.weixin.qq.com/cgi bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=78aa41f9fac1f47ca6d3bd20fe9e2ad7681e9e3c&lang=zh_CN ,看过之后,我们发现微信登录虽然是基于OAuth2.0协议,但是API的参数确不一样。之前我们做过github、微博、QQ其获取Access Token时所需的参数为 client_id 以及 client_secret ,Scribe默认的OAuthService在处理也是同样的参数,因此我们可以通过其默认的 OAuth20ServiceImpl 来处理OAuth的相关操作。 但是微信中 client_id 、 client_secret 两个参数统一用的是: appid 、 secret 。这也就意味着我们需要实现自己的 WeixinOAuth20Service 来对这些细节进行处理。同时,添加完成后,我们还需要添加一个 WeixinOAuthDeractorService 来适配 通用化的第三方登陆实现 https://open.weixin.qq.com/cgi bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=78aa41f9fac1f47ca6d3bd20fe9e2ad7681e9e3c&lang=zh_CN 中的设计。 但是 WeixinOAuth20Service 以及 WeixinOAuthDeractorService 实际上功能是一样的,只是我们需要一个CustomOAuthService来对OAuthService进行管理。如果我们通过一个接口对OAuthService进行管理的话,我们就只需要添加一个类 WeixinOAuthService 即可,同时这也符合依赖于接口而不是实现的最佳原则。 通过接口管理OAUTHSERVICE 我们首先来添加一个接口 CustomOAuthService : publicinterfaceCustomOAuthServiceextendsOAuthService{...

oauthspringjavaspringbootspring-mvc

3

点赞

1

回复

4037

浏览

基于Spring的QQ第三方登录实现

之前我们完成了 基于Spring的Github第三方登录 通用化的第三方登陆实现 http://tianmaying.com/tutorial/OAuth login impl 以及 基于Spring的新浪微博第三方登录实现 http://tianmaying.com/tutorial/OAuth login weibo ,接下来我们来学习一下如何实现QQ第三方登录。 完善个人信息 在实现QQ第三方登录功能之前,需要前往 QQ互联 http://connect.qq.com/ 完善个人信息,并添加你的第三方应用的相关信息。 访问 QQ互联 http://connect.qq.com/ ,点击【管理中心】,进入应用开发者完善界面: 创建第三方应用 按要求注册应用者开发信息后,进入 应用管理中心 http://connect.qq.com/manage/index ,点击【创建应用】,选择网站,按要求填写相关信息,与微博一样,QQ也需要填写网站地址以及验证是否是网站所有者,验证方法和微博一样,都是在首页添加一行代码,同时,还需要填写回调地址: 创建成功后我们就能得到相应的 appId 以及 appKey 。 第三方登录通用架构 同样,我们将添加 基于Spring的Github第三方登录 通用化的第三方登陆实现 http://tianmaying.com/tutorial/OAuth login impl 中的通用化架构: QQAPI 首先,添加QQApi,为OAuthService提供进行OAuth验证的各个地址,相关的地址可以在 QQ OAuth2.0开发文档 http://wiki.connect.qq.com/oauth2 0%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3 中得到,最终的QQApi代码如下: public class QQApi extends DefaultApi20 {...

oauthjavaspringboot

1

点赞

5

回复

4110

浏览

基于Spring的新浪微博第三方登录实现

在《 Github第三方登录 通用化的第三方登陆实现 http://tianmaying.com/tutorial/OAuth login impl 》中我们实现了一个通用化的第三方登录框架,其中包括OAUth的基本流程以及最简单的用户注册。但是不同的第三方登录因为其细节不同还是有很多坑的,今天我们就从完善开发者信息开始一步一步添加微博第三方登录的功能。 注意,需要完成微博的第三方登录功能需要有一个域名以及修改该域名网站的权限,之后审核时需要对首页进行修改。这里我们假设我们的域名是tianmaying.com。 完善用户信息 首先我们进入 新浪微博开发平台 http://open.weibo.com/ ,登录我们的微博账号,点击右上角的【我的应用】,我们就会看见相关的功能以及相对应需要完善的信息。 我们可以看到,如果需要添加第三方应用只需要完善基本信息,但是需要注意的是,如果你添加了微博第三方登录功能后需要通过其审核,仍然需要通过【身份认证】。这里我们只需要完善【基本信息】即可。 点击右侧的【基本信息】,按要求添加相关的信息,最后完成邮箱验证,我们的基本信息就添加完成了。之后我们需要添加网站的相关信息: 选择左上角的【微连接】 【网站接入】,之后再选择【立即接入】: 我们需要验证的是我们是否对于网站拥有所有者权限,需要修改域名相对应的网页上添加一行代码,按要求进行修改即可。 验证通过后,我们就可以在本地进行第三方登录的测试了。 添加第三方通用登录框架 《 Github第三方登录 通用化的第三方登陆实现 http://tianmaying.com/tutorial/OAuth login impl 》一文中已经完成了一个通用化第三方登录的框架,如果想对通用化第三方登录的实现有所了解,请先阅读《 Github第三方登录 通用化的第三方登陆实现 http://tianmaying.com/tutorial/OAuth login impl 》。 我们直接复制上述代码,去除掉github相关的代码: 添加SINAWEIBOOAUTHSERVICE 按照《 Github第三方登录 通用化的第三方登陆实现 http://tianmaying.com/tutorial/OAuth login impl 》,我们需要为Weibo添加两个类, SinaWeiboAPI 以及 SinaWeiboOAuthService ,但是 SinaWeiboAPI 在 scribe http://tianmaying.com/tutorial/OAuth login impl 中已经提供了,我们直接使用即可。接下来我们来添加 SinaWeiboOAuthService : public class SinaWeiboOAuthService extends OAuthServiceDeractor {...

oauthjavaspringboot

新建主题 记录代码

学员动态

  • z**i向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • k**7向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • j**0向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • z**i在亚博国际线上娱乐--任意三数字加yabo.com直达官网中提出了问题:和c++有什么区别需...
  • 1**3向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • v**g向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • z**i向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • 1**3向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • j**0向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • w**3回复了j**2在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:下载jdk1.8 老...
  • S**e向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • k**7向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • k**7向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • j**0向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • 天码君回复了j**0在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:欢迎来到天码营学习,...
  • l**m在亚博国际线上娱乐--任意三数字加yabo.com直达官网中提出了问题:第17课 反射的实战...
  • c**n向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • S**e回复了S**e在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:第四课: 作业问题 ...
  • 多谷乐向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • S**e向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • z**i在亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中回复了老师:输出似乎是对的,可是...
  • S**e评论了:老师我运行如下这段作...
  • 1**3向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • 1**3向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • j**i评论了:为啥实战章节是404...
  • j**2在亚博国际线上娱乐--任意三数字加yabo.com直达官网中提出了问题:老师,我一步一步按照...
  • 天码君回复了多谷乐在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:欢迎来到天码营学习,...
  • 天码君回复了z**i在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:欢迎来到天码营学习,...
  • 1**3向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • 天码君回复了叛逆吟游在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:欢迎来到天码营学习,...
  • z**i向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • 叛逆吟游在亚博国际线上娱乐--任意三数字加yabo.com直达官网中提出了问题:老师好,我好像下载不...
  • C**f评论了z**i在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的作业:for循环里数组越界...
  • w**3评论了R**_在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的作业:public sta...
  • z**i向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • I**2向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • k**7完成了亚博国际线上娱乐--任意三数字加yabo.com直达官网的作业
  • 天码君回复了S**e在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:欢迎来到天码营学习,...
  • 天码君回复了j**2在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:欢迎来到天码营学习,...
  • 9**6向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • z**i在亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中回复了老师:输出似乎没有错,可是...
  • 9**6向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • l**m评论了R**o在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的作业:这里要加上scann...
  • w**3回复了l**m在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:public sta...
  • k**7向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • 天码君回复了f**0在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:欢迎来到天码营学习,...
  • c**n评论了:哪里有所有的答案,很...
  • 1**3向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • 天码君回复了9**6在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:欢迎来到天码营学习,...
  • S**e回复了S**e在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:另外课否请老师 解锁...
  • l**m向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • j**0向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • z**i在亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中回复了老师:运行结果应该是符合题...
  • 1**3在亚博国际线上娱乐--任意三数字加yabo.com直达官网中提出了问题:定义实例属性的时候s...
  • I**2向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • I**2向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
  • w**3回复了z**i在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:函数的声明,定义; ...
  • 天码君回复了c**n在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:欢迎来到天码营学习,...
  • w**3回复了叛逆吟游在亚博国际线上娱乐--任意三数字加yabo.com直达官网中的问题:直接百度 java8...
  • c**n向亚博国际线上娱乐--任意三数字加yabo.com直达官网作业中提交了代码
反馈意见