shiro是一个轻量级的安全框架,包含用户认证和用户授权

分析shiro的核心API:

Subject:用户主体(把操作交给SecurityManager)

SecurityManager:安全管理器(管理Reaml)

Reaml:shiro连接数据的桥梁

Shiro的配置类:
 创建ShiroFilterFactoryBean;

 创建DefaultWebSecurityManager;

  创建Reaml(继承AuthorizingReaml);

Shiro内置过滤器,可以实现权限相关的拦截器:

 常用的过滤器:

anno:无需认证(登陆)可以访问

authc:必须认证才能访问

user:如果使用rememberMe的功能可以直接访问

perms:该资源必须得到资源权限可以访问

role:该资源必须得到角色权限才能访问

在整合Shiro的时候,我们先要确定一下我们的步骤:

1.加入Shiro的依赖包,实现自己的Realm类(通过继承AuthorizingRealm类);

2.实现Shiro的配置类

3.实现前端的登录界面以及Controller类

第一步:

在pom.xml中加入依赖包

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>

实现Realm类

package ariky.shiro.realm;

import java.util.HashSet;
import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.web.subject.WebSubject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* @ClassName:
* @Description: Realm的配置
* @author fuweilian
* @date 2018-5-12 上午11:36:41
*/
public class MyShiroRealm extends AuthorizingRealm {
//slf4j记录日志,可以不使用
private Logger logger = LoggerFactory.getLogger(MyShiroRealm.class); /**
* 设置授权信息
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
logger.info("开始授权(doGetAuthorizationInfo)");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils
.getSubject()).getServletRequest();//这个可以用来获取在登录的时候提交的其他额外的参数信息
String username = (String) principals.getPrimaryPrincipal();//这里是写的demo,后面在实际项目中药通过这个登录的账号去获取用户的角色和权限,这里直接是写死的
//受理权限
//角色
Set<String> roles = new HashSet<String>();
roles.add("role1");
authorizationInfo.setRoles(roles);
//权限
Set<String> permissions = new HashSet<String>();
permissions.add("user:list");
//permissions.add("user:add");
authorizationInfo.setStringPermissions(permissions);
return authorizationInfo;
} /**
* 设置认证信息
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authenticationToken) throws AuthenticationException {
logger.info("开始认证(doGetAuthenticationInfo)");
//UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils
.getSubject()).getServletRequest();
UsernamePasswordToken token = new UsernamePasswordToken (request.getParameter("userName"),request.getParameter("password"));
//获取用户输入的账号
String userName = (String)token.getPrincipal();
//通过userName去数据库中匹配用户信息,通过查询用户的情况做下面的处理
//这里暂时就直接写死,根据登录用户账号的情况做处理
logger.info("账号:"+userName);
if("passwordError".equals(userName)){//密码错误
throw new IncorrectCredentialsException();
}else if("lockAccount".equals(userName)){// 用户锁定
throw new LockedAccountException();
}else{
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
userName, //用户名
"123456", //密码,写死
ByteSource.Util.bytes(userName+"salt"),//salt=username+salt
getName() //realm name
);
return authenticationInfo;
}
} }

第二步 实现Shiro的配置类:

package ariky.shiro.configuration;

import java.util.LinkedHashMap;
import java.util.Map; import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import ariky.shiro.realm.MyShiroRealm; /**
* @ClassName: ShiroConfiguration
* @Description: shiro的配置类
* @author fuweilian
* @date 2018-5-12 上午11:05:09
*/
@Configuration
public class ShiroConfiguration {
private static Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
logger.info("进入shiroFilter......");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//设置不需要拦截的路径
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//按顺序依次判断
filterChainDefinitionMap.put("/static/**", "anon");
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
/************************************初始化所有的权限信息开始******************************************/
//这里,如果以后再项目中使用的话,直接从数据库中查询
filterChainDefinitionMap.put("/user/list", "authc,perms[user:list]");
//filterChainDefinitionMap.put("/user/add", "authc,perms[user:add]");
/***************************************初始化所有的权限信息开始结束*********************************************/
filterChainDefinitionMap.put("/**", "authc");
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index");
//未授权界面
shiroFilterFactoryBean.setUnauthorizedUrl("/error/403");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
} @Bean
public MyShiroRealm myShiroRealm(){
MyShiroRealm myShiroRealm = new MyShiroRealm();
//后面这里可以设置缓存的机制
return myShiroRealm;
} @Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
} @Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
} }

第三步:实现Controoler类,这里写俩个类,一个是登录信息的LoginController处理类,一个是测试权限用的UserController

1.LoginController.java

package ariky.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; /**
* @ClassName: LoginController
* @Description: 登录控制的controller
* @author fuweilian
* @date 2018-5-12 下午01:15:46
*/
@RequestMapping
@Controller
public class LoginController {
private Logger logger = LoggerFactory.getLogger(LoginController.class); @RequestMapping(value="/login",method=RequestMethod.GET)
public String getLogin(){
logger.info("进入login页面");
return "login";
} @RequestMapping(value="/login",method=RequestMethod.POST)
public String doLogin(HttpServletRequest req,Map<String, Object> model){
logger.info("进入登录处理");
String exceptionClassName = (String) req.getAttribute("shiroLoginFailure");
logger.info("exceptionClassName:"+exceptionClassName);
String error = null;
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
}else if(LockedAccountException.class.getName().equals(exceptionClassName)){
error = "用户已锁定或已删除";
}else if (exceptionClassName != null) {
error = "其他错误:" + exceptionClassName;
}
if(SecurityUtils.getSubject().isAuthenticated()){//没有错误,但是已经登录了,就直接跳转到welcom页面
model.put("name", req.getParameter("userName"));
return "index";
}else{//有错误的
model.put("error", error);
return "login";
}
}
@RequestMapping("/index")
public String index(){
return "index";
}
}

2.UserController.java

package ariky.controller;

import java.util.ArrayList;
import java.util.List; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; /**
* @ClassName: UserController
* @Description: 用户处理Controller
* @author fuweilian
* @date 2018-5-12 下午03:11:06
*/
@Controller
@RequestMapping("/user")
public class UserController {
Logger logger = LoggerFactory.getLogger(UserController.class);
@RequiresPermissions("user:list")//这个是配置是否有该权限的,如果是按上面的写法,这个是有权限的
@RequestMapping(value="/list",method=RequestMethod.GET)
public String getList(){
logger.info("进入用户列表");
return "user/list";
}
@RequiresPermissions(value={"user:add"})//这个是没有权限的
@RequestMapping(value="/add",method=RequestMethod.GET)
public String getAdd(){
logger.info("进入新增用户界面");
return "user/add";
} }

前端界面:有5个界面 (login.jsp,index.jsp,list.jsp,add.jsp,403.jsp)

目录结构为:

1.login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Login</title>
</head> <body>
<h1>登录页面----${error}</h1>
<form:form action="${pageContext.request.contextPath }/login"
method="post">
用户名:<input type="text" name="userName">
<br />
密码:<input type="passwordParam" name="password"/>
<input type="submit" value="提交"/>
</form:form>
</body>
</html>

2.index.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>第一个例子</title>
<script src="${pageContext.request.contextPath }/webjars/jquery/2.1.4/jquery.js"></script>
<script src="${pageContext.request.contextPath }/webjarslocator/jquery/jquery.js"></script>
</head> <body>
<h1>${name}:你好,欢迎访问该网页</h1>
<shiro:hasPermission name="user:list"><!-- 这个a标签是可以看见的 -->
<a href="${pageContext.request.contextPath }/user/list" target="_blank">跳转到用户列表(有权限)</a>
</shiro:hasPermission>
<br/>
<shiro:hasPermission name="user:add"><!-- 这个a标签是看不见的 -->
<a href="${pageContext.request.contextPath }/user/add" target="_blank">跳转到新增用户列表(无权限)</a>
</shiro:hasPermission>
</body>
</html>

3.list.jsp和add.jsp以及403.jsp都差不多一样,这里就写一个,这里只是demo所用,在实际项目中,要以实际项目为准

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>userList</title>
</head> <body>
<h1>用户列表信息</h1>
</body>
</html>

上面就是全部代码了,如果启动成功,进入login登录界面就可以测试一下shiro的权限认证了。上面的代码都是写死的,如果想要实现动态的权限管理和用户的权限管理的话,还要做一些其他处理,用户的动态权限这个只要在自己的ShiroRealm类里面授权的时候做一下查询数据库,动态的授权和角色就行。关于动态的权限管理的话,下面的方式可以实现,在修改完权限数据后,更新一下shiro里面的配置就行,具体看下面的代码,这里是demo,不是实际项目,在实际项目中最好不要把逻辑写在Controller里面

package ariky.shiro.controller;

import java.util.LinkedHashMap;
import java.util.Map; import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; /**
* @ClassName: PermssionController
* @Description: 权限操作的controller
* @author fuweilian
* @date 2018-5-12 下午04:59:15
*/
@Controller
@RequestMapping("permssion")
public class PermssionController { @Autowired
ShiroFilterFactoryBean shiroFilterFactoryBean; /**
* @Title: updatePermssion
* @author: fuweilian
* @Description: 这里暂时直接写在controller里面,,不按规则写了,,到时候在项目中使用的时候,才写
* @return 参数说明
* @return Object 返回类型
* @throws
*/
@RequestMapping("/updatePermssion")
@ResponseBody
public Object updatePermssion(){
synchronized (shiroFilterFactoryBean){
AbstractShiroFilter shiroFilter = null;
try {
shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean
.getObject();
PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
.getFilterChainResolver();
DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver
.getFilterChainManager();
// 清空老的权限控制
manager.getFilterChains().clear();
shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
//后面这个可以直接从数据库里面获取
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//按顺序依次判断
filterChainDefinitionMap.put("/static/**", "anon");
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
/************************************初始化所有的权限信息开始******************************************/
//这里,如果以后再项目中使用的话,直接从数据库中查询
filterChainDefinitionMap.put("/user/list", "authc,perms[user:list]");
filterChainDefinitionMap.put("/user/add", "authc,perms[user:add]");
/***************************************初始化所有的权限信息开始结束*********************************************/
filterChainDefinitionMap.put("/**", "authc");
//
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index");
//未授权界面
shiroFilterFactoryBean.setUnauthorizedUrl("/error/403");
shiroFilterFactoryBean
.setFilterChainDefinitionMap(filterChainDefinitionMap);
// 重新构建生成
Map<String, String> chains = shiroFilterFactoryBean
.getFilterChainDefinitionMap();
for (Map.Entry<String, String> entry : chains.entrySet()) {
String url = entry.getKey();
String chainDefinition = entry.getValue().trim()
.replace(" ", "");
manager.createChain(url, chainDefinition);
}
return "更新权限成功";
} catch (Exception e) {
throw new RuntimeException(
"更新shiro权限出现错误!");
}
}
} }

下面是mysql库的表结构

/*
Navicat MySQL Data Transfer
Source Server : arikyDB
Source Server Version : 50721
Source Host : 47.106.95.168:3306
Source Database : ariky
Target Server Type : MYSQL
Target Server Version : 50721
File Encoding : 65001
Date: 2018-05-14 16:05:51
*/ SET FOREIGN_KEY_CHECKS=0; -- ----------------------------
-- Table structure for common_permssion
-- ----------------------------
DROP TABLE IF EXISTS `common_permssion`;
CREATE TABLE `common_permssion` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`NAME` varchar(255) DEFAULT NULL COMMENT '权限名称',
`TYPE` varchar(255) DEFAULT NULL COMMENT '类型按钮(button)或者菜单(menu) ',
`PARENT_ID` int(11) DEFAULT NULL COMMENT '上级ID',
`PARENT_IDS` varchar(255) DEFAULT NULL COMMENT '上级PIDs',
`URL` varchar(255) DEFAULT NULL COMMENT '访问路径',
`ICONCLS` varchar(255) DEFAULT NULL COMMENT '图标(可以不要)',
`PERMISSION` varchar(255) DEFAULT NULL COMMENT '权限(如user:list)',
`ORDER_NUM` int(11) DEFAULT NULL COMMENT '排序',
`REMARK` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8 COMMENT='该表用来存储资源权限信息'; -- ----------------------------
-- Table structure for common_role
-- ----------------------------
DROP TABLE IF EXISTS `common_role`;
CREATE TABLE `common_role` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`LABEL_ID` varchar(255) DEFAULT NULL COMMENT '标签Id',
`NAME` varchar(255) DEFAULT NULL COMMENT '角色名称',
`ROLE` varchar(255) DEFAULT NULL,
`DESCRIPTION` varchar(255) DEFAULT NULL,
`IS_SHOW` int(11) DEFAULT '1' COMMENT '判断该角色是否在使用(1:使用,2:禁用)',
`IS_HANDLER` int(2) DEFAULT NULL COMMENT '判断是什么角色(1:后台角色,2:商家管理员角色,3:商家添加用户角色,4:游客角色)',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT='角色表'; -- ----------------------------
-- Table structure for common_role_permssion
-- ----------------------------
DROP TABLE IF EXISTS `common_role_permssion`;
CREATE TABLE `common_role_permssion` (
`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
`ROLE_ID` int(11) DEFAULT NULL COMMENT '角色Id',
`RESOURCE_ID` int(11) DEFAULT NULL COMMENT '资源(权限)Id',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=493 DEFAULT CHARSET=utf8 COMMENT='角色资源权限表中间表';

SpringBoot中关于Shiro权限管理的整合使用的更多相关文章

  1. xml配置文件中对于Shiro 权限管理filterChainDefinitions过滤器配置

    博客转载:http://blog.csdn.net/userrefister/article/details/47807075 /** * Shiro-1.2.2内置的FilterChain * @s ...

  2. 在前后端分离的SpringBoot项目中集成Shiro权限框架

    参考[1].在前后端分离的SpringBoot项目中集成Shiro权限框架 参考[2]. Springboot + Vue + shiro 实现前后端分离.权限控制   以及跨域的问题也有涉及

  3. Spring Boot Shiro 权限管理 【转】

    http://blog.csdn.net/catoop/article/details/50520958 主要用于备忘 本来是打算接着写关于数据库方面,集成MyBatis的,刚好赶上朋友问到Shiro ...

  4. Springboot2.0 集成shiro权限管理

    在springboot中结合shiro教程搭建权限管理,其中几个小细节的地方对新手不友好,伸手党更是无法直接运行代码,搭建过程容易遇坑,记录一下.关键的地方也给注释了. 版本:springboot版本 ...

  5. (39.3) Spring Boot Shiro权限管理【从零开始学Spring Boot】

    在学习此小节之前您可能还需要学习: (39.1) Spring Boot Shiro权限管理[从零开始学Spring Boot] http://412887952-qq-com.iteye.com/b ...

  6. (39.2). Spring Boot Shiro权限管理【从零开始学Spring Boot】

    (本节提供源代码,在最下面可以下载) (4). 集成Shiro 进行用户授权 在看此小节前,您可能需要先看: http://412887952-qq-com.iteye.com/blog/229973 ...

  7. (39.1) Spring Boot Shiro权限管理【从零开始学Spring Boot】

    (本节提供源代码,在最下面可以下载)距上一个章节过了二个星期了,最近时间也是比较紧,一直没有时间可以写博客,今天难得有点时间,就说说Spring Boot如何集成Shiro吧.这个章节会比较复杂,牵涉 ...

  8. Spring Boot Shiro 权限管理

    Spring Boot Shiro 权限管理 标签: springshiro 2016-01-14 23:44 94587人阅读 评论(60) 收藏 举报 .embody{ padding:10px ...

  9. shiro权限管理的框架-入门

    shiro权限管理的框架 1.权限管理的概念 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能 ...

随机推荐

  1. ElasticStack学习(十):深入ElasticSearch搜索之QueryFiltering、多/单字符串的多字段查询

    一.复合查询 1.在ElasticSearch中,有Query和Filter两种不同的Context.Query Context进行了相关性算分,Filter Context不需要进行算分,同时可以利 ...

  2. 从微信小程序开发者工具源码看实现原理(二)- - 小程序技术实现

    wxml与wxss的转换 1.wxml使用wcc转换 2.wxss使用wcsc转换 开发者工具主入口 视图层页面的实现 视图层页面实现技术细节 视图层快速打开原理 视图层新打开页面流程 业务逻辑层页面 ...

  3. 个人永久性免费-Excel催化剂功能第37波-把Sqlserver的强大分析函数拿到Excel中用

    本人一直钟情于使用Sqlserver数据库的一大原因是其提供了非常好用.高效的数据分析函数(窗口函数),可以在做数据清洗和数据分析场合等多个场景使用.只需简单的一个函数即可做出常规SQL语句很难以实现 ...

  4. Excel催化剂开源第22波-VSTO的帮助文档在哪里?

    Excel催化剂开源第22波-VSTO的帮助文档在哪里? Excel催化剂   2019.01.12 14:10 字数 2930 阅读 55评论 0喜欢 0 编辑文章 对于专业程序猿来说,查找文档不是 ...

  5. MyBatis框架之基本知识介绍

    前身背景: 前身是iBatis,为Apache的一个开源项目.2010年迁移到了Google Code,改名为MyBatis.2013年迁移到Github. MyBatis框架以及ORM MyBati ...

  6. openlayer 5 获取中心点

    之前在控制台把map对象打印出来后,有一个很像中心点坐标map.focus_.我可以确定的告诉大家,这个不是中心点坐标,检查出来的结果是地图中心最右的点位. 在创建地图时,会将中心点左边写在view中 ...

  7. C#3.0新增功能06 对象和集合初始值设定项

    连载目录    [已更新最新开发文章,点击查看详细] 使用 C# 可以在单条语句中实例化对象或集合并执行成员分配. 对象初始值设定项 使用对象初始值设定项,你可以在创建对象时向对象的任何可访问字段或属 ...

  8. C/C++指针函数和函数指针

    一.指针函数 当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中. 格式: 类型说明符 * 函数名(参数) 当然了,由于返回的是一个地址,所以类型说明 ...

  9. Windows系统配置java环境

    1:下载jdk  网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 2:下载 ...

  10. 物联网时代 跟着Thingsboard学IOT架构-CoAP设备协议

    thingsboard官网: https://thingsboard.io/ thingsboard GitHub: https://github.com/thingsboard/thingsboar ...