SpringBoot整合Shiro实现登录认证和授权CHCache

文章目录

    • 一、 springboot实现普通登录
      • 1 添加依赖
      • 2 编写配置文件
      • 3 新建实体类和mapper
      • 4 编写业务层代码
      • 5 编写控制器
      • 6 编写启动类
      • 7 编写登录页面和主页面
    • 二、 springboot整合shiro实现登录认证和凭证匹配
      • 1 添加依赖
      • 2 自定义Realm
      • 3 编写配置
      • 4 userService新增单元方法:使用shiro认证
      • 5 凭证匹配器
        • 5.1 修改ShiroConfig
        • 5.2 修改MyRealm
    • 三、 remember me实现---shiro已经集成
      • 1 修改application.yml-----增加shiro的loginUrl地址
      • 2 增加记住我的按钮
      • 3 修改Controller
      • 4 修改ShiroConfig
    • 四、 配置退出
      • 1 修改配置类
      • 2 修改主页面
    • 五、 授权
      • 1 简介
      • 2 Thymeleaf整合shiro
        • 2.1 添加依赖
        • 2.2 修改配置类(负责解析thymeleaf中shiro的相关属性)
        • 2.3 修改Realm
        • 2.4 修改main.html
      • 3 使用注解判断方法是否具有权限执行
        • 3.1 修改main.html
        • 3.2 修改UserController类
        • 3.3 新建依赖处理类
    • 六 EHCache
      • 1 ehcache简介
      • 2 EHCache API演示
        • 2.1 添加依赖
        • 2.2 新建配置文件
    • 七 Shiro和EhCache整合
      • 1 添加依赖
      • 2 编写ehcache缓存配置
      • 3 修改配置文件
    • 八 Shiro中Session对象获取

一、 springboot实现普通登录

1 添加依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.bjsxt</groupId><artifactId>02_shiro_springboot_login</artifactId><version>1.0-SNAPSHOT</version><!--配置继承--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.10.RELEASE</version></parent><!--配置依赖--><dependencies><!--配置web启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--配置mybatis启动器--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.1</version></dependency><!--配置mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.48</version></dependency><!--配置Thrmeleaf启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency></project>

2 编写配置文件

新建application.yml

spring:datasource:driver-class-name: com.mysql.jdbc.Driverusername: rooturl: jdbc:mysql://localhost:3306/springboot-loginpassword: 1234
##配置mapper的xml文件的路径
mybatis:mapper-locations: classpath:mybatis/*.xml

3 新建实体类和mapper

新建com.bjsxt.pojo.User

public class User {private Long id;private String username;private String pwd;// 省略getter和setter
// 省略构造方法
}

新建com.bjsxt.mapper.UserMapper

package com.bjsxt.mapper;public interface UserMapper {//根据用户名查询用户信息@Select("select * from t_user where uname=#{uname}")User selUserInfoMapper(@Param("uname") String uname);
}

4 编写业务层代码

新建com.bjsxt.service.UserService及实现类

public interface UserService {//用户登录User selUserInfoService(String uname);
}
@Service
public class UserServiceImpl implements UserService {//声明mapper属性@Autowiredprivate UserMapper userMapper;//用户登录@Overridepublic User selUserInfoService(String uname) {return userMapper.selUserInfoMapper(uname);}
}

5 编写控制器

新建com.bjsxt.controller.UserController

package com.bjsxt.controller;@Controller
public class UserController {//声明service属性@Autowiredprivate UserService userService;//声明单元方法:登录认证@RequestMapping("userLogin")public String userLogin(String uname,String pwd){//1.根据用户名获取用户信息User user=userService.selUserInfoService(uname);//2.判断用户名是否合法if(user!=null){//3.校验密码if(user.getPwd().equals(pwd)){//认证成功return "main";}}return "error";}//声明公共单元方法完成页面的内部转发@RequestMapping("{uri}")public String getPage(@PathVariable String uri){return uri;}}

6 编写启动类

新建com.bjsxt.ShiroApplication

package com.bjsxt;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.bjsxt.mapper")
public class ShiroApplication {public static void main(String[] args) {SpringApplication.run(ShiroApplication.class,args);}}

7 编写登录页面和主页面

新建templates/login.html

<!DOCTYPE html>
<html  xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h3>SpringBoot整合Shiro登录案例</h3><hr><!--创建登录页面--><form action="userLogin" method="post">用户名: <input type="text" name="uname" value=""><br>密码: <input type="password" name="pwd" value=""><br><input type="submit" value="登录"></form></body>
</html>

新建templates/main.html。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>我是主页面
</body>
</html>

二、 springboot整合shiro实现登录认证和凭证匹配

1 添加依赖

    <dependencies><!-- 注释掉web启动器是因为shiro-spring-boot-web-starter依赖了spring-boot-starter-web --><!-- <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>--><!--配置shiro的启动器--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.4.2</version></dependency></dependencies>

2 自定义Realm

新建com.bjsxt.shiro.MyRealm编写认证逻辑

package com.bjsxt.shiro;//配置为Bean对象
@Component
public class MyRealm extends AuthorizingRealm {//声明业务层属性@Autowiredprivate UserService userService;//自定义授权策略@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}//自定义认证策略@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//声明认证代码//1.获取用户传递的用户名信息Object principal = token.getPrincipal();//2.根据用户名获取数据库中的用户信息User user = userService.selUserInfoService((String) principal);//3.认证if(user!=null){//用户名是正确的//4.认证密码AuthenticationInfo info=  new SimpleAuthenticationInfo(principal,user.getPwd(), user.getUname());return info;}return null;}
}

3 编写配置

新建com.bjsxt.config.ShiroConfig,编写配置

package com.bjsxt.config;@Configuration
public class ShiroConfig {//声明MyRealm属性@Autowiredprivate MyRealm myRealm;//声明bean方法@Beanpublic DefaultWebSecurityManager securityManager(){DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();defaultWebSecurityManager.setRealm(myRealm);return defaultWebSecurityManager;}

4 userService新增单元方法:使用shiro认证

package com.bjsxt.controller;@Controller
public class UserController {//声明单元方法:使用shiro认证@RequestMapping("userLogin2")public String userLogin2(String uname,String pwd){//1.获取subject对象Subject subject = SecurityUtils.getSubject();//2.认证//创建认证对象存储认证信息AuthenticationToken token= new UsernamePasswordToken(uname,pwd);try{subject.login(token);return "redirect:main";}catch(Exception e){e.printStackTrace();}return "redirect:login";}//声明公共单元方法完成页面的内部转发@RequestMapping("{uri}")public String getPage(@PathVariable String uri){return uri;}}

此时登录出现问题:访问login时报错,错误说找不到login.jsp,应该找的是login.html
解决:在ShiroConfig配置类自定义shiro过滤器参数bean

package com.bjsxt.config;@Configuration
public class ShiroConfig {//自定义shiro过滤器参数bean@Beanpublic ShiroFilterChainDefinition shiroFilterChainDefinition(){DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();definition.addPathDefinition("/login", "anon");definition.addPathDefinition("/userLogin", "anon");definition.addPathDefinition("/main", "anon");definition.addPathDefinition("/**", "user");return definition;}}

<form action="userLogin" method="post">改为<form action="userLogin2" method="post">

<body><h3>SpringBoot整合Shiro登录案例</h3><hr><!--创建登录页面--><form action="userLogin2" method="post">用户名: <input type="text" name="uname" value=""><br>密码: <input type="password" name="pwd" value=""><br><input type="submit" value="登录"></form>
</body>

启动测试

5 凭证匹配器

首先将数据库中用户张三的密码改为:6bdae6366c1e46d541eb0ca9547d974c

5.1 修改ShiroConfig

@Bean
public DefaultWebSecurityManager securityManager() {DefaultWebSecurityManager defaultWebSecurityManager= new DefaultWebSecurityManager();//创建凭证匹配器HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();matcher.setHashAlgorithmName("md5");matcher.setHashIterations(2);myRealm.setCredentialsMatcher(matcher);//将自定义的认证策略对象注入到SecurityManagerdefaultWebSecurityManager.setRealm(myRealm);return defaultWebSecurityManager;
}

5.2 修改MyRealm

修改MyRealm中doGetAuthenticationInfo方法。

//自定义认证策略@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//声明认证代码//1.获取用户传递的用户名信息Object principal = token.getPrincipal();//2.根据用户名获取数据库中的用户信息User user = userService.selUserInfoService((String) principal);//3.认证if(user!=null){//用户名是正确的//4.认证密码AuthenticationInfo info=  new SimpleAuthenticationInfo(principal,user.getPwd(), ByteSource.Util.bytes(user.getUid()+""),user.getUname());return info;}return null;}

三、 remember me实现—shiro已经集成

1 修改application.yml-----增加shiro的loginUrl地址

spring:datasource:driver-class-name: com.mysql.jdbc.Driverusername: rooturl: jdbc:mysql://localhost:3306/springboot-loginpassword: 1234
##配置mapper的xml文件的路径
mybatis:mapper-locations: classpath:mybatis/*.xml
shiro:##当用户访问某个需要登录的功能时,但是被shiro内置的过滤器拦截后,判断本次请求##没有登录,而是直接访问的,则重定向到loginUrl的路径资源响应给用户loginUrl: /login

2 增加记住我的按钮

<!DOCTYPE html>
<html  xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h3>SpringBoot整合Shiro登录案例</h3><hr><!--创建登录页面--><form action="userLogin2" method="post">用户名: <input type="text" name="uname" value=""><br>密码: <input type="password" name="pwd" value=""><br><input type="submit" value="登录">&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" name="rememberme" value="true">记住俺</form></body>
</html>

3 修改Controller

@RequestMapping("userLogin2")public String userLogin2(String uname,String pwd,@RequestParam(defaultValue = "false") Boolean rememberme){//1.获取subject对象Subject subject = SecurityUtils.getSubject();//2.认证//创建认证对象存储认证信息AuthenticationToken token= new UsernamePasswordToken(uname,pwd,rememberme);try{subject.login(token);return "redirect:main";}catch(Exception e){e.printStackTrace();}return "redirect:login";}

4 修改ShiroConfig

	@Beanpublic DefaultWebSecurityManager securityManager(){DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();//创建凭证匹配器HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();//设置匹配器的加密算法matcher.setHashAlgorithmName("md5");//设置匹配器的迭代加密次数matcher.setHashIterations(2);//将匹配器注入到自定义的认证策略对象中myRealm.setCredentialsMatcher(matcher);//将自定义的认证策略对象注入到SecurityManagerdefaultWebSecurityManager.setRealm(myRealm);//将CookieRememberMeManager对象注入到SecurityManager,开启了rememberme功能defaultWebSecurityManager.setCacheManager(ehCacheManager());return defaultWebSecurityManager;}//设置Cookie的信息public SimpleCookie rememberMeCookie(){SimpleCookie simpleCookie=new SimpleCookie("rememberMe");//设置有效路径simpleCookie.setPath("/");//设置声明周期simpleCookie.setMaxAge(30*24*60*60);//返回设置的cookiereturn simpleCookie;}//创建rememberMeManager对象public CookieRememberMeManager rememberMeManager(){//创建CookieRememberMeManager对象CookieRememberMeManager cookieRememberMeManager=new CookieRememberMeManager();//注入Cookie对象cookieRememberMeManager.setCookie(rememberMeCookie());//设置密钥cookieRememberMeManager.setCipherKey(Base64.decode("MTIzNDU2Nzg="));//返回return cookieRememberMeManager;}//自定义shiro过滤器参数bean----`definition.addPathDefinition("/**", "user");`@Beanpublic ShiroFilterChainDefinition shiroFilterChainDefinition(){DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();definition.addPathDefinition("/login", "anon");definition.addPathDefinition("/userLogin2", "anon");//开启shiro内置的退出过滤器,完成退出功能definition.addPathDefinition("/logout", "logout");//definition.addPathDefinition("/main", "anon");definition.addPathDefinition("/**", "user");return definition;}

四、 配置退出

1 修改配置类

修改ShiroConfig类,添加logout filter 对应的url。definition.addPathDefinition("/logout", "logout");

@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();definition.addPathDefinition("/doLogin", "anon");definition.addPathDefinition("/logout", "logout");definition.addPathDefinition("/**", "authc");return definition;
}

2 修改主页面

在index.html页面中添加超链接。跳转到/logout后会由shiro内置filter进行拦截。

<body>
index.html
<a href="/logout">退出</a>
</body>

五、 授权

1 简介

授权就是判断认证用户是否具有指定角色或指定权限。
Shiro可以和JSP整合也可以和Thymeleaf整合,我们讲解SpringBoot的视图技术Thymeleaf整合Shiro。
只要是授权就执行Realm的doGetAuthorizationInfo进行判断,而触发doGetAuthorizationInfo的方式,常用的就两种:
(1)在页面中通过shiro:xxxx 属性进行判断
(2)在java代码中通过注解@RequiresXXX

thymeleaf中常用属性

需要在html页面中添加属性

<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">

1.1 shiro:user=””
认证通过或已记住的用户。
1.2 shiro:authenticated=””
认证通过的用户。不包含记住的用户。
1.3 shiro:principal
输出认证用户信息。shiro:principal/
1.4 shiro:hasRole=“admin”
判断是否具有指定角色。
1.5 shiro:lacksRole=“admin”
判断是否不是没有指定角色。
1.6 shiro:hasAllRoles=“role1,role2”
判断指定角色用户是否都具有。
1.7 shiro:hasAnyRoles=“role1,role2”
只要用户具有其中一个角色就表示判断通过。
1.8 shiro:hasPermission=“userInfo:add”
是否具有指定权限。
1.9 shiro:lacksPermission=“userInfo:del”
是否不具有指定权限
1.10 shiro:hasAllPermissions=“userInfo:view, userInfo:add”
是否全具有指定权限。
1.11 shiro:hasAnyPermissions=“userInfo:view, userInfo:del”
只要有其中任何一个权限即可。

2 Thymeleaf整合shiro

2.1 添加依赖

<dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.0.0</version>
</dependency>

2.2 修改配置类(负责解析thymeleaf中shiro的相关属性)

//创建解析Thymeleaf中的shiro属性的对象,由SpringBoot项目底层自动调用@Beanpublic ShiroDialect shiroDialect() {return new ShiroDialect();}

2.3 修改Realm

绑定用户具有的角色和权限,相关数据应该是从数据库中取出。

//自定义授权策略@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//1.从数据库中获取用户的权限信息//2.将权限信息存储到shiro授权对象中System.out.println("我是授权认证方法,我被执行了");SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();info.addRole("role1");info.addRole("role2");info.addStringPermission("user:insert");info.addStringPermission("user:update");info.addStringPermission("sys:*");return info;}

2.4 修改main.html

访问页面后会发现“有角色”不显示,“有权限”显示。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>我是主页面<a href="/logout">退出</a><hr><span shiro:hasRole="role3">有角色</span><br><span shiro:user="">shiro:user=””认证通过或已记住的用户</span><br><span shiro:authenticated="">shiro:authenticated=””认证通过的用户。不包含记住的用户。</span><br><hr><a href="/demo">测试后台逻辑代码的授权</a></body>
</html>

3 使用注解判断方法是否具有权限执行

方法:可以用控制器方法,也可以是业务方法。常在控制器方法上添加注解进行判断。
常用注解:
(1)@RequiresPermissions("") 必须具有指定权限
(2)@RequiresAuthentication 必须已经认证
(3)@RequiresRoles("") 必须具有指定角色
(4)@RequiresUser 必须是已认证或记住用户
(5)@RequiresGuest 必须是访客

3.1 修改main.html

添加下面内容

<a href="/isPermission">跳转到判断权限的控制器</a>

3.2 修改UserController类

@RequestMapping("/isPermission")
@ResponseBody
@RequiresPermissions("abc:jqk")
public String isPermission(){return "OK";
}

当用户登录成后,点击超链接“跳转到判断权限的”超链接会出现500错误页面信息。
在这里插入图片描述

3.3 新建依赖处理类

新建com.bjsxt.controller.NoPermissionException

@ControllerAdvice
public class NoPermissionException {@ResponseBody@ExceptionHandler(UnauthorizedException.class)public String handleShiroException(Exception ex) {return "无权限";}@ResponseBody@ExceptionHandler(AuthorizationException.class)public String AuthorizationException(Exception ex) {return "权限认证失败";}
}

六 EHCache

1 ehcache简介

EHCache是sourceforge的开源缓存项目,现已经具有独立官网,网址:(http://www.ehcache.org)。其本身是纯JAVA实现的,所以可以和绝大多数Java项目无缝整合,例如:Hibernate的缓存就是基于EHCache实现的。
EHCache支持内存和磁盘缓存,默认是存储在内存中的,当内存不够时允许把缓存数据同步到磁盘中,所以不需要担心内存不够问题。
EHCache支持基于Filter的Cache实现,同时也支持Gzip压缩算法提高响应速度。

2 EHCache API演示

2.1 添加依赖

从3.0版本开始groupid为org.ehcache

<dependencies><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId><version>2.6.11</version></dependency>
</dependencies>

2.2 新建配置文件

在src/main/resources中新建ehcache.xml。
属性含义:
maxElementsInMemory:缓存中允许创建的最大对象数。
eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
timeToIdleSeconds:缓存数据的钝化时间,取值0表示无限长。
timeToLiveSeconds:缓存数据的生存时间,取值0表示无限长。
overflowToDisk:内存不足时,是否启用磁盘缓存。
memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache><!-- 磁盘缓存位置 --><diskStore path="java.io.tmpdir/ehcache"/><!-- 默认缓存 --><defaultCachemaxEntriesLocalHeap="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"maxEntriesLocalDisk="10000000"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"><persistence strategy="localTempSwap"/></defaultCache><!-- helloworld缓存 --><cache name="HelloWorldCache"maxElementsInMemory="1000"eternal="false"timeToIdleSeconds="5"timeToLiveSeconds="5"overflowToDisk="false"memoryStoreEvictionPolicy="LRU"/>
</ehcache>

七 Shiro和EhCache整合

Shiro支持很多第三方缓存工具。官方提供了shiro-ehcache,实现了把EHCache当做Shiro的缓存工具的解决方案。其中最好用的一个功能是就是缓存认证执行的Realm方法,减少对数据库的访问。

1 添加依赖

添加shiro-ehcache依赖。
commons-io主要是为了使用里面的工具类。本质和当前整合功能没有关系。

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.4.2</version>
</dependency>
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version>
</dependency>

2 编写ehcache缓存配置

在resources下新建ehcache/ehcache-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="ehcache" updateCheck="false"><!-- 磁盘缓存位置 -->
<diskStore path="java.io.tmpdir"/>
<!-- 默认缓存 -->
<defaultCachemaxEntriesLocalHeap="1000"eternal="false"timeToIdleSeconds="3600"timeToLiveSeconds="3600"overflowToDisk="false">
</defaultCache><!-- 登录记录缓存 锁定10分钟 -->
<cache name="loginRecordCache"maxEntriesLocalHeap="2000"eternal="false"timeToIdleSeconds="600"timeToLiveSeconds="0"overflowToDisk="false"statistics="true">
</cache></ehcache>

3 修改配置文件

@Bean
public DefaultWebSecurityManager securityManager() {DefaultWebSecurityManager manager = new DefaultWebSecurityManager();HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();hashedCredentialsMatcher.setHashAlgorithmName("md5");hashedCredentialsMatcher.setHashIterations(2);myRealm.setCredentialsMatcher(hashedCredentialsMatcher);manager.setRealm(myRealm);manager.setRememberMeManager(rememberMeManager());manager.setCacheManager(getEhCacheManager());return manager;
}@Bean
public EhCacheManager ehCacheManager(){EhCacheManager ehCacheManager = new EhCacheManager();InputStream is = null;try {is = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache-shiro.xml");} catch (IOException e) {e.printStackTrace();}net.sf.ehcache.CacheManager cacheManager = new net.sf.ehcache.CacheManager(is);ehCacheManager.setCacheManager(cacheManager);return ehCacheManager;
}

八 Shiro中Session对象获取

Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("key","value");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324600.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中如何对对象排序?

大家好&#xff0c;我是雄雄。前言&#xff1a;我们知道&#xff0c;在平时做项目的过程中&#xff0c;我们总会用到各种各样的排序&#xff0c;或是升序&#xff0c;或是降序。在java中&#xff0c;要实现排序有好多中方式&#xff0c;比如我们耳熟能详的冒泡排序、选择排序等…

Java程序员必看的 13 本 Java 书籍

转载自 Java程序员必看的 13 本 Java 书籍 关乎于程序员&#xff0c;除了做项目来提高自身的技术&#xff0c;还有一种提升自己的专业技能就是&#xff1a;多&#xff01;看&#xff01;书&#xff01; 毕竟&#xff0c;书是学习的海洋呢&#xff01;So&#xff0c;Java程序…

祝你生日快乐!

祝生日快乐今天&#xff0c;于我来说是个特别的日子。本来&#xff0c;我是比较低调的&#xff0c;尤其是对于生日来说&#xff0c;可以说是这些年都没有好好的过过&#xff0c;要么忘记了&#xff0c;要么就是在异国他乡的&#xff0c;谁都不识&#xff0c;这一天和往常的一天…

.NET Exceptionless 日志收集框架本地环境搭建

一、简介 Exceptionless 是一个开源的实时的日志收集框架&#xff0c;它可以应用在基于 ASP.NET&#xff0c;ASP.NET Core&#xff0c;Web Api&#xff0c;Web Forms&#xff0c;WPF&#xff0c;Console&#xff0c;MVC 等技术栈的应用程序中&#xff0c;并且提供了Rest接口可以…

java中如何对汉字进行排序?

前言&#xff1a;上一篇文章我们讲解了java中实现Comparator进行排序 和实现Comparable进行排序&#xff0c;我们分别举例根据学号和姓名降序排序&#xff0c;原文在这里&#xff1a;java中如何对对象排序&#xff1f; &#xff0c;不过在文章的最后&#xff0c;我故意留了个问…

Blazor将.NET带回到浏览器

由Steve Sanderson开发的Blazor尝试使用WebAssembly和DotNetAnywhere将.NET带回到浏览器。它不是要成为一个像Flash或Silverlight那样的完整生产框架&#xff0c;而是要探索一下有什么可能性。 WebAssembly将自己描述成一个“内存安全的沙箱执行环境”标准&#xff0c;它“甚至…

过滤器和监听器

文章目录01 过滤器的简介02 使用过滤器进行乱码解决03 使用过滤器进行登陆的控制04 过滤器更多内容05 监听器实现日志记录06 监听器实现在线人数的统计07 其他监听器使用01 过滤器的简介 为什么使用过滤器&#xff1f; 我们目前书写项目中遇到的问题&#xff1f; A、目前使用的…

高启航:秋运会!

本文原创&#xff1a;高启航&#xff08;本文所有收益均归高启航所有&#xff09;在十月份的二十一号&#xff0c;我们济南信息工程学校迎来了一年一度的秋季运动会。这次秋运会&#xff0c;每一个班级所准备的开幕式、训练已久的千人武术大展演、以及在运动会上表现优越的运动…

用python画出吉祥物

大前提 你需要一个"npy" 效果图 源码 # 库的导入 import turtleturtle.title(PythonBingDwenDwen&#xff08;axing&#xff09;) #这里的字我们可以自己进行修改turtle.speed(10) # 速度&#xff0c;如果觉得20快了&#xff0c;你们可以设置10# 左手 turtle.p…

RabbitMQ知多少

1.引言 RabbitMQ——Rabbit Message Queue的简写&#xff0c;但不能仅仅理解其为消息队列&#xff0c;消息代理更合适。RabbitMQ 是一个由 Erlang 语言开发的AMQP&#xff08;高级消息队列协议&#xff09;的开源实现&#xff0c;其内部结构如下&#xff1a; RabbitMQ作为一个…

王宝兴:秋运会

本文原创&#xff1a;王宝兴本文所有收益归王宝兴所有一年一度的运动会如期而至。可谓是“沙场秋点兵”的壮阔&#xff0c;给了我们难以言喻的激情。为了入场式&#xff0c;为了我们每个人&#xff0c;为了我们整个班集体&#xff0c;所有人付出的不止一点&#xff0c;在这短短…

.NET Core快速入门教程 1、开篇:说说.NET Core的那些事儿

一、.NET Core的诞生 聊 .NET Core&#xff0c;就不得不说他的爸爸 .NET。当年Java刚刚兴起&#xff0c;如火如荼&#xff0c;微软也非常推崇Java&#xff0c;当时Windows平台的Java虚拟机就是微软按照JVM标准实现的&#xff0c;据说也是当时性能最好的Java虚拟机。但是微软也…

机器学习和深度学习概念入门

转载自 机器学习和深度学习概念入门 作者&#xff1a;谭东 遵循&#xff1a;BY-SA&#xff08;署名-相同方式共享4.0协议&#xff09; 对于很多初入学习人工智能的学习者来说&#xff0c;对人工智能、机器学习、深度学习的概念和区别还不是很了解&#xff0c;有可能你每天…

lldb 调试 linux下 .net Core 总结及开源扩展 yinuo

相信很多朋友在跟随微软.net core 从windows平台迁移至linux平台的过程中遇到很多别扭的地方&#xff0c;这里我只聊聊 运行时 调试的那些事儿。 首先从工具上来讲Windows上的windbg肯定是运行时的首选调试工具(因为有对应版本的SOS.dll)&#xff0c;在linux平台运行时调试需要…

班级日常分享:一天一瞬间!

好久没有记录班级日常了&#xff0c;自运动会结束之后&#xff0c;事情比较多&#xff0c;也很忙&#xff0c;所以没有及时记录。19级3班最近在上bootstrap&#xff0c;属于前端的范畴&#xff0c;内容较简单&#xff0c;同学们都能跟的上老师的步伐&#xff0c;一行一行大代码…

Java 程序员必须掌握的 8 道数据结构面试题,你会几道

转载自 Java 程序员必须掌握的 8 道数据结构面试题&#xff0c;你会几道 瑞士计算机科学家Niklaus Wirth在1976年写了一本书&#xff0c;名为《算法数据结构编程》。 40多年后&#xff0c;这个等式仍被奉为真理。这就是为什么在面试过程中&#xff0c;需要考察软件工程师对数…

vue.js 01 模板语法

文章目录vue插值vue指令vue插值 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport&…

如何使用bootstrap实现轮播图?

大家好&#xff0c;我是雄雄&#xff0c;今天给大家分享的是如何使用bootstrap实现轮播图&#xff0c;美观大方且兼容性还好&#xff01;轮播图就不做过多的介绍了&#xff0c;大家都知道&#xff0c;只是轮播的实现有多种方式&#xff0c;例如使用纯js写&#xff0c;费时费力&…

Visual Studio Code: 利用 MSSQL 插件创建数据库 IDE

尽管面对繁重的 .NET 开发任务 Visual Studio 仍是我的首选 IDE&#xff0c;但我却已深深迷恋上 Visual Studio Code (VS Code)&#xff0c;无论我使用的语言是 C#、JavaScript 还是 Node&#xff0c;也无论我使用的操作系统是 Windows 还是 macOS。 当然&#xff0c;VS Code 及…