建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

更新 :我们最近发布了对Stormpath Spring Security集成的修订。 您不再需要从特殊的Stormpath安全配置器适配器继承。 而是使用Stormpath DSL(特定于域的语言)。 看下面看这有多容易。

♥在Stormpath,我们♥Spring Boot。 构建丰富的Java Web应用程序变得如此轻松有趣。

我们对最新的Java SDK版本感到非常兴奋,其中包括对我们的Spring Security和Spring Boot支持的重大改进。

如果您以前曾经构建过Web应用程序,那么您将知道所有“用户资料”都是您的头疼。 Stormpath为开发人员提供了开箱即用的所有“用户资料”,因此您可以继续真正关心的是您的应用程序! 到本教程完成时(我保证不到15分钟),您将拥有一个可以正常运行的Spring Boot Web应用程序,该应用程序可以通过Spring Security保护用户对受限路径的访问,并得到Stormpath的支持。

我们将专注于我们的Spring Boot集成,以推出一个简单的Spring Boot Web应用程序,该应用程序具有完整的用户注册和登录系统,并具有以下功能:

  • 登录和注册页面
  • 密码重置工作流程
  • 根据组成员身份限制访问
  • 能够轻松启用Java库中的其他Stormpath功能(API身份验证,SSO,社交登录等)的功能

在本演示中,我们将使用stormpath-default-spring-boot-starter 。 它的模块化设计在Spring Boot 1.3.0和Spring Security 4.0.3以及Spring Boot WebMVC和Thymeleaf模板引擎中得到了体现。 我将使用Mac,终端应用程序和IntelliJ IDE。

本教程的所有代码都可以在这里找到。

在整个文章中,您可以通过单击Deploy to Heroku按钮来查看示例代码。 您需要做的就是注册一个免费的Heroku帐户。

什么是暴风雨?

Stormpath是一项API服务,允许开发人员创建,编辑和安全地存储
用户帐户和用户帐户数据,并将它们与一个或多个应用程序连接。 我们的API使您能够:

  • 验证和授权用户
  • 存储有关您的用户的数据
  • 执行密码和基于社交的登录
  • 发送密码重置消息
  • 发行基于API的Web应用程序的API密钥
  • 以及更多! 查看我们的产品文档

简而言之:我们使用户帐户管理变得更加轻松,安全和更多
可扩展性比您可能习惯的高。

准备开始了吗? 在此处注册免费的开​​发者帐户。

启动您的Spring Boot项目

有您的Stormpath开发者帐户? 大! 让我们开始吧…

无论你是一个Maven 的Maven或摇篮克里特 ,让您的项目设置是一个单元。

这是一个以pom.xml开头的文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.stormpath.sample</groupId><artifactId>stormpath-spring-boot-spring-security-tutorial</artifactId><version>0.1.0</version><name>Spring Boot Spring Security Stormpath Tutorial</name><description>A simple Spring Boot Web MVC application with Spring Security and out-of-the-box login and self-service screens!</description><dependencies><dependency><groupId>com.stormpath.spring</groupId><artifactId>stormpath-default-spring-boot-starter</artifactId><version>1.0.RC6</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>1.3.0.RELEASE</version><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>

而且,这是一个以以下内容开头的build.gradle文件:

buildscript {repositories {mavenCentral()}dependencies {classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.RELEASE")}
}apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'spring-boot'group = 'com.stormpath'
version = '0.1.0'repositories {mavenCentral()
}dependencies {compile group: 'com.stormpath.spring', name: 'stormpath-default-spring-boot-starter', version:'1.0.RC6'
}

您可能会注意到,对于Maven和Gradle来说,都存在一个依赖关系: stormpath-default-spring-boot-starter 。 对。 而已。 正如您将在下面看到的那样,一个依赖项立即为您提供了所有的Spring Boot,Spring Security和Stormpath魔术。

收集您的API凭证和应用程序参考

应用程序和Stormpath之间的连接通过“ API密钥对”进行保护。 您将提供这些密钥
到您的Web应用程序,并且在与Stormpath通信时将使用它们。 您可以从管理控制台下载API密钥对。 登录后,您可以从主页下载API密钥对,它将下载apiKey.properties文件-我们稍后将使用它。

在管理控制台中时,您要获取默认Stormpath应用程序的href。 在Stormpath中,Application对象用于将Web应用程序链接到Stormpath中的用户存储。 所有新的开发人员帐户都有一个名为“我的应用程序”的应用程序。 在管理控制台中单击“应用程序”,然后单击“我的应用程序”。 在该页面上,您将看到应用程序的Href。 复制它-我们稍后将需要它。

编写Spring Boot应用程序

该部分的代码可以在代码库的LockedDown标记中找到。

我们需要三个小的Java类和一个html模板来启动Webapp的第一个版本。 它们足够小,我会把它们放在这里。 让我们开始吧!

Spring Boot应用程序入口点

所有的Spring Boot应用程序都有一个入口点,其作用与普通的Java程序相同。 它具有main方法和所有内容。

这是Application.java

@SpringBootApplication
public class Application  {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

6行代码(包括@SpringBootApplication批注)拉开了序幕。

Spring安全配置

默认情况下(以及最佳安全实践),Spring Security会锁定整个应用程序。 它将其锁定到甚至无法访问的地步! 尽管这符合最佳安全性实践,但并不是很有用。 另外,我们需要将Spring Security和Stormpath挂钩。 这将我们带到我们的SpringSecurityWebAppConfig.java

@Configuration
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.apply(stormpath());}
}

@Configuration注释使Spring Boot将该类实例化为配置。 .apply(stormpath())将所有Stormpath优点(身份验证和授权工作流程)挂接到Spring Security中。

因为configure方法中没有进一步的配置,所以我们仍然会看到将所有内容锁定的默认行为。 但是,我们将看到默认的Stormpath流程,而不是默认的Spring Security身份验证流程。 也就是说,尝试浏览到应用程序中的任何路径将导致重定向到Stormpath login页面。

因此,一个1行的方法调用就可以保证安全!

Spring WebMVC紧密联系在一起

我们上面的安全性配置可确保保护应用程序中的所有路径。

控制器确定请求的路径如何定向以显示哪些模板。

这是我们的HelloController.java

@Controller
public class HelloController {@RequestMapping("/")String home() {return "home";}
}

@Controller注释@Controller Spring Boot这是一个控制器。 我们在第3行/上定义了一个路径。 第5行返回Thymeleaf模板,命名为home

7行代码,我们有模型-视图-控制器(MVC)路由。

带我们

默认情况下,Thymeleaf模板引擎将在类路径中名为templates的文件夹中查找从控制器返回的templates 。 它还将寻找.html的默认扩展名。

因此,当上述控制器返回"home" ,Thymeleaf将在resources/templates/home.html找到模板。

让我们看一下home.html文件:

<html xmlns:th="http://www.thymeleaf.org"><head><!--/*/ <th:block th:include="fragments/head :: head"/> /*/--></head><body><div class="container-fluid"><div class="row"><div class="box col-md-6 col-md-offset-3"><div class="stormpath-header"><img src="http://stormpath.com/images/template/logo-nav.png"/></div><h1 th:inline="text">Hello, [[${account.fullName}]]!</h1><a th:href="@{/logout}" class="btn btn-danger">Logout</a></div></div></div></body>
</html>

第1行为Thymeleaf设置了th名称空间。

第3行看起来像html / xml注释。 但是,这是Thymeleaf接受的指令,以在此模板中包含片段。 该片段位于: resources/templates/fragments/head.html 。 该片段包含所有要挂接到Bootstrap样式中的视图的设置。

第13和14行是操作所在的位置。 由于应用程序中的每条路径均已锁定,因此我们知道进入此页面的唯一方法是登录后。Stormpath的神奇之处在于,一旦登录, account对象就始终在您的视图范围内。 第13行显示已登录用户的全名。 第14行提供了单击后注销的链接。

有关使用Thymeleaf模板的更多信息,请单击此处 。

让我们火起来!

创建一个Stormpath帐户,15行Java代码和19行HTML模板代码(其中3行非常重要),使我们到达了受Spring Security保护并受Stormpath支持的功能齐全的Spring Boot WebMVC应用程序的地步。

如果您以前将apiKey.properties文件存储在标准位置: ~/.stormpath/apiKey.properties并且只有为您创建的默认Stormpath应用程序,则无需其他配置即可启动该应用程序。

这是Maven的方式:

mvn clean package
mvn spring-boot:run

注意:由于存在repackage执行, spring-boot-maven-plugin还会创建一个uber-jar。 您可以通过运行java来行使相同的代码:

mvn clean package
java -jar target/*.jar

这是Gradle的方式:

gradle clean build
java -jar build/libs/*.jar

真? 是吗 对!

您可以浏览到http:// localhost:8080 /并查看其运行情况。

如果您将apiKey.properties文件存储在其他位置,或者定义了其他Stormpath应用程序怎么办? 没问题!

还记得您之前保存的Application Href吗? 我们现在将使用它。

这是Maven的方式:

mvn clean package
STORMPATH_API_KEY_FILE=~/.stormpath/apiKey.properties \
STORMPATH_APPLICATION_HREF=https://api.stormpath.com/v1/applications/4YHCurbtcaFC4TKKsd3AYQ \
mvn spring-boot:run

这是Gradle的方式:

gradle clean build
STORMPATH_API_KEY_FILE=~/.stormpath/apiKey.properties \
STORMPATH_APPLICATION_HREF=https://api.stormpath.com/v1/applications/4YHCurbtcaFC4TKKsd3AYQ \
java -jar build/libs/*.jar

通过将STORMPATH_API_KEY_FILESTORMPATH_APPLICATION_HREF环境变量添加到命令行,我们可以轻松地告诉我们的应用程序在哪里可以找到api键以及要使用哪个Stormpath应用程序。

Stormpath Java SDK具有极其灵活的配置机制。 当我们开始限制Stormpath Group成员对您的应用程序的访问时,我们将在下面看到更多内容。

使用Spring Security完善的访问控制

该部分的代码可以在代码库的BasicAccessControl标记中找到。

在上一节中,我们创建了一个紧密锁定的应用程序。 每个路径(包括/ )都要求您首先登录。

也许您想要一个可公开访问的主页。 也许您希望网站的某些部分可以被任何经过身份验证的用户访问,而站点的另一部分则只能包含属于特定组的成员。

我们将在本节中探索那些细粒度的控件。

我们将从允许公众访问主页开始。 用户仍然必须进行身份验证才能访问任何其他页面。

Spring安全:门口的保镖

还记得以前的空SpringSecurityWebAppConfig.java吗? 我们现在将添加一些东西:

@Configuration
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.apply(stormpath()).and().authorizeRequests().antMatchers("/").permitAll();}
}

Spring Security提供了一个流畅的界面来提供访问规则。

在上面的5-8行中,我们正在建立一个规则集,该规则集关于Spring Security如何允许访问我们的应用程序。

您可以用简单的英语来表示:

Permit anyone to go to the front door
Ensure that they've authenticated for anything else

我们指定的规则优先于锁定所有内容的默认行为。

让我们也更新我们的home.html模板:

<html xmlns:th="http://www.thymeleaf.org"><head><!--/*/ <th:block th:include="fragments/head :: head"/> /*/--></head><body><div class="container-fluid"><div class="row"><div class="box col-md-6 col-md-offset-3"><div class="stormpath-header"><img src="http://stormpath.com/images/template/logo-nav.png"/></div><!--/* displayed if account IS NOT null, indicating that the user IS logged in */--><div th:if="${account}"><h1 th:inline="text">Hello, [[${account.fullName}]]!</h1><a href="/restricted" class="btn btn-primary">Restricted</a><a th:href="@{/logout}" class="btn btn-danger">Logout</a></div><!--/* displayed if account IS null, indicating that the user IS NOT logged in */--><div th:unless="${account}"><h1>Who are you?</h1><a href="/restricted" class="btn btn-primary">Restricted</a></div></div></div></div></body>
</html>

请注意,我们现在有两个不同的部分。 第一个从第13行开始,如果用户已登录,则显示第一个。

如果用户未登录,则显示从第20行开始的第二部分。

这是正在运行的Thymeleaf模板。 它提供了非常强大的控件,可有条件地显示模板的各个部分。

在进行任何其他更改之前,让我们在这里暂停并像以前一样启动应用程序。

当浏览到http:// localhost:8080时 ,您将看到home模板的未经身份验证的版本。

单击“ Restricted按钮,您将按预期重定向到login表单。 验证之后,您将进入404页面,因为我们尚未定义受限页面。

让我们对其进行设置以完成本节。

定义受限页面就像在我们的控制器中添加路线并创建要显示的模板一样容易。 这是更新的HelloController.java

@Controller
public class HelloController {@RequestMapping("/")String home() {return "home";}@RequestMapping("/restricted")String restricted() {return "restricted";}
}

并且,这是一个新的restricted.html模板:

<html xmlns:th="http://www.thymeleaf.org"><head><!--/*/ <th:block th:include="fragments/head :: head"/> /*/--></head><body><div class="container-fluid"><div class="row"><div class="box col-md-6 col-md-offset-3"><div class="stormpath-header"><img src="http://stormpath.com/images/template/logo-nav.png"/></div><h1 th:inline="text">[[${account.fullName}]], You are allowed here.</h1><a href="/" class="btn btn-primary">Go Home</a></div></div></div></body>
</html>

注意我们如何重新使用head片段为该模板提供Bootstrap样式。

再次重新启动该应用程序,您将获得完整的体验。 记下主页如何更改,具体取决于您是否登录。

通过组成员身份进行Spring Security访问控制

该部分的代码可以在代码存储库的GroupAccessControl标记中找到。

Spring Security提供了一组注释和一种丰富的表达语言,用于控制对应用程序中方法的访问。 @PreAuthorize是最常用的Spring Security批注。 并且,最常用的SpringEL表达式包括hasRole

Stormpath集成了将Stormpath组连接到Spring Security角色的机制。

让我们看一下代码,然后将其分解。 我们将添加一项新服务,以限制组成员身份的访问。 这是AdminService

@Service
public class AdminService {@PreAuthorize("hasRole(@roles.ADMIN)")public boolean ensureAdmin() {return true;}
}

上面的第3行是关键。 注释和SpringEL表达式可以用简单的英语表示为:

Before this method is even entered,
check to see that user is authenticated and
is a member of the ADMIN group

check to see that user is authenticatedcheck to see that user is authenticated可能并不明显。 发生的是, @PreAuthorize检查只能在经过身份验证的用户上执行。 Spring Security非常聪明,可以在检查用户是否是指定组的成员之前检查用户是否已登录。

让我们深入探讨上面的Spring Expression Language。 Spring Security在哪里寻找@roles.ADMIN@符号是特殊的–它标识Java Bean。 在这种情况下,一个名为roles的bean。 我们希望在该bean内定义一个名为ADMIN的常量。

最终, hasRole需要检查代表Stormpath Group的唯一Href。 因此,我们的ADMIN常数必须是一个Java String ,该String将Href保留到用于管理员的Stormpath组中。

为了完成此配置并使它具有Roles.java动态性,我们需要一个名为Roles.java的新类:

@Component
public class Roles {public final String ADMIN;@Autowiredpublic Roles(Environment env) {ADMIN = env.getProperty("stormpath.authorized.group.admin");}
}

这9条线是如此强大,我在这里一览无余! 让我们深入。

通过在第1行用@Component注释此类,Spring将实例化它并将其公开为bean。 猜猜豆子的名字是什么? Spring将采用该类的名称,并以驼峰式大小写以默认情况下派生Bean名称。 因此,bean的名称是roles 。 甜!

第5行的@Autowired注释使Spring Environment对象传递到构造函数中。 在构造函数内部,由于ADMIN已被声明为final ,因此我们唯一的机会是对其进行设置-要求能够在hasRoles子句中使用它。

难题的最后一部分利用了一些Stormpath配置魔术。 请注意,我们正在将ADMIN的值设置为名为stormpath.authorized.group.admin的环境属性。 这是标准的Spring。 如果您的application.properties文件中有一个具有该名称的属性,那么它将在Spring Environment中可用。

Stormpath增加了将其设置为系统环境变量的能力,从而无需在应用程序中的任何位置硬编码该值(在这种情况下为Stormpath Group Href)。

通常,系统环境变量全部为大写字母,单词之间用下划线分隔。 Stormpath Java SDK自动将这些系统变量转换为小写的点分表示法。

挖这个:

STORMPATH_AUTHORIZED_GROUP_ADMIN=https://api.stormpath.com/v1/groups/1wcsYMUZhzytUH5GmdaFXC \
java -jar build/libs/spring-boot-spring-security-tutorial-0.1.0.jar

在后台,Stormpath会将STORMPATH_AUTHORIZED_GROUP_ADMIN系统环境变量转换为stormpath.authorized.group.admin环境变量。 这将被我们上面的代码处理。

! 谁想到只需几行代码就能实现这种魔力!

现在,我们需要将AdminService到我们的控制器。 这是我们更新的HelloController.java的相关部分:

@Controller
public class HelloController {@AutowiredAdminService adminService;...@RequestMapping("/admin")String admin() {adminService.ensureAdmin();return "admin";}
}

在第4行和第5行自动连接AdminService 。请注意,在第11行,我们正在调用adminService.ensureAdmin方法。 如果已登录的用户ADMIN组中,则将生成403 (禁止)响应。

最后的代码整理工作是创建一个admin.html模板。 在与该帖子相关的代码中,有一个简单的admin.html模板,该模板显示了格式正确的消息,确认您确实是管理员。

现在,要查看实际效果,您需要在管理控制台中进行一些Stormpath内务处理。

步骤如下:

  • 创建一个新的应用程序

  • 为应用程序创建一个名为“ admin”的新组

  • 在管理组中创建一个新帐户

  • 不在管理员组中创建一个新帐户

在与此帖子相关的代码中,我还包括了一个方便的错误页面,因此,如果您不在admin组中,那么您将获得格式正确的页面,而不是默认的403页面。

让我们来看看它的作用。 我们将像以前一样启动该应用程序,只是这一次我们将对在上一步中创建的新应用程序和组使用在管理控制台中找到的Href。

这是Maven的方式:

mvn clean package
STORMPATH_API_KEY_FILE=~/.stormpath/apiKey.properties \
STORMPATH_APPLICATION_HREF=https://api.stormpath.com/v1/applications/4YHCurbtcaFC4TKKsd3AYQ \
STORMPATH_AUTHORIZED_GROUP_ADMIN=https://api.stormpath.com/v1/groups/1wcsYMUZhzytUH5GmdaFXC \
mvn spring-boot:run

这是Gradle的方式:

gradle clean build
STORMPATH_API_KEY_FILE=~/.stormpath/apiKey.properties \
STORMPATH_APPLICATION_HREF=https://api.stormpath.com/v1/applications/4YHCurbtcaFC4TKKsd3AYQ \
STORMPATH_AUTHORIZED_GROUP_ADMIN=https://api.stormpath.com/v1/groups/1wcsYMUZhzytUH5GmdaFXC \
java -jar build/libs/spring-boot-spring-security-tutorial-0.1.0.jar

浏览到/admin页面。

如果您以在Stormpath admin组(在我的情况下为micah+admin@stormpath.com)中创建的用户身份登录,则可以访问管理页面。 如果您以创建的用户身份登录,而该用户不在Stormpath admin组中(在我的情况下为micah+user@stormpath.com),则将显示禁止页面。

无论您以谁身份登录,都可以像我们之前设置的那样访问/restricted页面。

包起来

好吧,我们在这里涵盖了很多领域,不是吗!

我们看到了如何保护单个页面以及如何基于组中的成员资格来保护方法。

我们看到了如何在你的类,它扩展应用 Stormpath WebSecurityConfigurerAdapter定义不同的路径访问控制,以及利用Spring安全的@PreAuthorize注释控制的更细的晶粒。

我们看到了Stormpath Java SDK管理环境配置属性以为您的应用程序提供高度灵活性而无需进行任何硬编码的几乎神奇的方式。

Java SDK和Spring Boot集成中还有许多功能。 在此处查看深入的教程。

随时随地提供支持或亲自给我 。

建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

翻译自: https://www.javacodegeeks.com/2016/06/simple-web-app-spring-boot-spring-security-stormpath-15-minutes.html

一个具有Spring Boot,Spring Security和Stormpath的简单Web应用程序-15分钟相关推荐

  1. Spring Boot + Spring Security + JWT + 微信小程序登录

    Spring Boot + Spring Security + JWT + 微信小程序登录整合教程 参考文章 文章目录 整合思想 整合步骤 1. AuthenticationToken 2. Auth ...

  2. Spring Boot+Spring Security+JWT 实现token验证

    Spring Boot+Spring Security+JWT 实现token验证 什么是JWT? JWT的工作流程 JWT的主要应用场景 JWT的结构 SpringBoot+Spring Secur ...

  3. springboot jwt token前后端分离_基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目...

    一.前言 最近整合Spring Boot+Spring Security+JWT+Vue 完成了一套前后端分离的基础项目,这里把它开源出来分享给有需要的小伙伴们 功能很简单,单点登录,前后端动态权限配 ...

  4. Spring Boot+Spring Cloud实现itoken项目

    itoken项目简介 开发环境 操作系统: Windows 10 Enterprise 开发工具: Intellij IDEA 数据库: MySql 5.7.22 Java SDK: Oracle J ...

  5. Spring Boot Spring MVC 异常处理的N种方法

    默认行为 根据Spring Boot官方文档的说法: For machine clients it will produce a JSON response with details of the e ...

  6. spring boot + spring batch 读数据库文件写入文本文件读文本文件写入数据库

    好久没有写博客,换了一家新公司,原来的公司用的是spring,现在这家公司用的是spring boot.然后,项目组布置了一个任务,关于两个数据库之间的表同步,我首先想到的就是spring batch ...

  7. spring boot 使用maven和fat jar/war运行应用程序的对比

    文章目录 简介 Spring Boot Maven Plugin 使用Maven命令来运行应用程序 作为fat jar/war包运行应用程序 详解War文件 详解jar文件 如何选择 使用maven和 ...

  8. Spring Boot Spring MVC 异常处理的N种方法 1

    github:https://github.com/chanjarste... 参考文档: Spring Boot 1.5.4.RELEASE Documentation Spring framewo ...

  9. Spring - Spring Boot Spring Cloud

    Spring -> Spring Boot > Spring Cloud 这几天刚刚上班,公司用的是Spring Cloud,接触不多.我得赶快学起来. 想学习就必须得知道什么是微服务,什 ...

最新文章

  1. C# 实现Oracle中的数据与Excel之间的转换
  2. 根据标签分布来选择损失函数
  3. Spring的Bean的初始化
  4. spark on yarn 使用自定义jdk
  5. Spring Boot : 自定义 Starter
  6. 详细解读!Isotropic Remeshing的详细介绍与实现
  7. 读书笔记 - Thoughts on interaction design (第二版) - 交互设计沉思录
  8. Linux常见查看日志命令
  9. epub文件一揽子解决方案
  10. php如何判断一个数是不是整数,php判断变量是否是整数的两种方法
  11. Oracle EBS 值集获取段限定词SQL
  12. android指南针报告,Android 指南针
  13. [已修复] CredSSP 加密 Oracle 修复
  14. 短视频剪辑教程自学难吗?子苗教育
  15. SECS-GEM通信标准的特点
  16. Docker镜像压缩与优化
  17. AMD公司2020财年第三季度收益电话会议
  18. MFC之学习绘制椭圆、库画刷使用
  19. linux edb 运行不了,运行 Linux 的 IBM Power Systems 上的 EDB Postgres Advanced Server 9.5 入门...
  20. ciTerm - 程序员终端摸鱼神器,建议全屏后体验效果更佳

热门文章

  1. Java 8 日期和时间解读
  2. java之StringBuider与StringBuffer
  3. 《四世同堂》金句摘抄(十八)
  4. mybatis报错:java.lang.IllegalArgumentException: Mapped Statements collection does not contain
  5. MyBatis中Mapper代理方式
  6. 2018蓝桥杯省赛---java---A---1(分数)
  7. 2018蓝桥杯省赛---java---B---6(递增三元组)
  8. 文件内容查看---Linux
  9. oracle中join另一个表后会查询不出一些数据_面试必备 | 8个Hive数据仓工具面试题锦集!...
  10. javah导出类的头文件抛出异常——java.lang.IllegalArgumentException: Not a valid class name(原因及解决方法)