SpringBoot 整合shiro框架

2023-10-31

网上有很多整合shiro的博客分享,但是貌似没找到一个完整,并且能够实现的。不是包的问题,就是代码的问题,也可能是自己的问题,或者版本的问题。所以,整理了一版自己已应用的.

maven依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.2.RELEASE</version>
    <relativePath/>
</parent>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.22</version>
        </dependency>
        <!--整合模板打开注释-->
        <!--<dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <!--<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.4.0</version>
        </dependency>-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.11</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
</dependencies>

MyShiroRealm.java(权限配置)

import com.simple.users.dto.entity.UserInfo;
import com.simple.users.service.UserInfoService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;

public class MyShiroRealm extends AuthorizingRealm {

	@Resource
	private UserInfoService userInfoService;

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()");
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		UserInfo userInfo = (UserInfo) principals.getPrimaryPrincipal();
		/*
		 * for (SysRole role : userInfo.getRoleList()) {
		 * authorizationInfo.addRole(role.getRole()); for (SysPermission p :
		 * role.getPermissions()) {
		 * authorizationInfo.addStringPermission(p.getPermission()); } }
		 */
		// 获取用户角色
		Set<String> roleSet = new HashSet<String>();
		roleSet.add("100002");
		info.setRoles(roleSet);

		// 获取用户权限
		Set<String> permissionSet = new HashSet<String>();
		permissionSet.add("权限添加");
		permissionSet.add("权限删除");
		info.setStringPermissions(permissionSet);

		return info;
	}

	/**
	 * 主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。
	 * 
	 * @param authcToken
	 * @return
	 * @throws AuthenticationException
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
			throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		String username = token.getUsername();
		UserInfo userInfo = userInfoService.findByUsername(username);
		if (userInfo == null) {
			return null;
		}
		String password = new String((char[]) token.getCredentials());
		String pwdMd5 = (new Md5Hash(password, username)).toHex();
		System.out.println("----->>pwdMd5====" + pwdMd5);

		UserInfo user = new UserInfo();
		user.setUsername(username);
		user.setPassword(pwdMd5);

		return new SimpleAuthenticationInfo(user, pwdMd5, ByteSource.Util.bytes(username), getName());
	}

}

ShiroConfig.java(shiro配置)

import com.simple.utils.Base64Util;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

@Configuration
public class ShiroConfig {
	/**
	 * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
	 * 开启thymeleaf模板访问,注释则使用配置的jsp或者HTML访问模式
	 * @return
	 */
//	@Bean
//	public ShiroDialect shiroDialect() {
//		return new ShiroDialect();
//	}

	@Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		System.out.println("--------ShiroConfiguration.shirFilter()");
		// 添加安全管理器
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		// 如果不设置默认会自动寻找Web工程根目录下的"/index.jsp"页面
		shiroFilterFactoryBean.setLoginUrl("/");
		// 登录成功后要跳转的链接
		// shiroFilterFactoryBean.setSuccessUrl("/?path=user/main");
		// 添加shiro内置过滤器
		/**
		 * anon:表示可以匿名使用。 authc:表示需要认证(登录)才能使用,没有参数
		 * 
		 * roles:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,
		 * 例如admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。
		 *
		 * perms:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,
		 * 例如/admins/user/**=perms["user:add:*,user:modify:*"],
		 * 当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
		 *
		 * rest:根据请求的方法,相当于/admins/user/**=perms[user:method]
		 * ,其中method为post,get,delete等。
		 *
		 * port:当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,
		 * 其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,
		 * queryString是你访问的url里的?后面的参数。 authcBasic:没有参数表示httpBasic认证
		 *
		 * ssl:表示安全的url请求,协议为https user:当登入操作时不做检查
		 */
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		// 静态资源的处理
		filterChainDefinitionMap.put("/js/**", "anon");
		filterChainDefinitionMap.put("/css/**", "anon");
		filterChainDefinitionMap.put("/img/**", "anon");
		filterChainDefinitionMap.put("/fonts/**", "anon");
		filterChainDefinitionMap.put("/plugins/**", "anon");
//		// 请求路径的处理
		filterChainDefinitionMap.put("/H-PLE/**", "authc");

		// 退出系统的过滤器
		filterChainDefinitionMap.put("/userInfo/logout", "logout");
		filterChainDefinitionMap.put("/userInfo/login", "anon");

		// 默认所有资源必须认证才能访问
		filterChainDefinitionMap.put("/**", "authc");

		// 未授权界面;
		shiroFilterFactoryBean.setUnauthorizedUrl("/403");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}

	/**
	 * 凭证匹配器 (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 )
	 * 
	 * @return
	 */
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
		hashedCredentialsMatcher.setHashIterations(1);// 散列的次数(默认一次),比如散列两次,相当于 md5(md5(""));
		return hashedCredentialsMatcher;
	}

	@Bean
	public MyShiroRealm myShiroRealm() {
		MyShiroRealm myShiroRealm = new MyShiroRealm();
		myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return myShiroRealm;
	}

	@Bean
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(myShiroRealm());
		// 注入记住我管理器;
		securityManager.setRememberMeManager(rememberMeManager());
		return securityManager;
	}

	/**
	 * cookie对象;
	 * 
	 * @return
	 */
	public SimpleCookie rememberMeCookie() {
		// 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
		SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
		// <!-- 记住我cookie生效时间30天 ,单位秒;-->
		simpleCookie.setMaxAge(2592000);
		return simpleCookie;
	}

	/**
	 * cookie管理对象;记住我功能
	 * 
	 * @return
	 */
	public CookieRememberMeManager rememberMeManager() {
		CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
		cookieRememberMeManager.setCookie(rememberMeCookie());
		// rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
		try {
			cookieRememberMeManager.setCipherKey(Base64Util.decode("3AvVhmFLUs0KTA3Kprsdag=="));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return cookieRememberMeManager;
	}

	/**
	 * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
	 * 
	 * @param securityManager
	 * @return
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}

	@Bean(name = "simpleMappingExceptionResolver")
	public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
		SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
		Properties mappings = new Properties();
		mappings.setProperty("DatabaseException", "databaseError");// 数据库异常处理
		mappings.setProperty("UnauthorizedException", "403");
		r.setExceptionMappings(mappings); // None by default
		r.setDefaultErrorView("error"); // No default
		r.setExceptionAttribute("ex"); // Default is "exception"
		// r.setWarnLogCategory("example.MvcLogger"); // No default
		return r;
	}
}

UserController.java(登录应用)

@ResponseBody
@RequestMapping(value = "/login", method = RequestMethod.POST, produces = { "application/json; charset=UTF-8" })
public Object login(@RequestBody JSONObject jsonP) {
	JSONObject result = new JSONObject();
	JSONObject resultHd = new JSONObject();
	JSONObject resultBd = new JSONObject();
	String userName = Null.nullToSpace(jsonP.getString("userName"));
	String passWord = Null.nullToSpace(jsonP.getString("passWord"));
	Boolean rememberMe = jsonP.getBoolean("agree");
	System.out.println("userName--" + userName + "; passWord--" + passWord + "; rememberMe--" + rememberMe);
	UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord, rememberMe);
	try {
		SecurityUtils.getSubject().login(token);
		resultHd.put("error", "成功");
		resultHd.put("errorCode", "0");
		resultHd.put("data", new HashMap());
	} catch (UnknownAccountException e) {
		resultHd.put("error", "失败");
		resultHd.put("errorCode", "2");
		resultHd.put("data", new HashMap());
		e.printStackTrace();
	} catch (IncorrectCredentialsException e) {
		resultHd.put("error", "失败");
		resultHd.put("errorCode", "3");
		resultHd.put("data", new HashMap());
		e.printStackTrace();
	} catch (AuthenticationException e) {
		// 其他错误,比如锁定,如果想单独处理请单独catch处理
		resultHd.put("error", "失败");
		resultHd.put("errorCode", "1");
		resultHd.put("data", new HashMap());
		e.printStackTrace();
	}

	result.put("header", resultHd);
	result.put("body", resultBd);

	return result;
}

User实体:

权限类:SysPermission.java

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;

@Getter
@Setter
@ToString
@Entity
public class SysPermission implements Serializable {
	@Id
	@GeneratedValue
	private Integer id;// 主键.
	private String name;// 名称.
	@Column(columnDefinition = "enum('menu','button')")
	private String resourceType;// 资源类型,[menu|button]
	private String url;// 资源路径.
	private String permission; // 权限字符串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:view
	private Long parentId; // 父编号
	private String parentIds; // 父编号列表
	private Boolean available = Boolean.FALSE;
	@ManyToMany
	@JoinTable(name = "SysRolePermission", joinColumns = { @JoinColumn(name = "permissionId") }, inverseJoinColumns = {
			@JoinColumn(name = "roleId") })
	private List<SysRole> roles;
}
----------------------------------------------------------------------------------------
角色类:SysRole.java

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;
import java.util.List;

@Getter
@Setter
@ToString
@Entity
public class SysRole {
	@Id
	@GeneratedValue
	private Integer id; // 编号
	private String role; // 角色标识程序中判断使用,如"admin",这个是唯一的:
	private String description; // 角色描述,UI界面显示使用
	private Boolean available = Boolean.FALSE; // 是否可用,如果不可用将不会添加给用户

	// 角色 -- 权限关系:多对多关系;
	@ManyToMany(fetch = FetchType.EAGER)
	@JoinTable(name = "SysRolePermission", joinColumns = { @JoinColumn(name = "roleId") }, inverseJoinColumns = {
			@JoinColumn(name = "permissionId") })
	private List<SysPermission> permissions;

	// 用户 - 角色关系定义;
	@ManyToMany
	@JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "roleId") }, inverseJoinColumns = {
			@JoinColumn(name = "uid") })
	private List<UserInfo> userInfos;// 一个角色对应多个用户

	// 省略 get set 方法
}
----------------------------------------------------------------------------------------
用户类:UserInfo.java

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;

@Getter
@Setter
@ToString
@Entity
public class UserInfo implements Serializable {
	@Id
	@GeneratedValue
	private Integer uid;
	@Column(unique = true)
	private String username;// 帐号
	private String name;// 名称(昵称或者真实姓名,不同系统不同定义)
	private String password; // 密码;
	private String salt;// 加密密码的盐
	private byte state;// 用户状态,0:创建未认证(比如没有激活,没有输入验证码等等)--等待验证的用户 , 1:正常状态,2:用户被锁定.
	@ManyToMany(fetch = FetchType.EAGER) // 立即从数据库中进行加载数据;
	@JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "uid") }, inverseJoinColumns = {
			@JoinColumn(name = "roleId") })
	private List<SysRole> roleList;// 一个用户具有多个角色

	/**
	 * 密码盐.
	 * 
	 * @return
	 */
	public String getCredentialsSalt() {
		return this.username + this.salt;
	}
	// 重新对盐重新进行了定义,用户名+salt,这样就更加不容易被破解
}

数据:

用户表:账号admin	密码admin
INSERT INTO `user_info`(`uid`, `name`, `password`, `salt`, `state`, `username`) VALUES (1, '管理员', 'f6fdffe48c908deb0f4c3bd36c032e72', '87', 0, 'admin');

权限表:
INSERT INTO `sys_permission`(`id`, `available`, `name`, `parent_id`, `parent_ids`, `permission`, `resource_type`, `url`) VALUES (1, b'0', '用户管理', 0, '0/', 'userInfo:view', 'menu', 'userInfo/userList');
INSERT INTO `sys_permission`(`id`, `available`, `name`, `parent_id`, `parent_ids`, `permission`, `resource_type`, `url`) VALUES (2, b'0', '用户添加', 1, '0/1', 'userInfo:add', 'button', 'userInfo/userAdd');
INSERT INTO `sys_permission`(`id`, `available`, `name`, `parent_id`, `parent_ids`, `permission`, `resource_type`, `url`) VALUES (3, b'0', '用户删除', 1, '0/1', 'userInfo:del', 'button', 'userInfo/userDel');

角色表:
INSERT INTO `sys_role`(`id`, `available`, `description`, `role`) VALUES (1, b'0', '管理员', 'admin');
INSERT INTO `sys_role`(`id`, `available`, `description`, `role`) VALUES (2, b'0', 'VIP会员', 'vip');

里面的Null类引用,可以在 https://blog.csdn.net/weixin_42614447/article/details/86536425 (Java 一些常用工具类)这里面找工具类。

目录结构

yml配置:

druid:
    stat:
        mergeSql: true;
        slowSqlMillis: 5000
logging:
    level:
        com: DEBUG
mybatis:
    mapper-locations: classpath:com/simple/*/dto/maps/*Mapper.xml
    type-aliases-package: com.simple.*
server:
    port: 8081
    servlet:
        context-path: /
spring:
    datasource:
        driverClassName: com.mysql.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://127.0.0.1:3306/oa?characterEncoding=utf8&autoReconnect=true&useSSL=false&useAffectedRows=true
        username: root
        password: root
        filters: stat,wall,log4j
        initialSize: 5
        maxActive: 20
        maxPoolPreparedStatementPerConnectionSize: 20
        maxWait: 60000
        minEvictableIdleTimeMillis: 300000
        minIdle: 5
        poolPreparedStatements: true
        testOnBorrow: false
        testOnReturn: false
        testWhileIdle: true
        timeBetweenEvictionRunsMillis: 60000
        validationQuery: SELECT 1 FROM DUAL
    http:
        encoding:
            charset: UTF-8
            enabled: true
    jpa:
        show-sql: true
        hibernate:
            ddl-auto: update
            naming:
                physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
        properties:
            hibernate:
                dialect: org.hibernate.dialect.MySQL5Dialect
    mvc:
        locale: zh_CN
        view:
            prefix: /WEB-INF/jsp/
            suffix: .jsp
        static-path-pattern: /**
    #资源名称md5方式
    resources:
        chain:
            strategy:
                content:
                    enabled: true
                    paths: /**

以上就是shiro完整代码,如有疑问,随时评论.

转载请注明出处!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot 整合shiro框架 的相关文章

随机推荐

  • nrm 安装与使用

    nrm 安装与使用 nrm 是 npm 的镜像源管理工具 可以用来切换 npm 镜像源 安装 nrm 使用 npm 全局安装 npm i g nrm nrm 命令 查看镜像列表 带 号为当前镜像 nrm ls 查看当前所在镜像 nrm cu
  • 【STM32F4】二、I/O引脚的复用和映射

    目录 一 基本概念 1 什么是I O引脚 2 什么是I O引脚的复用 二 如何配置I O引脚复用 1 复用器 GPIOx AFRL GPIOx AFRH 和复用功能 AF 2 程序编写 2 1 打开I O时钟和复用功能对应外设时钟 2 2
  • win7安装ubuntu,如何设置win7为默认启动项

    第一种方法 运行sudo gedit etc default grub 输入密码 将GRUB DEFAULT 0改为GRUB DEFAULT 4 如果没做过其他设置 即启动时win7为第5项 可根据自己情况更改 然后运行sudo updat
  • Android 快速开发框架:推荐10个框架

    一 Afinal 官方介绍 Afinal是一个android的ioc orm框架 内置了四大模块功能 FinalAcitivity FinalBitmap FinalDb FinalHttp 通过finalActivity 我们可以通过注解
  • 免费的HTML5连载来了《HTML5网页开发实例详解》连载(五)图解通过Fiddler加速开发...

    Fiddler是Windows底下最强大的请求代理调试工具 监控任何浏览器的HTTP HTTPS流量 窜改客户端请求和服务器响应 解密HTTPS Web会话 图4 44为Fiddler原理示意图 图4 44 Fiddler原理示意图 Fid
  • 20个基于SpringBoot搭建的开源项目,总有一个你会感兴趣

    前言 SpringBoot一直是开发者比较青睐的一款轻量级框架 他不仅继承了Spring框架原有的优秀特性 而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程 现在很多Java系的软件开发都是基于SpringBoot的 这
  • 安秒平衡在单相整流器纹波分析中的应用

    1 占空比表达式 单相PWM整流器的拓扑如图所示 四个开关管S1 S4 采用双极性调制 S1与S4开关信号一样 S2和S3开关信号相同 两者互补 假设调制度表达式 m Vgm Vo S1占空比表达式为D S1 0 5m sinwt 0 5
  • 数据提取-Selenium专治各种顽固性客户端

    说起Selenium 很多人想到的是Selenium用在自动化web测试上 的确 Selenium是一个很好的自动化测试工具 能够实现很多便利的测试功能 其实Selenium也是一款数据抽取的神器 我们知道现在很多网站使用了很多javasc
  • OSI 五层网络模型详解

    OSI网络模型 是指 开放式系统互联通信参考模型 英语 Open System Interconnection Reference Model 缩写为 OSI 简称为OSI模型 OSI model 一种概念模型 由ISO 国际标准化组织 提
  • python 查找指定字符在字符串中的次数(全)

    s neu is very neupk kjneuneu dhsj neu print s count neu n 0 co 0 while s find neu n len s 1 co 1 n s find neu n len s 1
  • 【技术经验分享】计算机毕业设计hadoop+spark知识图谱房源推荐系统 房价预测系统 房源数据分析 房源可视化 房源大数据大屏 大数据毕业设计 机器学习

    创新点 1 支付宝沙箱支付 2 支付邮箱通知 JavaMail 3 短信验证码修改密码 4 知识图谱 5 四种推荐算法 协同过滤基于用户 物品 SVD混合神经网络 MLP深度学习模型 6 线性回归算法预测房价 7 Python爬虫采集链家数
  • 实现线程同步的几种方法

    在多线程程序中 会出现多个线程抢占一个资源的情况 这时间有可能会造成冲突 也就是一个线程可能还没来得及将更改的 资源保存 另一个线程的更改就开始了 可能造成数据不一致 因此引入多线程同步 也就是说多个线程只能一个对共享的资源进行更改 其他线
  • 计算机用户名携带中文路径,Win10 User下的中文用户名改成英文路径操作方法

    导读 Win10 User下的中文用户名改成英文路径的方法 相关电脑教程分享 有很多Win10系统用户在新购买电脑或是新装Win10时采用了中文用户名 这时会发现C User下的文件夹是中文名 但是这样有一个很不好的地方 很多软件安装在个路
  • JavaWeb新留言板系统 23年4月原创

    JavaWeb留言板系统 2023年4月原创 极低价付费提供项目代码 sql文件 配置说明 包运行服务 答疑解惑服务 私信即可 功能概述 JavaWeb留言板系统项目遵循MVC编程模式 基于Servlet Bootstrap MySQL J
  • Git&&Github配置

    1 把现有的 ssh key 都删掉或查找现有的key PS 如果多打空格可能要破环系统 删掉现有的Key rm rf ssh 查找现有的Key 如果没有 bash终端显示如下 No such file or directory 如果已经存
  • 常见Windows Server漏洞处理方法

    常见的几种漏洞 mysql 3306 Oracle 1521 Redis 6379 Tomcat 8080 445 138端口不安全 weblogic Server 7001 3389远程桌面 下面分别讲解几种漏洞解决的方法 一 mysql
  • CH06_第一组重构(下)

    封装变量 Encapsulate Variable 132 曾用名 自封装字段 Self Encapsulate Field 曾用名 封装字段 Encapsulate Field let defaultOwner firstName Mar
  • C++的强制类型转换

    关于强制类型转换的问题 很多书都讨论过 写的最详细的是C 之父的 C 的设计和演化 最好的解决方法就是不要使用C风格的强制类型转换 而是使用标准C 的类型转换符 static cast dynamic cast 标准C 中有四个类型转换符
  • 在docker上安装spark

    拉安装好spark的镜像 https hub docker com r bde2020 spark master docker pull bde2020 spark master 安装master节点 docker run name spa
  • SpringBoot 整合shiro框架

    网上有很多整合shiro的博客分享 但是貌似没找到一个完整 并且能够实现的 不是包的问题 就是代码的问题 也可能是自己的问题 或者版本的问题 所以 整理了一版自己已应用的 maven依赖