1、Shiro简介

1.1 什么是Shiro

  • Apache Shiro 是一个Java的安全框架

  • Shiro可以非常容易的开发出足够好的应用,其不仅可以使用在JavaSE环境,也可以用在JavaEE环境

  • Shiro可以完成,认证,授权,加密,会话管理,Web集成 ,缓存等方面

  • 下载地址:http://shiro.apache.org/download.html

1.2 有哪些功能

  • Authentication:身份认证、登陆、验证用户是不是拥有相应的身份

  • Authorization:授权,即权限验证,验证某个已认证的用户是不是拥有某个权限,即判断用户能否进行什么操作,如:验证某个用户是否拥有某个角色,或者细粒度的验证某个用户是否对某个资源有某个权限!

  • Session Manager:会话管理,即用户登陆后就是第一次会话,在没有退出之前,它的所有信息都在会话中,会话是可以普通的JAVA环境,也可以是Web环境

  • Cryptography:加密,保护数据的安全性,如密码存储到数据库中,而不是明文存储

  • Web Support:Web支持,可以非常容易的集成到Web环境

  • Caching:缓存,比如用户登陆后,用户信息,拥有的角色,权限不必每次去查,这样可以提高效率

  • Concurrency:Shiro支持多线程应用的并发验证,即:在一个线程中开启另一个线程,能把权限自动的传递过去

  • Testing:提供测试支持

  • Run As:允许一个用户假装成另一个用户的身份访问

  • Remember Me:记住我,这个非常常见的功能,即一次登陆后,下次再来的话可以不用登陆

1.3 Shiro架构

从外部来看Shiro,即应用程序角度来观察如何使用Shiro完成工作;

  • subject:应用代码直接交互的对象是Subject,也就是说Shiro对外API的核心就是Subject,Subject代表了当前的用户,这个用户不一定是具体的人,与当前应用交互的任何东西都是Subject,如:网络爬虫,机器人等,与Subject的所有交互都会委托给SecurityManager;Subject其实是一个门面,SecurityManager才是实际的执行者

  • SecurityManager:安全管理器,即所有安全有关的操作都会与SercurityManager交互,并且它管理着所有的Subject,可以看出它是Shiro的核心,它对负责与Shiro的其他组件进行交互,它相当于SpringMVC的DispatcherServlet的角色

  • Realm:Shiro从Realm获取安全数据(如用户、角色、权限),就是说SecurityManagery要验证用户身份,那么它需要从Realm获取相应的用户进行笔记,来确定用户身份的合法性;也就是说从Realm得到的用户相应的角色,权限进行验证用户的操作是否能进行,可以把Realm看成DataSource;

1.4 Shiro内部架构

  • Subject:任何可以与应用交互的”用户“

  • Subject Manager:相当于Spring MVC中的DispatcherServlet;是Shiro的心脏,所有具体交互管理都通过Security Manager进行控制,它的管理者所有的Subject,且负责进行权限认证,授权,会话,缓存的管理

  • Authenticator:负责Subject认证,是一个扩展点,可以自定义实现,可以使用认证策略(Authentication Strategy)即什么情况下都算用户通过验证

  • Authorizer:授权器,即访问控制器,用来决定主题是否拥有权限进行相关操作,即控制着用户访问应用中的那些功能

  • Realm:可以有一个或者多个的realm,可以认为是安全实体数据源,即用于获取安全实体的,可以用JDBC实现,也可以是内存实现等等,由用户提供;所以一般在应用中都需要实现自己的realm

  • SessionManager:管理Session生命周期dd饿组件,而Shiro并不仅仅是可以用在Web环境,也可以用在普通的JavaSE环境中

  • CacheManager:缓存控制器,来管理用户,角色,权限等缓存,因为这些数据基本很少改变,放到缓存后可以提高访问性能

  • Cryptography:密码模块,Shiro提高了一些常见的加密组件用于密码加密,解密等

2、HelloWorld

1、导入shiro需要的包

 <!--shiro整合spring的包--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.5.3</version></dependency>

2、快速开始shiro

 ​import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.session.Session;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;​​public class Quickstart {​//使用log来进行日志输出private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);​​public static void main(String[] args) {​// The easiest way to create a Shiro SecurityManager with configured// realms, users, roles and permissions is to use the simple INI config.// We'll do that by using a factory that can ingest a .ini file and// return a SecurityManager instance:​// Use the shiro.ini file at the root of the classpath// (file: and url: prefixes load from files and urls respectively)://1、使用工厂模式来获得对象Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");SecurityManager securityManager = factory.getInstance();​SecurityUtils.setSecurityManager(securityManager);​​//2、三大对象之一:Subject// get the currently executing user// 可以通过方法获取当前用户Subject currentUser = SecurityUtils.getSubject();​// Do some stuff with a Session (no need for a web or EJB container!!!)//通过当前对象拿到SessionSession session = currentUser.getSession();​session.setAttribute("someKey", "aValue");String value = (String) session.getAttribute("someKey");if (value.equals("aValue")) {log.info("Subject=>的session中someKey对应的值! [" + value + "]");}​// let's login the current user so we can check against roles and permissions://判断当前用户是否已经验证if (!currentUser.isAuthenticated()) {//如果已经验证,就拿到一个token//token:令牌,去ini文件里面判断是否拥有这个用户UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");//设置记住我token.setRememberMe(true);try {//执行了登录操作currentUser.login(token);} catch (UnknownAccountException uae) {//未知账户异常log.info("There is no user with username of " + token.getPrincipal());} catch (IncorrectCredentialsException ice) {//密码错误异常log.info("Password for account " + token.getPrincipal() + " was incorrect!");} catch (LockedAccountException lae) {//用户锁定异常log.info("The account for username " + token.getPrincipal() + " is locked.  " +"Please contact your administrator to unlock it.");}// ... catch more exceptions here (maybe custom ones specific to your application?catch (AuthenticationException ae) {//认证异常,上面的异常都是其子类//unexpected condition?  error?}}​//say who they are://print their identifying principal (in this case, a username)://获取当前用户的一个认证码,用户的很多信息可以存储在这里log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");​//test a role://测试用户是否由角色if (currentUser.hasRole("schwartz")) {log.info("May the Schwartz be with you!");} else {log.info("Hello, mere mortal.");}​//test a typed permission (not instance-level)//测试用户的权限(粗粒度)//如果求权限不满足 就会报相应的错误if (currentUser.isPermitted("lightsaber:wield")) {log.info("You may use a lightsaber ring.  Use it wisely.");} else {log.info("Sorry, lightsaber rings are for schwartz masters only.");}​//a (very powerful) Instance Level permission://判断用户是否拥有更多权限(细粒度)if (currentUser.isPermitted("winnebago:drive:eagle5")) {log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +"Here are the keys - have fun!");} else {log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");}​//all done - log out!//注销currentUser.logout();​//结束System.exit(0);}}​

3、shiro的配置文件shiro.ini

 [users]# user 'root' with password 'secret' and the 'admin' roleroot = secret, admin# user 'guest' with the password 'guest' and the 'guest' roleguest = guest, guest# user 'presidentskroob' with password '12345' ("That's the same combination on# my luggage!!!" ;)), and role 'president'presidentskroob = 12345, president# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'darkhelmet = ludicrousspeed, darklord, schwartz# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'lonestarr = vespa, goodguy, schwartz​# -----------------------------------------------------------------------------# Roles with assigned permissions## Each line conforms to the format defined in the# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc# -----------------------------------------------------------------------------[roles]# 'admin' role has all permissions, indicated by the wildcard '*'admin = *# The 'schwartz' role can do anything (*) with any lightsaber:schwartz = lightsaber:*# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with# license plate 'eagle5' (instance specific id)goodguy = winnebago:drive:eagle5​

4、log4fj的配置文件

 log4j.rootLogger=INFO, stdout​log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n​# General Apache librarieslog4j.logger.org.apache=WARN​# Springlog4j.logger.org.springframework=WARN​# Default Shiro logginglog4j.logger.org.apache.shiro=INFO​# Disable verbose logginglog4j.logger.org.apache.shiro.util.ThreadContext=WARNlog4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

3、SpringBoot集成Shiro

1、导入整合的包

 <!--thymeleaf整合shiro--><dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.0.0</version></dependency>​​<!--lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.8</version><scope>provided</scope></dependency>​<!-- mybatis-spring-boot-starter --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.0</version></dependency>​​<!--mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--druid数据源--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.12</version></dependency>​<!--shiro整合spring的包--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.5.3</version></dependency>​<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>

2、shiro的配置类

 package com.wei.config;​import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;​import java.util.LinkedHashMap;import java.util.Map;​@Configurationpublic class ShiroConfig {//三大要素//ShiroFilterFactoryBean:3@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("webSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();//设置安全管理器bean.setSecurityManager(defaultWebSecurityManager);//添加shiro的内置过滤器/*anon:无需认证即可访问authc:必须认证才可访问user:必须拥有记住我功能才能用perms:拥有对某个资源的权限才能访问role:拥有某个角色权限才能访问*///登录拦截Map<String, String> filterMap = new LinkedHashMap<>();​//第一个参数是请求,第二个是设置的权限filterMap.put("/add","authc");filterMap.put("/update","authc");​//授权//user用户拥有add权限才能访问 /add请求//正常情况下没有授权,会跳到授权页面filterMap.put("/add","perms[user:add]");filterMap.put("/update","perms[user:update]");bean.setFilterChainDefinitionMap(filterMap);​//设置登录的请求bean.setLoginUrl("toLogin");//设置未授权页面bean.setUnauthorizedUrl("/noauth");​return bean;}​​//DefaultWebSecurityManager:2@Bean(name = "webSecurityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager();//关联我们的userRealmwebSecurityManager.setRealm(userRealm);return webSecurityManager;}​​//创建Realm对象,需要自定义 :1//将自己写的realm对象 交给spring容器托管@Beanpublic UserRealm userRealm(){return new UserRealm();}​//整合ShiroDialect:Shiro方言  用来整合shiro-thymeleaf@Beanpublic ShiroDialect getShiroDialect(){return new ShiroDialect();}}​

3、自定义领域(Realm)

 package com.wei.config;​import com.wei.entity.User;import com.wei.service.UserService;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.session.Session;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.subject.Subject;import org.springframework.beans.factory.annotation.Autowired;​//自定义的Realm UserRealm//要实现自定义的 只需要继承AuthorizingRealm 即可public class UserRealm extends AuthorizingRealm {​@Autowiredprivate UserService userService;//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行了授权doGetAuthorizationInfo方法");​//进入一些被拦截的页面 就会执行授权方法//给用户赋予权限的对象SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//给用户添加权限//info.addStringPermission("user:add");​//拿到当前登录的对象Subject subject = SecurityUtils.getSubject();User currentUser = (User) subject.getPrincipal();//这里取得是59行存得user得值//没有权限直接返回空  显示自己的没有权限界面if (currentUser.getPerms()==null){return null;}​//设置当前用户的权限info.addStringPermission(currentUser.getPerms());​//要返回赋予的权限对象return info;}​//认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("执行了认证doGetAuthenticationInfo方法");//伪造用户名和密码    真的要再数据库中去取//        String name = "root";//        String password = "123";​​//将认证的token转化成存储用户信息的token 方便进行信息的判断UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;//连接真实数据库User user = userService.queryByName(token.getUsername());​if (user==null){return null;//没有这个人报错}​Subject currentUser = SecurityUtils.getSubject();Session session = currentUser.getSession();session.setAttribute("loginUser",user);​//shiro也有一些加密方式:MD5  MD5盐值加密 SHA等 但是如果没有加密  密码正确一样可以访问//这个和SpringSecurity有一点区别//密码认证shiro来做,交给程序员操作可能会导致密码泄露return new SimpleAuthenticationInfo(user,user.getPwd(),"");}}​

4、控制器

 package com.wei.controller;​import com.sun.org.apache.regexp.internal.RE;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.subject.Subject;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;​@Controllerpublic class MyController {@RequestMapping({"/","/index"})public String toIndex(Model model){model.addAttribute("msg","hello,shiro");return "index";}​@RequestMapping("/add")public String toAdd(){return "user/add";}​@RequestMapping("/update")public String toUpdate(){return "user/update";}​​@RequestMapping("/toLogin")public String toLogin(){return "login";}​@RequestMapping("/login")public String login(String username,String password,Model model){//获取当前的用户Subject subject = SecurityUtils.getSubject();​//封装用户的登录数据  把账号密码放在一个令牌中加密UsernamePasswordToken token = new UsernamePasswordToken(username, password);//使用令牌登录,如果没有异常就说明oktry {subject.login(token);return "index";} catch (UnknownAccountException e) {model.addAttribute("msg","用户名错误");return "login";}catch (IncorrectCredentialsException e){model.addAttribute("msg","密码错误");return "login";}}​@RequestMapping("/noauth")@ResponseBodypublic String noauth(){return "没有授权,无法登录";}​@RequestMapping("/logout")public String logout(Subject subject){subject.logout();return "index";}}​

5、实体类

 package com.wei.entity;​import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;​@Data@NoArgsConstructor@AllArgsConstructorpublic class User {private int id;private String name;private String pwd;private String perms;}​

6、mapper接口

 package com.wei.mapper;​import com.wei.entity.User;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Param;import org.springframework.stereotype.Repository;​@Repository@Mapperpublic interface UserMapper {​public User queryByName(@Param("name") String name);}​

实现类

 <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">​<mapper namespace="com.wei.mapper.UserMapper">​<select id="queryByName" parameterType="string" resultType="com.wei.entity.User">select * from user where name = #{name};</select>​</mapper>

7、Service

 package com.wei.service;​import com.wei.entity.User;import org.apache.ibatis.annotations.Param;​public interface UserService {​public User queryByName(String name);}​

实现类

 package com.wei.service;​import com.wei.entity.User;import com.wei.mapper.UserMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;​@Servicepublic class UserServiceImpl implements UserService {​@Autowiredprivate UserMapper userMapper;​@Overridepublic User queryByName(String name) {User user = userMapper.queryByName(name);return user;}}​

8、前端模板

login.html

 <!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Title</title></head><body><h1>登录页面</h1><form th:action="@{/login}" method="post"><p>用户名:</p><input type="text" name="username"><p>密码:</p><input type="password" name="password"><br><input type="submit" value="提交"></form><p th:text="${msg}" style="color: red"></p></body></html>

index.html

 <!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org"xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"><head><meta charset="UTF-8"><title>Title</title></head><body><h1>首页</h1><p th:text="${msg}"></p><div shiro:hasPermission="user:add"><a th:href="@{/add}"> 去添加页面 </a></div><br><div shiro:hasPermission="user:update"><a th:href="@{/update}"> 去修改页面 </a></div><br></div><div th:if="${session.loginUser == null}"><a th:href="@{/toLogin}">登录</a></div><div th:if="${session.loginUser != null}"><a>已登录</a><a th:href="@{/logout}">注销</a></div>​</body></html>

add.html

 <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><h1>添加页面</h1></body></html>

update.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>修改页面
</h1>
</body>
</html>

9、Mybaties整合Springboot

#设置mybatis
mybatis.type-aliases-package=com.wei.entity
mybatis.mapper-locations=classpath:mapper/*.xml

10、数据源配置

spring:datasource:username: rootpassword: root#serverTimezone=UTC解决时区的报错url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8driver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource#Spring Boot 默认是不注入这些属性值的,需要自己绑定#druid 数据源专有配置initialSize: 5minIdle: 5maxActive: 20maxWait: 60000timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000validationQuery: SELECT 1 FROM DUALtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入#如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4jfilters: stat,wall,log4jmaxPoolPreparedStatementPerConnectionSize: 20useGlobalDataSourceStat: trueconnectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

Shiro是如何进行权限管理相关推荐

  1. 一篇搞定 SpringBoot+Mybatis+Shiro 实现多角色权限管理

    初衷:我在网上想找整合springboot+mybatis+shiro并且多角色认证的博客,发现找了好久也没有找到想到的,现在自己会了,就打算写个博客分享出去,希望能帮到你. 原创不易,请点赞支持! ...

  2. shiro、基于url权限管理、超详细

    如果需要本篇博客内容的代码!请到我的博客下载中心去下载   https://download.csdn.net/download/qq_36125138/10719559 项目运行图: 权限管理原理知 ...

  3. shiro最简洁的权限管理(菜单)控制

    主要是思想,步骤的话,还是需要分不同的场景,有什么问题及时留言评论即可. 生活中常见的管理系统中,都会有权限的控制,让不同类型的登录用户看到不同的菜单.其实,类似于uasyui这样的前端框架,是有提供 ...

  4. OA/CRM/ERP 权限管理系统设计 - bg.work办公开源实现

    一 .简介 权限管理对有组织结构的系统重要性无需多言,没有权限限制的管理.办公系统将没有可用性可谈.说实话权限管理系统实现起来没有任何门槛,直接几个if else判断就能解决现实需求 ,但是,如果需要 ...

  5. 简单的jsp权限管理

    简单权限管理的控制 权限管理 代码 权限管理 在java项目中经常会遇到用户的权限管理,通常有一种方法通过shiro框架来进行权限管理,现在我要说的是一种简单的权限管理方法,可以在jsp页面中添加ja ...

  6. 权限管理(shiro框架)

    为什么80%的码农都做不了架构师?>>>    1. 权限管理的流程 页面中的菜单和按钮就是我们访问某个功能的入口. 无论是访问菜单或者按钮,要想完成某个业务操作,实际上是需要发送一 ...

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

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

  8. shiro权限管理_重量级课程发布~企业权限管理平台(SpringBoot2.0+Shiro+Vue)

    历经半个多月的时间,Debug亲自撸的 "企业员工角色权限管理平台"终于完成了.正如字面意思,本课程讲解的是一个真正意义上的.企业级的项目实战,主要介绍了企业级应用系统中后端应用权 ...

  9. Spring Boot Shiro 权限管理

    Spring Boot Shiro 权限管理 标签: springshiro 2016-01-14 23:44 94587人阅读 评论(60) 收藏 举报 本来是打算接着写关于数据库方面,集成MyBa ...

最新文章

  1. show status用法
  2. jQuery选择器和选取方法
  3. 2018-2019-1 20165219 实验三 实时系统
  4. IDEA 启动报错could not find main class com/intellij/idea/main解决办法
  5. Kubernetes NetworkPolicy 工作原理浅析
  6. c语言判断字符串合法标识符,HDU 2024 C语言合法标识符(以及一些关于输入和ctype.h的内容)...
  7. Unity Transform bug
  8. string取某个符号后面的的_String.replace 用的不对性能可能差 10 倍,你用对了吗?...
  9. 8uftp更改上传的网页内容
  10. wap网页如何跳转到微信一键关注公众号
  11. 中控考勤仪IFace302多线程操作时无法订阅事件
  12. 6.5 发散思维能力
  13. PHP入门需要多久?
  14. 十种常见的图像标注方法 | 数据标注
  15. swiper 上滑触发_在绝地求生加入滑铲等战术动作会怎么样?你们想过吗?
  16. 数独解、多解(数据结构、栈、回溯法)
  17. 计算机应用基础第四版答案周南岳,计算机应用基础第周南岳win+office期末复习及答案.docx...
  18. 你会如何给全局对象添加toString()方法
  19. 用JSTL实现JSP应用程序快速开发
  20. Abaqus常用小技巧

热门文章

  1. eclipse 反编译插件安装
  2. 电磁感应,让你制作独一无二的作品
  3. matlab 输入坐标,matlab中坐标希腊符号的输入方法
  4. apt-get 离线包安装
  5. 武汉科技大学计算机生命与科学周海,湖北双胞胎周海周洋:为了母亲,一个放弃清华,一人放弃中科院...
  6. FE!FE!面板固定效应模型:你用对了吗
  7. Microsoft Visual Studio 2010 Service Pack 1 离线下载版
  8. 负载均衡技术全攻略(大全)
  9. 联想小新310电脑Fn功能键切换
  10. 测试用例(测试用例的编写、评审和管理)