首页
友链
关于
免责声明
Search
1
王者营地战绩数据王者荣耀查询网页源码
6,209 阅读
2
群晖Active Backup for Business套件备份Linux服务器教程
4,384 阅读
3
影视分享
4,313 阅读
4
(亲测)Jrebel激活破解方式2019-08-21
4,289 阅读
5
centos7 安装及卸载 jekenis
3,573 阅读
日常
文章
后端
前端
Linux
异常
Flutter
分享
群辉
登录
Search
标签搜索
docker
springboot
Spring Boot
java
linux
Shiro
Graphics2D
图片
游戏账号交易
Mybatis
Spring Cloud
centos
脚本
Web Station
群辉
王者营地
战绩查询
平台对接
Spring Cloud Alibaba
nacos
绿林寻猫
累计撰写
249
篇文章
累计收到
26
条评论
首页
栏目
日常
文章
后端
前端
Linux
异常
Flutter
分享
群辉
页面
友链
关于
免责声明
搜索到
195
篇与
后端
的结果
2021-12-08
Spring Cloud 入门之 Hystrix(四) 附源码
一、前言在微服务应用中,服务存在一定的依赖关系,如果某个目标服务调用慢或者有大量超时造成服务不可用,间接导致其他的依赖服务不可用,最严重的可能会阻塞整条依赖链,最终导致业务系统崩溃(又称雪崩效应)。上述的问题将是本篇需要解决的问题。二、简单介绍# 2.1 请求熔断断路器是一种开关设置,当某个服务单元发生故障之后,通过断路器的故障监控,向调用方返回一个符合预期的服务降级处理(fallback),而不是长时间的等待或者抛出调用方无法处理的异常,这样保证了服务调用方的线程不会长时间被占用,从而避免了故障在分布式系统的蔓延乃至崩溃。# 2.2 服务降级fallback 相当于是降级操作。对于查询操作, 我们可以实现一个 fallback 方法, 当请求后端服务出现异常的时候, 可以使用 fallback 方法返回的值。 fallback 方法的返回值一般是设置的默认值或者来自缓存,告知后面的请求服务不可用了,不要再请求了。# 2.3 请求熔断和服务降级区别相同:目标一致:为了防止系统崩溃而实施的一种防御手段 表现形式一致:当请求目标在一定时间内无响应时,返回或执行默认响应内容 不同:触发条件不同:下游服务出现故障触发请求熔断。系统负荷超过阈值触发服务降级。 管理目标层次不同:请求熔断针对所有微服务。服务降级针对整个系统中的外围服务。2.4 实现方案Spring Cloud Hystrix 实现了断路器、线程隔离等一系列服务保护功能。它是基于 Netflix 的开源框架 Hystrix 实现的,该框架的目的在于通过控制访问远程系统、服务和第三方库节点,从而对延迟和故障提供更强大的容错能力。Hystrix 具备服务熔断、服务降级、线程和信号隔离、请求缓存、请求合并以及服务监控的能力。本次测试基于之前发表的文章,不清楚请移步Spring Cloud 入门 之 Feign(三)三、请求熔断实战3.1在“消费者”中添加依赖:<!-- hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.1.0.RELEASE</version> </dependency>3.2设置熔断策略 方法上加 @HystrixCommand 注解:@Service public class UserServiceImpl implements IUserService { @Autowired private ApiFeign apiFeign; @HystrixCommand(fallbackMethod = "defaultSelect") @Override public User select(Integer uId) { return apiFeign.select(uId); } public User defaultSelect() { User user = new User(); user.setuId(-1); user.setuName("没有数据"); return user; } }当调用服务超时或出现异常时,Hystrix 会调用 @HystrixCommand 中指定的 fallbackMethod 方法获取返回值或执行异常处理。注意:fallbackMethod 方法要求与正常方法有相同的入参和回参。3.3 启动熔断功能在启动类上添加 @EnableCircuitBreaker 注解:@EnableFeignClients(basePackages = {"com.web.demo"}) @EnableEurekaClient @EnableHystrix @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }3.4 熔断测试我们首先演示没有开启熔断的功能,即先把上边的 @EnableCircuitBreaker 注解进行注释。2.再将 @EnableCircuitBreaker 注解的注释放开请求一个没有的用户ID从图中可知,虽然请求了一个 不存在的id,但是调用方(消费者)开启了熔断机制,执行默认方法,从而使接口能正常通信而不是抛出调用方不可处理的异常导致整个系统不能正常运行。看到这里,或许会有读者产生一个疑问,如果类中定义 N 个方法,是不是意味着同时也要定义 N 个异常处理的方法呢,答案是否定的。Hystrix 还提供了 @DefaultProperties 统一处理请求熔断,在该注解上设置 defaultFallback 属性值,即熔断开启后要执行的方法。@DefaultProperties(defaultFallback = "defaultSelect") @Service public class UserServiceImpl implements IUserService { @Autowired private ApiFeign apiFeign; @HystrixCommand @Override public User select(Integer uId) { return apiFeign.select(uId); } public User defaultSelect() { User user = new User(); user.setuId(-1); user.setuName("没有数据"); return user; } }注意:defaultFallback 定义的方法必须是无参的。四、服务降级实战4.1定义 Fallback@Component public class UserClientFallbackFactory implements FallbackFactory<ApiFeign> { @Override public ApiFeign create(Throwable throwable) { return new ApiFeign() { @Override public User select(Integer uId) { System.out.println(uId); User user = new User(); user.setuName("哈哈哈哈哈"); return user; } }; } }使用单独的类处理异常逻辑,当与服务端无法正常通信时调用此类中的方法返回结果4.2修改 Feign 客户端将上边定义好的 FallbackFactory 设置到 @FeignClient 注解上:@FeignClient(value = "PROVIDER",fallbackFactory = UserClientFallbackFactory.class) public interface ApiFeign { @RequestMapping(value ="/user/get/" ) User select(@RequestParam("uId") Integer uId); }4.3开启服务降级功能server: port: 80 spring: application: name: api eureka: client: # register-with-eureka: false # 不向注册中心注册自己 fetch-registry: true # 是否检索服务 service-url: defaultZone: http://localhost:9000/eureka/ # 注册中心访问地址 feign: hystrix: enabled: true #开启服务降级功能 client: config: default: connect-timeout: 10000 read-timeout: 20000 service-test: connect-timeout: 10000 read-timeout: 200004.4去掉 @HystrixCommand 配置//@DefaultProperties(defaultFallback = "defaultSelect") @Service public class UserServiceImpl implements IUserService { @Autowired private ApiFeign apiFeign; // @HystrixCommand @Override public User select(Integer uId) { System.out.println(uId); return apiFeign.select(uId); } public User defaultSelect() { User user = new User(); user.setuId(-1); user.setuName("没有数据"); return user; } }4.5测试在启动类上加 FallbackFactory 类的包扫描目录Postman测试:请求一个没有的用户ID 5.仪表盘除了服务熔断、降级的功能外,Hystrix 还提供了准及时的调用监控。 Hystrix 会持续地记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表和图形方式展示给用户。5.1 配置被监控方API项目中:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>修改 application.ymlmanagement: endpoints: web: exposure: include: "*"5.2 配置监控方创建一个名为dashboard 的项目,添加依赖<!-- hystrix-dashboard --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency>新建 application.ymlserver: port: 3333 spring: application: name: Hystrix-Dashboard开启监控功能在启动类上添加 @EnableHystrixDashboard 注解@EnableHystrixDashboard @SpringBootApplication public class DashboardApplication { public static void main(String[] args) { SpringApplication.run(DashboardApplication.class, args); } }启动,浏览器访问: http://127.0.0.1:3333/hystrix 监控设置# 需要监控的服务地址 http://localhost:80/actuator/hystrix.stream delay: 请求间隔时间 title: 监控名称 点击 monitor stream 批量访问 order-server 服务的下单接口。 刚开始进来如果没有调用接口,界面是这样的:调用接口之后: 六案例源码demo
2021年12月08日
289 阅读
0 评论
0 点赞
2021-12-08
Spring Cloud 入门 之 Zuul(五)附源码
一、前言随着业务的扩展,微服务会不对增加,相应的其对外开放的 API 接口也势必增多,这不利于前端的调用以及不同场景下数据的返回,因此,我们通常都需要设计一个 API 网关作为一个统一的 API 入口,来组合一个或多个内部 API。二、简单介绍2.1 API 网关使用场景黑白名单: 实现通过 IP 地址控制请求的访问 日志:实现访问日志的记录,进而实现日志分析,处理性能指标等 协议适配:实现通信协议的校验、适配转换的功能 身份认证:对请求进行身份认证 计流限流:可以设计限流规则,记录访问流量 路由:将请求进行内部(服务)转发 2.2 API 网关的实现业界常用的 API 网关有很多方式,如:Spring Cloud Zuul、 Nginx、Tyk、Kong。本篇介绍的对象正是 Spring Cloud Zuul。Zuul 是 Netflix 公司开源的一个 API 网关组件,提供了认证、鉴权、限流、动态路由、监控、弹性、安全、负载均衡、协助单点压测等边缘服务的框架。Spring Cloud Zuul 是基于 Netflix Zuul 的微服务路由和过滤器的解决方案,也用于实现 API 网关。其中,路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入门的基础。而过滤功能是负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。Spring Cloud Zuul 和 Eureka 进行整合时,Zuul 将自身注册到 Eureka 服务中,同时从 Eureka 中获取其他微服务信息,以便请求可以准确的通过 Zuul 转发到具体微服务上。三、实战演练本次测试案例基于之前发表的文章中介绍的案例进行演示,不清楚的读者请先转移至Spring Cloud 入门之 Hystrix 进行浏览。服务实例端口描述common-公用的,如:实体类eureka-server9000注册中心(Eureka 服务端)provider01-server8081用户服务(Eureka 客户端)provider02-server8082用户服务(Eureka 客户端)api80消费服务(Eureka 客户端)创建一个为名 gateway-server 的 Spring Boot 项目。3.1添加依赖<!-- eureka 客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.1.0.RELEASE</version> </dependency> <!-- zuul 网关 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> <version>2.1.0.RELEASE</version> </dependency>3.2配置文件server: port: 5555 spring: application: name: gateway eureka: instance: instance-id: gateway-5555 prefer-ip-address: true client: service-url: defaultZone: http://localhost:9000/eureka/ # 注册中心访问地址3.3 启动 Zuul在启动类上添加 @EnableZuulProxy 注解.@EnableZuulProxy @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }依次启动上面项目 首先我们先调用api服务项目的地址:http://127.0.0.1/user/get/1之后再修改成访问 gateway-server 项目的请求地址:http://127.0.0.1:5555/api/user/get/1最终的相应结果都一样。http://127.0.0.1:5555/api/user/get/1中的api是在Eureka 上注册的消费服务3.4 zuul 常用配置修改路由:zuul: sensitive-headers: # 全局忽略敏感头,即允许接收 cookie 等请求头信息 routes: javaj: # 任意名字,保证唯一即可 path: /javaj/** # 自定义,真正用到的请求地址 service-id: api # 路由到的目标服务名称将消费服务的路由名称改成 javaj。使用 Postman 请求下单接口,运行结果:请求成功禁用路由:zuul: ignored-patterns: - /api/user/**http://127.0.0.1:5555/api/user/get/1 无法正常路由到消费服务,返回404错误路由加前缀:zuul: prefix: /open所有请求中的path需要添加前缀/open;如http://127.0.0.1:5555/javaj/user/get/1 要改为 http://127.0.0.1:5555/open/javaj/user/get/1设置敏感头:zuul: sensitive-headers: # 设置全局敏感头,如果为空,表示接收所有敏感头信息 或 zuul: routes: javaj: # 任意名字,保证唯一即可 path: /javaj/** # 自定义,真正用到的请求地址 service-id: api# 路由到的目标服务名称 sensitive-headers: # 针对 /javaj/ 的请求设置敏感头信息四、Zuul 自定义过滤器Zuul 的核心技术就是过滤器,该框架提供了 ZuulFilter 接口让开发者可以自定义过滤规则。我们以身份检验为例,自定义 ZuulFilter 过滤器实现该功能。4.1 创建用户服务新建名为 user-server 的项目。添加依赖:<dependency> <groupId>com.common</groupId> <artifactId>common</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!-- eureka 客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.1.0.RELEASE</version> </dependency>application.yml:server: port: 8100 spring: application: name: USER eureka: instance: instance-id: user-api-8100 prefer-ip-address: true # 访问路径可以显示 IP client: service-url: defaultZone: http://localhost:9000/eureka/ # 注册中心访问地址登录接口:@RestController @RequestMapping("/user") public class LoginController { @PostMapping("/login") public AjaxResult login(String username, String password, HttpServletResponse response) { if ("admin".equals(username) && "admin".equals(password)) { // 模拟生成 token,实际开发中 token 应存放在数据库或缓存中 String token = "123456"; Cookie cookie = new Cookie("token", token); cookie.setPath("/"); cookie.setMaxAge(60 * 10); response.addCookie(cookie); return AjaxResult.success(); } return AjaxResult.error(401, "账号或密码错误"); } }user-server 启动类:@EnableEurekaClient @SpringBootApplication public class UserApplication { public static void main(String[] args) { SpringApplication.run(UserApplication.class, args); } }4.2 创建 ZuulFilter 过滤器在 gateway-server 项目中,新建一个过滤器,需要继承 ZuulFilter 类:@Component public class AuthenticationFilter extends ZuulFilter { /** * 是否开启过滤 */ @Override public boolean shouldFilter() { RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); boolean flag = request.getRequestURI().contains("/login"); // 如果是登录请求不进行过滤 if (flag) { System.out.println("========不执行 zuul 过滤方法======="); } else { System.out.println("========执行 zuul 过滤方法======="); } return !flag; } /** * 过滤器执行内容 */ @Override public Object run() throws ZuulException { RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); String token = request.getParameter("token"); // 此处模拟获取数据库或缓存中的 token String dbToken = "123456"; // 此处简单检验 token if (token == null || "".equals(token) || !dbToken.equals(token)) { context.setSendZuulResponse(false); context.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); } return null; } /** * 过滤器类型 */ @Override public String filterType() { return "pre"; } /** * 过滤器执行顺序 */ @Override public int filterOrder() { return 0; } }其中,filterType 有 4 种类型:pre: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。 routing:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用 Apache HttpClient 或 Netfilx Ribbon 请求微服务。 post:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。 error:在其他阶段发生错误时执行该过滤器。其过滤顺序如下图:4.3 测试过滤器运行所有项目,测试操作步骤如下:请求用户服务的登录接口(http://127.0.0.1:5555/open/user/user/login?username=admin&password=admin),请求不执行 zuul 过滤方法,并且请求响应返回的 cookie 包含 token 请求消费服务的接口(http://127.0.0.1:5555/open/javaj/user/get/1),但不携带 token,请求需要执行 zuul 过滤方法,请求响应 401 权限不足 请求消费服务的接口(http://127.0.0.1:5555/open/javaj/user/get/1),携带之前登录接口返回的 token,请求需要执行 zuul 过滤方法,校验通过后路由到消费服务执行之后的操作 五、案例源码源码
2021年12月08日
282 阅读
0 评论
0 点赞
2021-12-08
Spring Boot 整合 ActiveMQ
《ActiveMQ安装》一、通信模式1.点对点(queue)一个消息只能被一个服务接收消息一旦被消费,就会消失如果没有被消费,就会一直等待,直到被消费多个服务监听同一个消费空间,先到先得 2.发布/订阅模式(topic)一个消息可以被多个服务接收订阅一个主题的消费者,只能消费自它订阅之后发布的消息。消费端如果在生产端发送消息之后启动,是接收不到消息的,除非生产端对消息进行了持久化(例如广播,只有当时听到的人能听到信息) 二、整合2.1 添加依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency> <!-- 如果需要配置连接池,添加如下依赖 --> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-pool</artifactId> </dependency>2.2添加配置spring: activemq: broker-url: tcp://127.0.0.1:61616 user: admin password: admin pool: enabled: false #表示关闭连接池 max-connections: 50此处 spring.activemq.pool.enabled=false,表示关闭连接池。2.3 编码配置类:负责创建队列和主题。import org.apache.activemq.command.ActiveMQQueue; import org.apache.activemq.command.ActiveMQTopic; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.jms.Queue; import javax.jms.Topic; @Configuration public class JmsConfirguration { public static final String QUEUE_NAME = "activemq_queue"; public static final String TOPIC_NAME = "activemq_topic"; @Bean public Queue queue() { return new ActiveMQQueue(QUEUE_NAME); } @Bean public Topic topic() { return new ActiveMQTopic(TOPIC_NAME); } }消息生产者:import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.stereotype.Component; import javax.jms.Queue; import javax.jms.Topic; /** * 消息生产者 */ @Component public class JmsSender { @Autowired private Queue queue; @Autowired private Topic topic; @Autowired private JmsMessagingTemplate jmsTemplate; public void sendByQueue(String message) { this.jmsTemplate.convertAndSend(queue, message); } public void sendByTopic(String message) { this.jmsTemplate.convertAndSend(topic, message); } }消息消费者:消息消费者使用 @JmsListener 注解监听消息。import org.springframework.context.annotation.Bean; import org.springframework.jms.annotation.JmsListener; import org.springframework.jms.config.DefaultJmsListenerContainerFactory; import org.springframework.jms.config.JmsListenerContainerFactory; import org.springframework.stereotype.Component; import javax.jms.ConnectionFactory; /** * 消息消费者 */ @Component public class JmsReceiver { //需要给topic定义独立的JmsListenerContainer @Bean public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) { DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory(); bean.setPubSubDomain(true); bean.setConnectionFactory(activeMQConnectionFactory); return bean; } @JmsListener(destination = JmsConfirguration.QUEUE_NAME) public void receiveByQueue1(String message) { System.out.println("接收队列消息1:" + message); } @JmsListener(destination = JmsConfirguration.QUEUE_NAME) public void receiveByQueue2(String message) { System.out.println("接收队列消息2:" + message); } @JmsListener(destination = JmsConfirguration.TOPIC_NAME , containerFactory="jmsListenerContainerTopic") public void receiveByTopic1(String message) { System.out.println("接收主题消息1:" + message); } @JmsListener(destination = JmsConfirguration.TOPIC_NAME, containerFactory="jmsListenerContainerTopic") public void receiveByTopic2(String message) { System.out.println("接收主题消息2:" + message); } }2.4测试@RunWith(SpringRunner.class) @SpringBootTest public class ActivemqApplicationTests { @Autowired private JmsSender sender; @Test public void testSendByQueue() { for (int i = 0; i < 10; i++) { this.sender.sendByQueue("发送队列消息: " + i); } } @Test public void testSendByTopic() { for (int i = 0; i < 10; i++) { this.sender.sendByTopic("发送主题消息: " + i); } } }2.4.1 queue测试首先注释 receiveByQueue2,运行结果如下:查看是否消费了放开注释 receiveByQueue2,运行结果如下:一个生产者,两个消费者的情况如下,谁先拿到谁先使用。 2.4.2 topic测试首先注释 receiveByTopic2,运行结果如下:接着我们把receiveByTopic2注释取消掉,运行结果如下:可以看到订阅一个主题的多个消费者,都能收到订阅后发布的消息 三、一些简单常用的应用场景3.1发送邮件 最经典的就是当用户注册时,我们就需要用activeMQ来做为中间件,当用户注册后,我门把用户的邮箱号和验证码等信息通过activeMQ的生产端发送到activeMQ的消息队列中,而一旦消息队列中出现了数据,我们的邮件模块通过实时的监控activeMQ的消息队列就能通过消费端获取到这个数据,染回邮件模块就会自行的去对数据进行解析,给用户发送邮件3.2发送短信 原理同发送邮件相同3.3同步索引库 为了缓解数据库的压力,我们把经常被调用的数据放入索引库中,当有请求查询时,我们会先去查询索引库,如果索引库内有数据,那么我们就不用就数据库进行查询,这样就能大大的减轻服务器的压力,可是随之而来的一个问题是,假如我们服务器内的数据已经发生了改变,而浏览用户查询数据时,因为索引库中已经有数据了,那么这样一来数据库与索引库的数据就不一致了,那么怎么解决这个问题呢?我们想到了通过用activeMQ来监听数据库的操作来实现数据库与索引库的数据同步,当后台管理员或房产经纪人对数据库的数据进行了增删改的操作时,我们通过activeMQ监听到了数据的改变,获取到被修改的数据的id,然后在另一个服务模块中通过这个数据的id去数据库先查询一把,然后根据查询结果进行判断,再去做索引库的数据同步。打个比方,如果查询结果返回的是空,就说明商品已经被删除,那么我们就可以根据数据的id去把索引库中的数据也一并删除了。4.同步静态页面 此原理同上一个同步索引库是一个原理,目的都是为了减缓服务器的压力,我们经过数据分析发现,其实我们的一些商品详情页面的数据其实都是大同小异的,完全可以通过freemarker页面静态化的模块加上后台查询出的数据拼装成一个静态页面,而这些数据从哪来呢?我们经过讨论和研究,最后一致认为还是放在缓冲中比较好,这样一来就能大大的减轻了数据 库的压力,而另一个好处是,由于页面是纯静态页面,所以页面上的数据都是死数据,这样一来就不用像JSP动态页面那样需要和后台数据库有大量的数据交互,可以最大化的降低服务器的压力,其实这个技术已经有很多大型公司在使用了,比如淘宝,京东,网易等,我们要是细心一些就会发现,他们的页面其实就都是HTML格式的静态页面。
2021年12月08日
461 阅读
0 评论
0 点赞
2021-12-08
IDEA SpringBoot多模块开发
测试项目整体结构:1.创建父项目(测试)使用IDEA创建springboot父项目下一步:2.创建公共子模块(测试)项目右键2.1修改该子项目comet-common的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"> <parent> <artifactId>comet</artifactId> <groupId>com.comet</groupId> <version>1.0.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>comet-common</artifactId> <description> common通用工具 </description> <dependencies> <!-- Spring框架基本的核心工具 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- SpringWeb模块 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <!--Shiro核心框架 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> </dependency> <!-- pagehelper 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> </dependency> <!-- 自定义验证注解 --> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> </dependency> <!--常用工具类 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <!-- JSON工具类 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- 阿里JSON解析器 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> <!-- io常用工具类 --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> </dependency> <!-- 文件上传工具类 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> </dependency> <!-- HTML解析器 --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> </dependency> <!-- excel工具 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> </dependency> <!-- yml解析器 --> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> </dependency> <!-- servlet包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> </dependencies></project> 整体目录结构及测试类:2.2修改父项目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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.comet</groupId> <artifactId>comet</artifactId> <packaging>pom</packaging> <version>1.0.0</version> <modules> <module>comet-common</module> </modules> <name>comet</name> <description>彗星管理系统</description> <properties> <comet.version>1.0.0</comet.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <shiro.version>1.4.1</shiro.version> <thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version> <mybatis.boot.version>1.3.2</mybatis.boot.version> <druid.version>1.1.14</druid.version> <bitwalker.version>1.19</bitwalker.version> <kaptcha.version>2.3.2</kaptcha.version> <swagger.version>2.9.2</swagger.version> <pagehelper.boot.version>1.2.5</pagehelper.boot.version> <fastjson.version>1.2.47</fastjson.version> <oshi.version>3.9.1</oshi.version> <commons.io.version>2.5</commons.io.version> <commons.fileupload.version>1.3.3</commons.fileupload.version> <jsoup.version>1.11.3</jsoup.version> <poi.version>3.17</poi.version> <velocity.version>1.7</velocity.version> </properties> <!-- 依赖声明 --> <dependencyManagement> <dependencies> <!-- 公共模块--> <dependency> <groupId>com.comet</groupId> <artifactId>comet-common</artifactId> <version>${comet.version}</version> </dependency> <!-- SpringBoot的依赖配置--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.1.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--阿里数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <!--验证码 --> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>${kaptcha.version}</version> </dependency> <!--Shiro核心框架 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>${shiro.version}</version> </dependency> <!-- Shiro使用Srping框架 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version> </dependency> <!-- Shiro使用EhCache缓存框架 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>${shiro.version}</version> </dependency> <!-- thymeleaf模板引擎和shiro框架的整合 --> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>${thymeleaf.extras.shiro.version}</version> </dependency> <!-- 解析客户端操作系统、浏览器等 --> <dependency> <groupId>eu.bitwalker</groupId> <artifactId>UserAgentUtils</artifactId> <version>${bitwalker.version}</version> </dependency> <!-- pagehelper 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>${pagehelper.boot.version}</version> </dependency> <!-- 获取系统信息 --> <dependency> <groupId>com.github.oshi</groupId> <artifactId>oshi-core</artifactId> <version>${oshi.version}</version> </dependency> <!-- swagger2--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> <exclusions> <exclusion> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> </exclusion> <exclusion> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> </exclusion> </exclusions> </dependency> <!-- swagger2-UI--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <!--io常用工具类 --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>${commons.io.version}</version> </dependency> <!--文件上传工具类 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons.fileupload.version}</version> </dependency> <!-- HTML解析器 --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>${jsoup.version}</version> </dependency> <!-- excel工具 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>${poi.version}</version> </dependency> <!--velocity代码生成使用模板 --> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>${velocity.version}</version> </dependency> <!-- 阿里JSON解析器 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> <encoding>${project.build.sourceEncoding}</encoding> </configuration> </plugin> </plugins> </build></project> 3.创建定时任务子项目(测试)和创建公共模块同样步骤:3.1修改comet-quartz项目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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.comet</groupId> <artifactId>comet</artifactId> <version>1.0.0</version> <relativePath/> </parent> <artifactId>comet-quartz</artifactId> <description> quartz定时任务</description> <dependencies> <dependency> <groupId>com.comet</groupId> <artifactId>comet-common</artifactId> </dependency> </dependencies></project> 3.2修改父项目pom.xml做相应添加 整体结构及测试类: 4.创建启动项目步骤基本一致,注意以下几点:4.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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.comet</groupId> <artifactId>comet</artifactId> <version>1.0.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>comet-admin</artifactId> <packaging>war</packaging> <description> web服务入口 </description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--定时任务--> <dependency> <groupId>com.comet</groupId> <artifactId>comet-quartz</artifactId> <version>${comet.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 --> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build></project> 4.2修改父项目pom.xml做相应添加4.3修改父项目application.yml项目中application.yml只在启动项目存在# 项目相关配置 comet: # 名称 name: comet # 版本 version: 1.0.0 # 版权年份 copyrightYear: 2019 # 开发环境配置 server: # 服务器的HTTP端口,默认为80 port: 80 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # tomcat最大线程数,默认为200 max-threads: 800 # Tomcat启动初始化的线程数,默认值25 min-spare-threads: 30 4.4启动项目整体结构图中标注为在启动类上取消数据源自动配置,避免启动时报错,因为没有配置数据源5.运行测试运行:comet-admin访问:http://127.0.0.1/结果:数据来源:.comet-commoncomet-quartz
2021年12月08日
314 阅读
0 评论
0 点赞
2021-12-08
Xmind8安装破解教程
Xmind8 Pro安装教程(Win+Mac)xmind是一款优秀的思维导图制作软件,这一点相信不用太多解释,从大家搜遍网络找破解/激活版本就能够看得出来了哈!网上关于激活的方法有很多,自己也整理了一下,此篇内容涵盖win和mac版本的激活步骤(其实都是一样的)。自己试过可以激活截止2017年09月16日的xmind8的up4版本,以后的版本没有试过。下面就以xmind8的up4版本为例进行描述:1、官网下载安装客户端并安装Win:http://dl2.xmind.cn/xmind-8-update4-windows.exeMac:http://dl2.xmind.cn/xmind-8-update4-macosx.dmg2、下载补丁百度链接:https://pan.baidu.com/s/1E4wUovM1R4r6GweiNrtvzQ提取密码:5ue43、将补丁复制到安装路径的根目录 (根据自己需要选择panfu)Win:如:C:\Program Files (x86)\XMindMac:应用程序-xmind-右键显示包内容-Contents 4、找到安装目录中的xmind.iniWin:安装路径C:\Program Files (x86)\XMind8,xmind.ini文件Mac:应用程序-xmind-右键显示包内容-Contents-Eclipse,xmind.ini文件5、在 XMind.ini 最后追加代码Win:-javaagent:(你的XMindCrack.jar放置的目录)/XMindCrack.jar(注意:写的路径是你下载的XMindCrack.jar文件的路径)Mac:选择使用文本方式打开,最后面追加代码:-javaagent:../XMindCrack.jar6、找到hosts文件Win:C:\Windows\System32\drivers\etcMac:桌面顶部菜单栏,前往-前往文件夹,输入代码:/private/etc/ hosts文件目录 ->C:\Windows\System32\drivers\etc7、在hosts里面追加代码(修改时需要注意,文件原本是只读,要把只读去了)Win:127.0.0.1 www.xmind.net 回车Mac:127.0.0.1 www.xmind.net 回车(直接修改会提示无权修改,需要先将hosts文件复制到桌面,在桌面修改,然后在粘贴回去,覆盖原文件)8、打开xmind 8 输入邮箱和序列号帮助->序列号邮箱:x@iroader.me序列号:XAka34A2rVRYJ4XBIU35UZMUEEF64CMMIYZCK2FZZUQNODEKUHGJLFMSLIQMQUCUBXRENLK6NZL37JXP4PZXQFILMQ2RG5R7G4QNDO3PSOEUBOCDRYSSXZGRARV6MGA33TN2AMUBHEL4FXMWYTTJDEINJXUAV4BAYKBDCZQWVF3LWYXSDCXY546U3NBGOI3ZPAP2SO3CSQFNB7VVIY123456789012345现在关闭xmind并重新打开,就可以看到显示为已激活状态了,各种pro的功能都能够正常使用
2021年12月08日
752 阅读
0 评论
0 点赞
2021-12-08
com.microsoft.sqlserver.jdbc.SQLServerException: 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。
连接sqlserver2005时报这个错,JDK使用的是1.8找到Windows下 java安装路径,以下是本人安装路径C:softwareJavajdk1.8.0_201jrelibsecurity修改java.security改为 去掉 , 3DES_EDE_CBC ,启用旧的算法。然后就可以连接了
2021年12月08日
958 阅读
0 评论
0 点赞
2021-12-08
java环境变量配置(java和javac命令可用)
第一步第二步在系统变量中新建JAVA_HOME第三步**如果有CLASSPATH则在此变量里添加,没有则创建CLASSPATH变量在变量里添加.;%JAVA_HOME%libdt.jar;%JAVA_HOME%libtools.jar; 一个符号都不能少**第四步在path变量中添加D:APPJavajdk1.8.0_144bin 红色部位为安装路径注:每次配置为之后记得确定保存操作。重新使用win+r打开命令窗口至于“java -version”显示安装成功,这并不能说明什么。在页面内输入java,回车,如果出来的是这些中文,那说明这是正确的在接下来输入javac,回车,如果出现这些中文,说明是环境变量配好了(java是跨平台的语言,在Windows、Linux等多种操作系统平台上都预装有java的运行环境JRE,在它的bin目录下就有java命令(用于运行Java程序),但没有javac命令(用于编译Java程序)。也就是说,即使你不安装JDK,一样可以使用java命令,但不能直接使用javac,除非安装jdk,并设置path环境变量)
2021年12月08日
254 阅读
0 评论
0 点赞
2021-12-08
Spring Cloud 集成 WebHook
1.配置 WebHook 地址登录 GitHub,点击 GitHub 的 WebHook 菜单,右侧面板中 Payload URL 填写 <配置中心 url>/actuator/bus-refresh, Content-type 选择 applicaton/json,保存即可。因为需要用到外网,这里使用natapp外网穿透做外网映射设置 WebHook 操作: 2.修改config-server添加:import org.springframework.stereotype.Component;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import java.io.ByteArrayInputStream;import java.io.IOException;@Componentpublic class WebHookFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String url = new String(httpServletRequest.getRequestURI()); // 只过滤 /actuator/bus-refresh 请求 if (!url.endsWith("/actuator/bus-refresh")) { chain.doFilter(request, response); return; } // 使用 HttpServletRequest 包装原始请求达到修改 post 请求中 body 内容的目的 CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest); chain.doFilter(requestWrapper, response); } @Override public void destroy() { } private class CustometRequestWrapper extends HttpServletRequestWrapper { public CustometRequestWrapper(HttpServletRequest request) { super(request); } @Override public ServletInputStream getInputStream() throws IOException { byte[] bytes = new byte[0]; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); return new ServletInputStream() { @Override public boolean isFinished() { return byteArrayInputStream.read() == -1 ? true : false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() throws IOException { return byteArrayInputStream.read(); } }; } } } 3.测试 完成以上配置后,重启项目 修改github文件 再执行 http://localhost/test/getConfigInfo 因为网络原因,等几秒钟加载几次就能拉去新的数据了
2021年12月08日
176 阅读
0 评论
0 点赞
2021-12-08
Spring Cloud 整合 Bus(附源码)
一、前言本篇笔者是根据上篇进行修改,若有不懂,转《Spring Cloud 入门 之 Config(六)附源码》了解二、介绍Spring Cloud Bus 是 Spring Cloud 家族中的一个子项目,用于实现微服务之间的通信。它整合 Java 的事件处理机制和消息中间件消息的发送和接受,主要由发送端、接收端和事件组成。针对不同的业务需求,可以设置不同的事件,发送端发送事件,接收端接受相应的事件,并进行相应的处理。三、配置3.1config-server3.1.1添加依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> <version>2.1.0.RELEASE</version> </dependency> 3.1.2 修改 application.yml:添加了 rabbitmq 配置和 management 的配置server: port: 10000spring: application: name: CONFIG cloud: config: server: git: uri: https://github.com/Uncle-LiuY/config.git username: ****** password: ****** rabbitmq: host: 127.0.0.0 port: 5672 username: admin password: admin management: endpoints: web: exposure: include: '*' # 暴露接口 eureka: instance: instance-id: config-api client: service-url: defaultZone: http://localhost:9000/eureka/ # 注册中心访问地址 3.2 api3.2.1 添加依赖; <!-- bus --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> <version>2.1.0.RELEASE</version> </dependency> 3.2.2 修改 bootstrap.yml:添加 rabbitmq 配置spring: application: name: api cloud: config: discovery: enabled: true service-id: CONFIG # config-server 在注册中心的名称 profile: dev # 指定配置文件的环境 rabbitmq: host: 127.0.0.0 port: 5672 username: admin password: admin eureka: client: service-url: defaultZone: http://localhost:9000/eureka/ # 注册中心访问地址 3.2.3 修改TestController添加 @RefreshScope 注解,顺序一定不能错@RestController@RequestMapping("/test")@RefreshScopepublic class TestController { @Value("${env}") private String env; // 从配置中心获取 @RequestMapping("/getConfigInfo") public String getConfigInfo() { return env; } } 4.测试依次启动 eureka-server、config-server、api4.1 参数原来的值:4.2 修改文件值为:dev1234.3 POST执行http://localhost:10000/actuator/bus-refresh间隔几秒再执行 http://localhost/test/getConfigInfo 就会发现获取的值变了。5.项目地址源码下载 到这里还是需要手动调用才能更新,下篇《Spring Cloud 集成 WebHook》讲解在线更新
2021年12月08日
182 阅读
0 评论
0 点赞
2021-12-08
Spring Boot 整合Shiro(一)登录认证和授权(附源码)
shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。主要功能三个核心组件:Subject, SecurityManager 和 Realms.Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。 Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。 SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。 Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。 从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。 Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。 1.项目版本Spring Boot 2.x shiro 1.3.21.1导入依赖 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency>2.类配置2.1 ShiroConfig相当于之前的xml配置,包括:过滤的文件和权限,密码加密的算法,其用注解等相关功能。import com.shiro.realm.CustomRealm; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import java.util.LinkedHashMap; import java.util.Map; /** * 过滤的文件和权限,密码加密的算法,其用注解等相关功能 */ @Configuration public class ShiroConfig { @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // Shiro的核心安全接口,这个属性是必须的 shiroFilterFactoryBean.setSecurityManager(securityManager); // 身份认证失败,则跳转到登录页面的配置 shiroFilterFactoryBean.setLoginUrl("/login"); // 权限认证失败,则跳转到指定页面 shiroFilterFactoryBean.setUnauthorizedUrl("/notRole"); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> filterChainDefinitionMap.put("/webjars/**", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/", "anon"); filterChainDefinitionMap.put("/front/**", "anon"); filterChainDefinitionMap.put("/api/**", "anon"); filterChainDefinitionMap.put("/admin/**", "authc"); filterChainDefinitionMap.put("/user/**", "authc"); //主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证 filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager(); defaultSecurityManager.setRealm(customRealm()); return defaultSecurityManager; } @Bean public CustomRealm customRealm() { CustomRealm customRealm = new CustomRealm(); return customRealm; } }2.1.1 shiroFilter方法shiro的过滤器,可以设置登录页面(setLoginUrl)、权限不足跳转页面(setUnauthorizedUrl)、具体某些页面的权限控制或者身份认证。注意:这里是需要设置SecurityManager(setSecurityManager)。默认的过滤器还有:anno、authc、authcBasic、logout、noSessionCreation、perms、port、rest、roles、ssl、user过滤器。具体的大家可以查看package org.apache.shiro.web.filter.mgt.DefaultFilter。这个类,常用的也就authc、anno。2.1.2 securityManager 方法public interface SecurityManager extends Authenticator, Authorizer, SessionManager { //登录方法 Subject login(Subject subject, AuthenticationToken authenticationToken) throws AuthenticationException; //注销方法 void logout(Subject subject); //创建subject Subject createSubject(SubjectContext context); }由于项目是一个web项目,所以我们使用的是DefaultWebSecurityManager ,然后设置自己的Realm。2.1.3 CustomRealm 方法将 customRealm的实例化交给spring去管理,当然这里也可以利用注解的方式去注入 2.2 CustomRealm自定义的CustomRealm继承AuthorizingRealm。并且重写父类中的doGetAuthorizationInfo(权限相关)、doGetAuthenticationInfo(身份认证)这两个方法。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.subject.PrincipalCollection; import java.util.HashSet; import java.util.Set; /** * */ public class CustomRealm extends AuthorizingRealm { /** * 权限相关 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //账户 String username = (String) SecurityUtils.getSubject().getPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //从数据库获取账户权限信息 Set<String> stringSet = new HashSet<>(); stringSet.add("user:show"); stringSet.add("user:admin"); info.setStringPermissions(stringSet); return info; } /** * 身份认证 * 这里可以注入userService,为了方便演示直接写死账户和密码 * 获取即将需要认证的信息 * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("-------身份认证方法--------"); String userName = (String) authenticationToken.getPrincipal(); String userPwd = new String((char[]) authenticationToken.getCredentials()); System.out.println(userPwd); //根据用户名从数据库获取密码 String password = "123"; if (userName == null) { throw new AccountException("用户名不正确"); } else if (!userPwd.equals(password )) { throw new AccountException("密码不正确"); } return new SimpleAuthenticationInfo(userName, password,getName()); } } 自定义的Realm类继承AuthorizingRealm类,并且重载doGetAuthorizationInfo和doGetAuthenticationInfo两个方法。doGetAuthorizationInfo: 权限认证,即登录过后,每个身份不一定,对应的所能看的页面也不一样。doGetAuthenticationInfo:身份认证。即登录通过账号和密码验证登陆人的身份信息。 3.实战演练3.1 登陆认证创建LoginControllerimport org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.subject.Subject; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping public class LoginController { @RequestMapping(value = "/login", method = RequestMethod.GET) public String defaultLogin() { return "首页"; } @RequestMapping(value = "/login", method = RequestMethod.POST) public String login(@RequestParam("username") String username, @RequestParam("password") String password) { // 从SecurityUtils里边创建一个 subject Subject subject = SecurityUtils.getSubject(); // 在认证提交前准备 token(令牌) UsernamePasswordToken token = new UsernamePasswordToken(username, password); // 执行认证登陆 try { subject.login(token); } catch (UnknownAccountException uae) { return "未知账户"; } catch (IncorrectCredentialsException ice) { return "密码不正确"; } catch (LockedAccountException lae) { return "账户已锁定"; } catch (ExcessiveAttemptsException eae) { return "用户名或密码错误次数过多"; } catch (AuthenticationException ae) { return "用户名或密码不正确!"; } if (subject.isAuthenticated()) { return "登录成功"; } else { token.clear(); return "登录失败"; } } }测试结果:3.2 权限测试在ShiroConfig添加如下代码,开启注解。@Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * * * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 * * * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能 * * @return */ @Bean @DependsOn({"lifecycleBeanPostProcessor"}) public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; }创建UserControllerimport com.shiro.utils.BaseController; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/user") @RestController public class UserController extends BaseController { @RequiresPermissions("user:list") @RequestMapping("/show") public String showUser() { return "张三信息"; } }再创建 BaseController,UserController继承BaseController,用于捕获没有权限时的异常import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.authz.UnauthorizedException; import org.springframework.web.bind.annotation.ExceptionHandler; import java.util.HashMap; import java.util.Map; public class BaseController { /** * 捕获没有权限时的异常 * @return */ @ExceptionHandler({ UnauthorizedException.class, AuthorizationException.class }) public Map<String, Object> authorizationException(){ Map<String, Object> map = new HashMap<String, Object>(); System.out.println("没有权限"); map.put("success", true); map.put("msg", "当前用户没有此权限"); return map; } } 运行测试,先执行 http://127.0.0.1:8080/login,再执行http://127.0.0.1:8080/user/show:方法上是 @RequiresPermissions("user:list"),之前在customRealm只添加了两个所以没有权限现在把方法上的改为@RequiresPermissions("user:show")测试现在就有权限访问数据啦4.项目源码项目地址 下篇介绍《Spring Boot 整合Shiro(二)加密登录与密码加盐处理》
2021年12月08日
425 阅读
0 评论
0 点赞
1
...
18
19
20