文章目录

  • SpringBoot
      • 感谢秦老师 指路: [秦老师](https://www.bilibili.com/video/BV1PE411i7CV)
    • 什么是Spring
    • Spring是如何简化Java开发的
    • 什么 SpringBoot
  • 微服务
    • 什么是微服务?
    • 单体应用架构
    • 微服务架构
    • 如何构建微服务
  • 第一个SpringBoot程序
  • 自动装配原理初探
    • pom.xml
    • 启动器:
    • 主程序
    • 注解
    • @Conditional扩展注解
    • 结论:
    • SpringApplication
    • springboot启动流程
    • 关于springboot,谈谈你的理解
  • SpringBoot配置
    • 配置文件
    • YAML
    • YAML语法
      • 基本语法
      • 值的写法
      • 松散绑定
      • 结论
    • JSR303校验
    • 配置文件位置优先级
    • 为什么可以完成自动配置
    • 查看哪些配置类生效
  • SpringBoot Web开发
    • 静态资源
      • 什么是webjars?
      • 静态资源目录
      • 总结
    • 首页如何定制
    • 模板引擎
      • 导入依赖:
      • 使用thymeleaf:
        • 导入约束
        • 表达式
        • 简单测试一下
    • 修改springboot的默认配置
      • 方式一
    • 扩展装配SpringMVC
    • 扩展SpringMVC
      • 为什么?
  • Springboot整合ORM
    • Springboot整合JDBC
      • 简介
      • 引入SQL相关依赖
      • pom依赖
      • 配置信息
      • 测试,默认数据源
      • 测试jdbcTemplate
    • Sringboot整合Druid
      • 简介
      • 导入依赖
      • 配置信息
      • DruidConfig配置类
      • 实现后台监控功能
      • filter
    • Springboot整合Mybatis
      • 引入依赖
      • application.properties(yml也可)
      • 测试
  • SpringSecurity
      • 可以实现的功能
      • 环境引入
      • 简介
      • 引入依赖
      • 官方示例
      • 授权
      • 认证
      • 注销
      • 问题
      • 记住我
  • Shiro
    • 简介
    • 有哪些功能
    • shiro架构(外部)
    • shiro架构(内部)
    • HelloWorld快速实践
      • 新建一个helloshiro工程
      • 配置log4j.properties配置文件
      • shiro.ini配置文件
      • 把QuickStart.java类建好
      • 运行结果
    • Springboot集成shiro
      • 结构
      • pom依赖
      • UserRealm.java
      • ShiroConfig.java
      • Controller
      • 测试页面
    • 整合mybatis
      • application.yml
      • application.properties
      • pojo
      • mapper
      • userMapper.xml
      • Service
      • 改造UserRealm
      • 完善ShiroConfig.java

SpringBoot

感谢秦老师 指路: 秦老师

image-20200518143037005

什么是Spring

Spring是一个开源框架, 2003 年兴起的一个轻量级的gva开发框架,作者: Rod Johnson。
Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。

Spring是如何简化Java开发的

为了降低Java开发的复杂性,Spring采用了以下4种关键策略:

  • 基于POJO的轻量级和最小侵入性编程;
  • 通过IOC,依赖注入(DI)和面向接口实现松耦合;
  • 基于切面(AOP) 和惯例进行声明式编程;
  • 通过切面和模版减少样式代码;

什么 SpringBoot

学过javaweb的同学 就知道,开发-个web应用,从最初开始接触Servlet结合Tomcat,跑出一个Hello Wolrld程序,是要经历特别多的步骤;后来就用了框架Struts,再后来是SpringMVC,到了现在的SpringBoot,过一两年又会有其他web框架出现;不知道你们有没经历过框架不断的演进,然后自己开发项目所有的技术也再不断的变化、改造,反正我是都经历过了,哈哈。言归正传,什么是SpringBoot呢,就是一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框 架的好处,官方说是简化开发,约定大于配置,you can “just run”,能迅速的开发web应用,几行代码开发一个http接口.

所有的技术框架的发展似乎都遵循了-条主线规律:从一个复杂应用场景衍生-种规范框架,人们只需要进行各种配置而不需要自己去实现它,这时候强大的配置功能成了优点;发展到一定程度之后,人们根据实际生产应用情况,选取其中实用功能和设计精华,重构出一些轻量级的框架;之后为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡”约定大于配置”,进而衍生出一些一站式的解决方案。

是的这就是Java企业级应用-> J2EE-> spring-> springboot的过程。
随着Spring不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,违背了最初的理念,甚至人称配置地狱。Spring Boot正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用Spring、更容易的集成各种常用的中间件、开源软件;

Spring Boot基于Spring开发, Spirng Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。SpringBoot以约定大于配置的核心思想,默认帮我们进行了很多设置,多数Spring Boot应用只需要很少的Spring配置。同时它集成了大量常用的第三方库配置(例如Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用,

简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架
Spring Boot 出生名门,从一开始就站在-个比较高的起点,又经过这几年的发展,生态足够完善,Spring Boot 已经当之无愧成为Java 领域最热门的技术。

SpringBoot的主要优点:

  • 为所有的Spring开发者更快的入门
  • 开箱即用,提供各种默认配置来简化项目配置
  • 内嵌式容器简化web项目
  • 没有冗余代码生成和XML配置的要求

Springboot starter官方文档 https://docs.spring.io/spring-boot/docs/2.2.7.RELEASE/reference/html/using-spring-boot.html#using-boot-starter

微服务

什么是微服务?

微服务是-种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系 列小服务的组合;可以通过http的方式进行互通。要说微服务架构,先得说说过去我们的单体应用架构。

单体应用架构

所谓单体应用架构(all in one)是指,我们将一个应用的中的所有应用服务都封装在一个应用中。
无论是ERP、CRM或是其他什么系统,你都把数据库访问,web访问,等等各个功能放到一个war包内。

  • 这样做的好处是,易于开发和测试;也十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
  • 单体应用架构的缺点是,哪怕我要修改一个非常小的地方,我都需要停掉整个服务,重新打包、部署这个应用war包。特别是对于一个大型应用,我们不可能吧所有内容都放在一个应用里面,我们如何维护、如何分I合作都是问题。

微服务架构

image

all in one的架构方式,我们把所有的功能单元放在一个应用里面。然后我们把整个应用部署到服务器上。如果负载能力不行,我们将整个应用进行水平复制,进行扩展,然后在负载均衡。
所谓微服务架构,就是打破之前all in one的架构方式,把每个功能元索独立出来。把独立出来的功能元索的动态组合,需要的功能元索才去拿来组合,需要多一些时 可以整合多个功能元素。所以微服务架构是对功能元索进行复制,而没有对整个应用进行复制。

这样做的好处是:

  1. 节省了调用资源
  2. 每个功能元素的服务都是一个可替换的,可独立升级的软件代码.

如何构建微服务

一个大型系统的微服务架构,就像一个复杂交织的神经网络,每-个神经元就是- -个功能元素,它们各自完成自己的功能,然后通过http相互请求调用。比如一个电商系统,查缓存、连数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被微化了,它们作为一个个微服务共同构建了一个庞大的系统。如果修改其中的一个功能,只需要更新升级其中-个功能服务单元即可。
但是这种庞大的系统架构给部署和运维带来很大的难度。于是,spring为我们带来了构建大型分布式微服务的全套、全程产品:

  • 构建-个个功能独立的微服务应用单元,可以使用springboot, 可以帮我们快速构建一个 应用;
  • 大型分布式网络服务的调用,这部分由spring cloud来完成,实现分布式;
  • 在分布式中间,进行流式数据计算、批处理,我们有spring cloud data flow。
  • spring为我们想清楚了整个从开始构建应用到大型分布式应用全流程方案。

image-20200518145905217

第一个SpringBoot程序

  1. IDEA整合了Springboot,创建项目时选择Spring Initializer创建项目
  2. 在启动类同级目录下建包

image-20200518160335795

  1. 编写controller,加上@RestController注解,就可以不用写@Responsebody了image-20200518160712836
  2. 启动类本身就是spring的一个组件,@SpringbootApplication整合@Springbootconfiguration,再进去是@Configuration,最底层是一个@Componentimage-20200518160904227
  3. pom依赖[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ijOENbH-1590996141553)(upload\image-20200518160954380.png)]
  4. springboot帮我们自动导入的web依赖[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HNmUlrlx-1590996141554)(upload\image-20200518161047662.png)]

主要有四个部分:

  • 项目元数据信息:创建时候输入的Project Metadata部分, 也就是Maven项目的基本元素,包括: groupld、 artifactld、 version、 name、 description等
  • parent:继承spring-boot -starter-parent的依赖管理,控制版本与打包等内容
  • dependencies: 项目具体依赖,这里包含了spring- boot-starter -web用于实现HTTP接口(该依赖中包含了Spring MVC),官网对它的描述是:使用Spring MVC构建Web (包括RESTful) 应用程序的入门者,使用Tomcat作为默认嵌入式容器。spring-boot-starter-test用于编写单元测试的依赖包。更多功能模块的使用我们将在后面逐步展开。
  • build: 构建配置部分。默认使用了spring-boot-maven-plugin,配合spring-boot-starter-parent就可以把Spring Boot应用打包成JAR来直接运行。

自动装配原理初探

pom.xml

  • spring-boot-dependencies :核心依赖在父工程中
  • 我们在写或者引入一些Springboot依赖的时候,不需要指定版本,就是因为有这些版本仓库

启动器:

  • <dependency><groupId>org.springframework.boot</groupId><artifactId>spri ng-boot-starter</artifactId>
    </dependency>
    
  • 启动器:说白了就是springboot的启动场景

  • 比如spring-boot-starter-web,他就会帮我们自动导入web环境所有的依赖

  • springboot会将所有的功能场景,都变成一个个的启动器

  • 如果我们要使用什么功能,就只需要找到对应的启动器就可以了 Starter

主程序

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class HelloworldApplication {public static void main(String[] args) {SpringApplication.run(HelloworldApplication.class, args);}}

注解

  • @SpringBootConfiguration	:	springboot的配置@Configuration	:	spring配置类@Component	:	说明这也是一个spring的组件@EnableAutoConfiguration	:	自动配置@AutoConfigurationPackage   	:	自动配置包@Import({Registrar.class})	:	自动配置'包注册'@Import({AutoConfigurationImportSelector.class})	:	自动配置导入选择   @ComponentScan	:	扫描当前主启动类同级的包//获取所有的配置
    List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
    

    获取候选的配置

    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");return configurations;
    }
    

    META-INF/spring.factories:自动配置的核心文件

    image-20200518164312472

image-20200518164537691

每一个自动装配的类(bean)最终会对应一个properties或者yml配置文件,通过导入的方式进行参数绑定,以达到自动配置的效果.

@Conditional扩展注解

image-20200519143606147

结论:

虽然是有这么多自动配置,但为什么不是每一个都会生效呢?原因是因为在对应的自动配置类中会进行条件判断’@ConditionOnxxx’,条件成立了之后配置才会生效.例如我们导入了web的starter,web相关的配置就会生效,而我们没有开启AOP,那AOP的相关配置就不会生效

  1. springboot在启动的时候,从类路径下META-INF/spring.factories获取指定的值
  2. 将这些自动配置的类导入容器,自动配置就会生效,帮我门进行自动配置
  3. 以前我们需要自动配置的东西,现在springboot帮我门做了
  4. 整个javaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure包下
  5. 他会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器
  6. 容器中也会存在非常多的xxxxAutoConfiguration的文件(@Bean),就是这些类给容器导入了这个场景需要的所有组件

SpringApplication

这个类主要做了以下四个事情

  1. 推断应用的类型是普通的项目还是web项目
  2. 查找并加载所有可用初始化器,设置到initializers属性中
  3. 找出所有的应用程序监听器,设置到listeners属性中
  4. 推断并设置main方法的定义类,找到运行的主类

查看构造器

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.sources = new LinkedHashSet();this.bannerMode = Mode.CONSOLE;this.logStartupInfo = true;this.addCommandLineProperties = true;this.addConversionService = true;this.headless = true;this.registerShutdownHook = true;this.additionalProfiles = new HashSet();this.isCustomEnvironment = false;this.lazyInitialization = false;this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));this.webApplicationType = WebApplicationType.deduceFromClasspath();this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = this.deduceMainApplicationClass();}

springboot启动流程

关于springboot,谈谈你的理解

  • 自动装配
  • run()

SpringBoot配置

配置文件

SpringBoot使用一个全局的配置文件,配置文件名称是固定的

  • application.properties
    • 语法结构: key=value
  • application.yaml
    • 语法结构: key: 空格 value

配置文件的作用: 修改springboot自动配置的默认值,因为springboot在底层都给我们自动配置好了

YAML

YAML是"YAML Ain’t a Markup Language" (YAML不是一 种置标语言)的递归缩写。
在开发的这种语言时,YAML的意思其实是: “Yet Another Markup Language” (仍是一种置标语言)
YAML A Markup Language :是一个标记语言
YAML isnot Markup Language :不是一个标记语言

标记语言

以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,我们来对比下yaml和xml

yaml配置:

server:port: 8080

xml配置:

<server><port>8081<port>
</server>

YAML语法

基本语法

k:(空格) v

以此来表示一对键值对(空格不能省略) ;以空格的缩进来控制层级关系,只要是左边对齐的一-列数据都是同一个层级的。
注意:属性和值的大小写都是十分敏感的。例子:

server:port: 8081path: /hello

值的写法

字面量: 普通的值 [数字,布尔值,字符串]

k: v

字面量直接写在后面就可以,字符串默认不用加上双引号或者单引号;

“” 双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思;

比如: name: “kang \n yuan” 输出: kang 换行 yuan

# k=v
# 对空格的要求十分严格
# 普通的key-value# 可以注入到配置类中
name: deemo# 对象
student:name: deemoage: 21#行内写法
student1: {name: deemo, age: 21}# 数组
pets:- cat- dog- pigpets1: [cat,dog,pig]

@ConfigurationProperties(prefix = “yaml配置中的对象”)

把这个注解加在类上,prefix中写yaml中对应的key,就可以为POJO赋值,注意,k-v和POJO中的字段要一一对应

举一反三

我们可以写一个Mybatis的配置类,然后把配置信息写在yaml配置文件中,加上@ConfigurationProperties注解为Mybatis配置类注入值

如果非要用properties呢?

注意:此时必须是UTF-8

用@PropertiesSource(value=“classpath:xxx.properties”)注解,然后在字段上用@Value注解,写SPEL表达式去除配置文件的值就可以

一点骚操作

image-20200518203737813

松散绑定

image-20200518204539986

结论

  • 配置yml和配置properties都可以获取到值,强烈推荐 yml

  • 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下@value

  • 如果说,我们专门编写了-个JavaBean来和配置文件进行映射,

    就直接使用@configurationProperties,不要犹豫!

JSR303校验

在类上加上@Validated注解开启数据校验

image-20200518205100431

配置文件位置优先级

image-20200518211729626

强制:必须以前缀为application为开头

在生产环境中,我们可以在不同位置进行配置,然后达到覆盖的效果

第一种方式.指定properties配置文件:

image-20200518212503203

image-20200518212616081

第二种方式:yaml配置文件:

image-20200518212925477

为什么可以完成自动配置

在我们这配置文件中能配置的东西,都存在一个固有的规律

xxxAutoConfiguration:默认值 <—注入----- xxxProperties -----绑定— 配置文件

精髓

  1. SpringBoot启动会加载大量的自动配置类

  2. 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;

  3. 我们再来看这个自动配置类中到底配置了哪些组件; (只要我们要用的组件存在在其中,我们就不需要再手动配置了)

  4. 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置
    文件中指定这些属性的值即可;

    xxxxAutoConfigurartion: 自动配置类; 给容器中添加组件
    xxxxProperties: 封装配置文件中相关属性;

查看哪些配置类生效

debug: true

如果配置了log4j之类的,设置log的level为debug,也可以看到

自动配置了并且生效的

image-20200519151115420

大量的没有生效的

image-20200519151158381

没有条件所以没生效的

image-20200519151244998

SpringBoot Web开发

要解决的问题:

  • 导入静态资源
  • 首页
  • jsp, 模板引擎 Thymeleaf
  • 装配扩展SpringMVC
  • 增删改查
  • 拦截器
  • 国际化

静态资源

public void addResourceHandlers(ResourceHandlerRegistry registry) {//第一种方式,webjarsif (!this.resourceProperties.isAddMappings()) {logger.debug("Default resource handling disabled");} else {Duration cachePeriod = this.resourceProperties.getCache().getPeriod();CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();if (!registry.hasMappingForPattern("/webjars/**")) {this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));}//第二种方式,某路径下的静态资源String staticPathPattern = this.mvcProperties.getStaticPathPattern();if (!registry.hasMappingForPattern(staticPathPattern)) {this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern})
.addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));}}
}

什么是webjars?

给静态资源的一层封装,比如jquery,以maven的方式引入的话,会给他包上一层webjars封装

image-20200519161822815

如上述代码 “/webjars/**” 对应的是 “classpath:/META-INF/resources/webjars/” 直接输入/webjars/jquery/3.5.1/jquery.js就可以访问到js文件了

静态资源目录

优先级即为,他们的位置关系 /META-INF/resources/ 优先级最高,最低的是classpath:/public/

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

总结

  1. 在springboot中,我们可以使用以下方式处理静态资源

    • webjars localhost:8080/webjars/
    • public, static, /**, resources localhost:8080/
  2. 优先级: resources > static(默认) > public

首页如何定制

    @Beanpublic WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());return welcomePageHandlerMapping;}private Optional<Resource> getWelcomePage() {String[] locations = WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations());return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();}private Resource getIndexHtml(String location) {return this.resourceLoader.getResource(location + "index.html");}

注意:此处需要模板引擎的支持(Thymeleaf)

image-20200519171514559

模板引擎

模板引擎的作用就是我们来写一个页面模板,比如有些值呢,是动态的,我们写一些表达式。而这些值,从哪来呢,我们来组装一些数据, 我们把这些数据找到。然后把这个模板和这个数据交给我们模板引擎,模板弓|擎按照我们这个数据帮你把这表达式解析、填充到我们指定的位置,然后把这个数据最终生成一个我们想要的内容给我们写出去, 这就是我们这个模板弓|擎,不管是jsp还是其他模板引擎,都是这个思想。只不过呢,就是说不同模板弓|擎之间,他们可能这个语法有点不一样。其他的我就不介绍了,我主要来介绍一下SpringBoot给我们推荐的Thymeleaf模板引擎,这模板引擎呢,是一个高级语言的模板引擎,他的这个语法更简单。而且呢,功能更强大。

image-20200519174530461

默认路径是在classpath下的templates路径下,文件后缀.html

导入依赖:

官方文档 https://docs.spring.io/spring-boot/docs/2.2.7.RELEASE/reference/html/appendix-dependency-versions.html#appendix-dependency-versions

<!--thymeleaf,都是基于3.0以上开发-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.2.7.RELEASE</version>
</dependency>

现在就能跳转成功了

image-20200519174941652

image-20200519174954838

使用thymeleaf:

导入约束

<html xmlns:th="http://www.thymeleaf.org">

表达式

官方文档

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

所有这些功能可以组合和嵌套:

  • Simple expressions:
    • Variable Expressions: ${...}
    • Selection Variable Expressions: *{...}
    • Message Expressions: #{...}
    • Link URL Expressions: @{...}
    • Fragment Expressions: ~{...}
  • Literals
    • Text literals: 'one text', 'Another one!',…
    • Number literals: 0, 34, 3.0, 12.3,…
    • Boolean literals: true, false
    • Null literal: null
    • Literal tokens: one, sometext, main,…
  • Text operations:
    • String concatenation: +
    • Literal substitutions: |The name is ${name}|
  • Arithmetic operations:
    • Binary operators: +, -, *, /, %
    • Minus sign (unary operator): -
  • Boolean operations:
    • Binary operators: and, or
    • Boolean negation (unary operator): !, not
  • Comparisons and equality:
    • Comparators: >, <, >=, <= (gt, lt, ge, le)
    • Equality operators: ==, != (eq, ne)
  • Conditional operators:
    • If-then: (if) ? (then)
    • If-then-else: (if) ? (then) : (else)
    • Default: (value) ?: (defaultvalue)
  • Special tokens:
    • No-Operation: _

简单测试一下

@RequestMapping("/index")public String index(Model model){model.addAttribute("msg","hello thymeleaf");model.addAttribute("users", Arrays.asList("花玲","kk"));return "index";}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>index</title>
</head>
<body><!--所有的html元素都可以被 thymeleaf替换接管:    th:元素名  -->
<div th:text="${msg}"></div>
<!--foreach-->
<h3 th:each="user:${users}" th:text="${user}"></h3></body>
</html>

输出

image-20200519182311041

注意

热部署(Ctrl+F9)需要关闭缓存:

spring.thymeleaf.cache=false

修改springboot的默认配置

方式一

这么多的自动配置,原理都是一样的, 通过这个WebMVC的自动配置原理分析,我们要学会一种学习方式,通过源码探究,得出结论;这个结论一定是属于自己的,而且一通百通。

SpringBoot的底层,大量用到了这些设计细节思想,所以,没事需要多阅读源码!得出结论;

SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean) ,如果有就用用户配置的,如果没有就用自动配置的;如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!

扩展装配SpringMVC

官方文档

https://docs.spring.io/spring-boot/docs/2.2.7.RELEASE/reference/html/spring-boot-features.html#boot-features-developing-web-applications

扩展SpringMVC

image-20200519183225354

我们要做的就是编写一个@Configuration注解类, 并且类型要为WebMvcConfigurer, 还不能标注@EnableWebMvc注解;我们去自己写一个;
我们新建一个包叫config, 写一个类MyMvcConfig;

package com.ky.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.Locale;//如果,你想diy一些定制化的功能,只要写这个组件,然后将它交给springboot,springboot就会帮我们自动装配
//扩展springMvc dispatcherServlet
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {//ViewResolver 实现了视图解析器接口的类,我们就可以把它看做视图解析器@Beanpublic ViewResolver myViewResolver(){return new MyViewResolver();}//自定义了一个自己的视图解析器MyViewResolverpublic static class MyViewResolver implements ViewResolver{@Overridepublic View resolveViewName(String s, Locale locale) throws Exception {return null;}}
}

官网中有这么一句话:

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.

@EnableWebMvc是干嘛的?

//如果我们要扩展springmvc,官方建议我们这样去做
@Configuration
@EnableWebMvc   //导入了一个类   DelegatingWebMvcConfiguration    作用:从容器中获取所有的webmvcconfig
public class MyMvcConfig implements WebMvcConfigurer {//视图跳转@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/kang").setViewName("index");}
}

先说结论,@EnableWebMvc相当于覆盖所有默认设置

为什么?

WebMvcAutoConfiguration这个类的主要作用是完成对MVC设置的自动装配

但是条件是在没有导入WebMvcConfigurationSupport这个类的情况下才会生效

image-20200519231251603

@EnableWebMvc导入了DelegatingWebMvcConfiguration这个类

image-20200519231022797

DelegatingWebMvcConfiguration这个类继承了WebMvcConfigurationSupport

image-20200519231225893

所以WebMvcAutoConfiguration这个类对MVC的自动设置会全部失效,这是完全接管SpringMVC,而不是对SpringMVC的扩展.

Springboot整合ORM

Springboot整合JDBC

简介

对于数据访问层,无论是SQL(关系型数据库)还是NOSQL(非关系型数据库),Spring Boot底层都是采用Spring Data的方式进行统一处理。Spring Boot底层都是采用Spring Data的方式进行统一处理各种数据库, Spring Data也是Spring中与Spring Boot、Spring Cloud等齐名的知名项目。

Spring data官网: https://spring.io/projects/spring-data

引入SQL相关依赖

image-20200530002829655

pom依赖

image-20200530003017711

配置信息

image-20200530133002875

测试,默认数据源

image-20200530133141478

测试jdbcTemplate

image-20200530133726706

增删改查之类的就不演示了,见名知意直接看api就好.

Sringboot整合Druid

简介

Druid是阿里巴巴开源平台上一个数据库连接池实现,结合了C3P0、DBCP、PROXOOL 等DB池的优点,同时加入了日志监控。
Druid可以很好的监控DB池连接和SQL的执行情况,天生就是针对监控而生的DB连接池。
Spring Boot 2.0以上默认使用Hikari数据源,可以说Hikari与Driud都是当前Java Web.上最优秀的数据源,我们来重点介绍SpringBoot如何集成Druid数据源,如何实现数据库监控。

导入依赖

<!--Druid-->
<dependency><groupId>com. alibaba</ groupId><artifactId>druid</artifactId><version>1.1.21</version>
</dependency>

配置信息

image-20200530144647266

image-20200530145016301

当然,如果要用日志功能,需要引入日志依赖

<!--log4j-->|
<dependency><groupId>1og4j</groupId><artifactId>1og4j</artifactId><version>1.2.17</version>
</dependency>

DruidConfig配置类

image-20200530145823972

这样spring容器中就会有我们的Druid数据源了,可以实现一些功能的配置

实现后台监控功能

//后台监控
//因为SpringBoot内置了servlet 容器,所以没有web.xmL,替代方法: ServletRegistrationBean
@Bean
public ServletRegistrationBean statViewServlet(){ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServ1et("/druid/**")){//后台需要有人登陆,账号密码配置HashMap<String, String> initParameters = new HashMap<>();//增加配置initParameters.put( "loginUsername", "admin"); //登key是固定的LoginUsername LoginPasswordinitParameters.put("loginPassword" , "123456");//允许谁可以访问,为空表示所有人可访问initParameters.put("a11ow", "";//禁止谁能访问initParameters.put( "deny", "192.168.11.123"); bean.setInitParameters(initParameters); // 设置初始化参数return bean;
}

自带monitor

image-20200530150903153

image-20200530151000980

filter

//filter
@Bean
public FilterRegistrationBean webStatFilter(){FilterRegistrationBean bean = new FilterRegistrationBean();bean.setFilter(new WebStatFilter());//可以过滤哪些请求呢?Map<String, String> initParameters = new HashMap<>(); .//这些东西不进行统计initParameters.put("exclusions","*.js,*.css,/druid/*");bean.setInitParameters(initParameters);return bean;
}

Springboot整合Mybatis

引入依赖

<!--mybatis-spring- boot-starter-->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.1</version>
</dependency>

application.properties(yml也可)

spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.ur1=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysq1.cj.jdbc.Driver

测试

pojo

//此处是导入了lombok的依赖
@Data
@NoArgsConstructor
@A11ArgsConstructor
public class User {private int id;private String name ; private String pwd ;
}

mapper

//这个注解表示了这是一一个 mybatis的mapper类;  我们原来用的@MapperScan,现在用这个就不用写了,都可
@Mapper
@Repository
public interface UserMapper {List<User> queryUserList();User queryUserById(int id);int addUser(User user);int updateUser(User user);int deleteUser(int id);
}

mybatis官方中文文档 https://mybatis.org/mybatis-3/zh/getting-started.html

xxxMapper.xml(这里是官方示例)

<?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="org.mybatis.example.BlogMapper"><select id="selectBlog" resultType="Blog">select * from Blog where id = #{id}</select>
</mapper>

image-20200530154305052

整合mybatis配置信息

#整合mybatis
mybatis.type-aliases-package=com.kuang.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

xml一一对应(当然我们如果用tk的通用mapper就没那么麻烦了)

image-20200530154713636

搞一个Controller测试

@RestController
public class UserController {@Autowiredprivate UserMapper userMapper;@GetMapping(/queryUserList" )public List<User> queryUserList(){List<User> userlist = userMapper.queryUserList();for (User user : userList) {System.out.print1n(user);}return userList;}
}

总的来说

  1. 导入包
  2. 配置文件
  3. mybatis配置
  4. 编写sq
  5. service层调用dao层
  6. controller调用service层

SpringSecurity

web开发中,过滤器拦截器都能做安全相关的东西,安全并不是一个功能性需求(不做安全网站也能跑起来)

但是安全应该是在设计之初就考虑的内容

可以实现的功能

  • 功能权限
  • 访问权限
  • 菜单权限

我们原来实现这些功能–>拦截器,过滤器—>大量的原生代码—>繁琐冗余

环境引入

RouteController

通过输入的id直接路由到对应的网页,展示对应的内容

image-20200530162003669

页面展示

因为没有加权限控制,所以了展示所有的信息

image-20200530162432964

Springsecurity是一种AOP的思想,就是横切嘛,不懂得同学了解下就好

简介

Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入spring boot-starter-security模块,进行少量的配置,即可实现强大的安全管理!

记住几个类:

  • WebSecurityConfigurerAdapter: 自定义Security策略 适配器模式
  • AuthenticationManagerBuilder: 自定义认证策略 建造者模式
  • @EnableWebSecurity: 开启WebSecurity模式 @Enablexxxx—>开启某个功能

Spring Security的两个主要目标是“认证”和"授权”(访问控制)

“认证”(Authentication)

"授权”(Authorization)

这个概念是通用的,而不是只在Spring Security中存在。

参考官网: https://spring.io/projects/spring-security#overview

查看项目中的版本,找到对应的帮助文档: https://docs.spring.io/spring-security/site/docs/5.2.4.RELEASE/reference/htmlsingle/

引入依赖

<!--security-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

核心的就是AOP,config,web

image-20200530163842554

官方示例

https://docs.spring.io/spring-security/site/docs/5.2.4.RELEASE/reference/htmlsingle/#hello-web-security-java-configuration

@EnableWebSecurity
public class Config extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.apply(customDsl()).flag(true).and()...;}
}

授权

image-20200530174934993

效果

image-20200530175014118

设置跳转登录页面之后可以自动跳转到登录页

image-20200530175157528

认证

image-20200530190430061

注意:此处在springboot2.1.x中可以直接使用,在Spring Security 5.0中新增了很多加密方法,如果未设置会报错

解决方案:

image-20200530190516316

注销

image-20200531110703040

问题

现在我们只是可以通过security达到让用户只能点击对应权限的模块,但是还不能做到只能让用户直接看到他自己的模块

image-20200531111848972

解决方案

SpringSecurity整合thymeleaf

引入依赖:

<!--security-thymeleaf整合包-->
<dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-springsecurity4</artifactId><version>3.0.4.RELEASE</version>
</dependency>

前端页面修改

导入命名空间

image-20200531114319243

修改页面

image-20200531115239243

image-20200531115545063

SecurityConfig修改

image-20200531115334346

记住我

image-20200531120015898

效果

image-20200531120041769

其实是往cookie和session中丢了个value

image-20200531120124012

害,兄弟萌自己看吧,这里有点绕,笔记文字不好描述 https://www.bilibili.com/video/BV1PE411i7CV?p=37

Shiro

简介

  • Apache Shiro是一个Java的安全(权限)框架。
  • Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。
  • Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等。
  • 下载地址: http://shiro.apache.org/
  • image-20200531172924314

有哪些功能

image-20200531173228437

  • Authentication:身份认证、登录,验证用户是不是拥有相应的身份;
  • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限,即判断用户能否进行什么操作,如:验证某个用户是否拥有某个角色,或者细粒度的验证某个用户对某个资源是否具有某个权限!
  • Session Manager:会话管理,即用户登录后就是第一次会话, 在没有退出之前,它的所有信息都在会话中; 会话可以是普通的JavaSE环境,也可以是Web环境;
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库中,而不是明文存储;
  • Web Support: Web支持,可以非常容易的集成到Web环境;
  • Caching:缓存,比如用户登录后,其用户信息,拥有的角色、权限不必每次去查,这样可以提高效率
  • Concurrency: Shiro支持多线程应用的并发验证,即,如在一个线程中开启另- 个线程,能把权限自动的传播过去
  • Testing:提供测试支持;
  • Run As:允许一个用户假装为另-一个用户(如果他们允许)的身份进行访问;
  • Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了

shiro架构(外部)

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

image-20200531173445075

  • subject:应用代码直接交互的对象是Subject, 也就是说Shiro的对外API核心就是Subject, Subject代表了当前的用户,这个用户不-定是- -个具体的人,与当前应用交互的任何东西都是Subject, 如网络爬虫,机器人等,与ubject的所有交互都会委托给SecurityManager; Subject其实是一 个门面, SecurityManageer 才是实际的执行者
  • SecurityManager:安全管理器,即所有与安全有关的操作都会与SercurityManager交互,并且它管理着所有的Subject,可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC的DispatcherServlet的角色
  • Realm: Shiro从Realm获取安全数据(如用户,角色,权限),就是说SecurityManager 要验证用户身份,那么它需要从Realm获取相应的用户进行比较,来确定用户的身份是否合法;也需要从Realm得到用户相应的角色、权限,进行验证用户的操作是否能够进行,可以把Realm看 成DataSource;

shiro架构(内部)

image-20200531173905154

  • Subject:任何可以与应用交互的’用户’;
  • Security Manager:相当于SpringMVC中的DispatcherServlet; 是Shiro的心脏,所有具体的交互都通过Security Manager进行控制,它管理者所有的Subject,且负责进行认证,授权,会话,及缓存的管理。
  • Authenticator:负责Subject认证,是一个扩展点,可以自定义实现;可以使用认证策略(Authentication Strategy),即什么情况下算用户认证通过了;
  • Authorizer:授权器,即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的那些功能;
  • Realm:可以有一一个或者多个的realm,可以认为是安全实体数据源,即用于获取安全实体的,可以用JDBC实现,也可以是内存实现等等,由用户提供;所以一般在应用中都需要实现自己的realm
  • SessionManager:管理Session生命周期的组件,而Shiro并不仅仅可以用在Web环境, 也可以用在普通的JavaSE环境中
  • CacheManager:缓存控制器,来管理如用户,角色,权限等缓存的;因为这些数据基本.上很少改变,放到缓存中后可以提高访问的性能;
  • Cryptography:密码模块,Shiro 提高了- -些常 见的加密组件用于密码加密,解密等

HelloWorld快速实践

官方文档: http://shiro.apache.org/tutorial.html

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

github: https://github.com/apache/shiro

quickstart

git pull之后可以看到quickstart文件夹,可以去看看里面的start代码

image-20200601082654971

新建一个helloshiro工程

image-20200601083437731

配置log4j.properties配置文件

image-20200601083622605

shiro.ini配置文件

如果想要语法高亮需要安装ini插件

image-20200601083928083

把QuickStart.java类建好

/*** Simple Quickstart application showing how to use Shiro's API.** @since 0.9 RC2*/
public class Quickstart {private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);public static void main(String[] args) {// 创建带有配置领域、用户、角色和权限的Shiro SecurityManager的最简单方法是使用简单的INI配置。// 我们将使用一个工厂读取.ini文件,并返回一个SecurityManager实例:// 使用类路径根目录下的shiro.ini文件// (file:和url前缀分别从文件和url加载):Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");SecurityManager securityManager = factory.getInstance();// 对于这个简单的示例quickstart,可以将SecurityManager作为一个JVM单例进行访问。// 大多数应用程序不会这样做,而是依赖于它们的容器配置或web.xml。// 这超出了简单的快速入门的范围,所以我们只做最基本的,感知感知强烈。SecurityUtils.setSecurityManager(securityManager);// 现在,简单的shiro环境已经设置好了,让我们看看您可以做些什么:// 获取当前执行用户: 		重点,subject 三大对象之一Subject currentUser = SecurityUtils.getSubject();// 通过当前用户拿到sessionSession session = currentUser.getSession();session.setAttribute("someKey", "aValue");String value = (String) session.getAttribute("someKey");if (value.equals("aValue")) {log.info("Retrieved the correct value! [" + value + "]");}// 判断当前用户是否被认证if (!currentUser.isAuthenticated()) {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 (AuthenticationException ae) {// 意料之外的条件,是个错误?}}// 说出他们是谁:打印它们的标识主体(在本例中为用户名):log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");// 测试角色if (currentUser.hasRole("schwartz")) {log.info("May the Schwartz be with you!");} else {log.info("Hello, mere mortal.");}// 粗粒度// 测试类型化权限(不是实例级)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.");}// 细粒度// 一个(非常强大的)实例级权限: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!");}// done! 登出currentUser.logout();System.exit(0);}
}

总的来说主要的就几个方法:

Subject currentuser = SecurityUtils.getSubject();
Session session = currentuser.getSession();
currentuser.isAuthenticated()
currentuser.getPrincipa1()
currentuser.hasRole("schwartz")
currentuser.isPermitted("lightsaber:wie1d")
currentUser.logout();

运行结果

image-20200601084008363

Springboot集成shiro

Subject 用户
Securi tyManager 管理所有用户
Realm 连接数据

结构

image-20200601143314818

pom依赖

<!--thymeleaf模板-->
<dependency><groupId>org.thymeleaf</ groupId><artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency><groupId>org.thymeleaf.extras</ groupId><artifactId>thymeleaf-extras-java8time</artifactId>
</dependency><!--shiro-thymeleaf整合-->
<dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.0.0</version>
</dependency>
<!--shiro整合springboot-->	
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-starter</artifactId><version>1.5.3</version>
</dependency><!--springboot-web整合shiro-->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.5.3</version>
</dependency>

UserRealm.java

//自定义的UserRealm 	extends Authoriz ingReaLm
public class UserRealm extends AuthorizingRealm {//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {System.out.println("执行了授权");return null;}//认证@Overrideprotected AuthenticationInfo doGetAuthenticat ionInfo( AuthenticationToken token) throws AuthenticationException{System.out.println("执行了认证");//用户名,密码  数据库中取	此处伪装一下String name = "root";String password = "123456";UsernamePasswordToken userToken = (UsernamePas swordToken) token;if(!userToken.getUsername().equals(name)){return null; //抛出异常 	UnknownAccountException}//密码认证,shiro做return new SimpleAuthenticationInfo("",password,"");}}

ShiroConfig.java

@Configuration
public class ShiroConfig {//ShiroFilterFactoryBean :3@Beanpublic ShiroFilterFactoryBean getshiroFilterFactoryBean(@Qualifler("securityManager") DefaultWebSecurityManager 				defaultWebSecurityManager){ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();//设置安全管理器bean.setSecurityManager(defaultWebSecurityManager);//添加shiro的内置过滤器/**anon:	无需认 证就可以访问authc:	必须认证了才能让问user:	必须拥有记住我功能才能用perms:	拥有对菜 个资源的权限才能访间:role:	拥有某个角色权限1能访间*/Map<String, String> filterMap = new LinkedHashMap<>();filterMap.put("/user/add", "authc");filterMap.put("/user/update", "authc");bean.setFilterChainDefinitionMap(filterMap);//设置登录请求bean.setLoginUrl("/toLogin");bean.setFilterChainDefinitionMap(filterMap);return bean;}//DafaultWebSecurityManager :2@Bean(name="securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRea1m") UserRealm userRealm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//关联UserRealmsecurityManager.setRealm(userRea1m) ; .return securityManager;}//创建realm 对象 需要自定义类 :1@Bean(name="userRealm")public UserRealm userRealm() {return new UserRealm();}}

Controller

@Controller
public class MyController {@RequestMapping({"/","/index"})public String toIndex(Model model){model.addAttribute( "msg","hello,Shiro");return "index";}@RequestMapping("/user/add")public String add(){return "user/add";}@RequestMapping("/user/update")public String update(){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();//封装用户的登录数据UsernamePas swordToken token = new UsernamePasswordToken(username , password);try{subject.login(token); //执行登录方法,如果没有异常就说明oK了 //Subject currentSubject = SecurityUtils.getSubject();//Sesson session = currentSubject.getSession();return "index";}catch (UnknownAccountException uae) { //用户名不存在model.addAttribute("msg","用户名错误");return "login";} catch (IncorrectCredentialsException ice) {model.addAttribute("msg","密码错误"); //密码不存在return "login";}}@RequestMapping("/noauth")@ResponseBodypublic String unauthorized( ){return "未经投权无法访间此页面";}}

测试页面

index

<!DOCTYPE html>
<html lang="en" xmlns :th="http://www.thymeleaf.org"xmlns :shiro="http:// Www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<meta charset="UTF-8">
<title>Tit1e</title>
</head>
<body>
<h1>首页</h1>
<div shiro:notAuthenticated=""><a th:href="@{/toLogin}">登录</a>
</div>
<p th:text="${msg}"></p>
<hr>
<div shiro:hasPermission="user:add"><a th:href="@{/user/add}">add</a>
</div>
<div shiro:hasPermission="user:update"><a th:href="@{/user/update}">update</a>
</div></body>
</html>

login

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

add

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

update

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

整合mybatis

<!--lombok-->
<dependency><groupId>org.projectlombok</ groupId><artifactId>lombokk</artifactId><version>1.16.10</version>
</dependency>
<!--数据库连接-->
<dependency><groupId>mysq1</ groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
<!--日志 -->
<dependency><groupId>1og4j</ groupId><artifactId>1og4j</artifactId><version>1.2.17</version>
</dependency>
<!-- druid数据源 -->
<dependency><groupId>com. alibaba</ groupId><artifactId>druid</artifactId><version>1.1.12</version>
</dependency>
<!--引入myBatis,这是MyBatis官方提供的适配Spring Boot的,而不是Spring Boot自己的-->
<dependency><groupId>org.mybatis.spring.boot</ groupId><artifactId>mybatis-spring-boot-starter</ artifactId><version>2.1.0</version>
</dependency>

在这里BB一句,我觉得只引入一个mybatis的starter就可了

<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>

application.yml

spring: datasource: username: rootpassword: 123456#?serverTimezone=UTC解决时区的报错ur1: jdbc:mysql://1ocalhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8driver-class-name: com.mysq1.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: sta,wall,log4jmaxPoolPreparedStatementPerConnectionSize: 20useGlobalDataSourceStat: trueconnectionProperties: druid.stat.mergeSq1=true;druid.stat.slowSqlMillis=500

application.properties

mybatis.type-aliases-package=com.kuang.pojo
mybatis.mapper-locations=classpath:mapper/*.xml

pojo

User.java

@Data
@A11ArgsConstructor
@NoArgsConstructor
public class User {private int id;private String name;private String pwd;private String perms;
}

mapper

@Repository
@Mapper
public interface UserMpper {public User queryUserByName(String name);
}

userMapper.xml

<?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.kuang.mapper.UserMapper"><select id="queryUserByName" parameterType= "String" resultType= "User">select * from mybatis.user where name = #{name}</select></mapper>

Service

//service接口
public interface UserService {public User queryUserByName(String name);
}
@Service
public class UserServiceImpl implements UserService {@AutowiredUserMapper userMapper;@Overridepub1ic User queryUserByName(String name) {return userMapper.queryUserByName(name);}
}

测试一下

@SpringBootTest
class ShiroSpringbootApplicationTests {@AutowiredUserServiceImpl userService;@Testvoid contextLoads() {System.out.print1n(userService.queryUserByName("kuangshen"));}
}

可以,底层没问题了

image-20200601111027291

改造UserRealm

//自定义的UserRealm 	extends Authoriz ingReaLm
public class UserRealm extends AuthorizingRealm {@AutowiredUserService userService;//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {System.out.println("执行了授权");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//info.addStringPermission("user:add");//拿到当前登录的这个对象Subject subject = SecurityUtils.getSubject();User currentUser = (User)subject.getPrincipal();		//取得是下面认证时return的user//设置当前用户的权限info.addStringPermission(currentUser.getPerms());return info;}//认证@Overrideprotected AuthenticationInfo doGetAuthenticat ionInfo( AuthenticationToken token) throws AuthenticationException{System.out.println("执行了认证");UsernamePasswordToken userToken = (UsernamePas swordToken) token;//连接数据库查询用户User user = userService.queryUserByName(userToken.getUsername());if(user == null){//没有这个人return null;}//可以加密:		MD5: 123456:e10adc3949ba59abbe56e057f20f883e	MD5加盐:123456+username	f052d3f8344c2afe6263843456d15be2//密码认证,shiro做return new SimpleAuthenticationInfo(user,user.getPwd(),"");	//传递user,上面授权才能拿到}}

完善ShiroConfig.java

@Configuration
public class ShiroConfig {//ShiroFilterFactoryBean :3@Beanpublic ShiroFilterFactoryBean getshiroFilterFactoryBean(@Qualifler("securityManager") DefaultWebSecurityManager 				defaultWebSecurityManager){ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();//设置安全管理器bean.setSecurityManager(defaultWebSecurityManager);//添加shiro的内置过滤器/**anon:	无需认 证就可以访问authc:	必须认证了才能让问user:	必须拥有记住我功能才能用perms:	拥有对菜 个资源的权限才能访间:role:	拥有某个角色权限1能访间*///filterMap.put("/user/add","authc");//filterMap.put("/user/update", "authc");//拦截Map<String, String> filterMap = new LinkedHashMap<>();//授权,正常情况下会跳转到未授权页面filterMap.put("/user/add", "perms[user:add]");filterMap.put("/user/update", "perms[user:update]");filterMap.put("/user/*", "authc");bean.setFilterChainDefinitionMap(filterMap);//设置登录请求bean.setLoginUrl("/toLogin");//设置未授权页面bean.setUnauthorizedUr1("/noauth");bean.setFilterChainDefinitionMap(filterMap);return bean;}//DafaultWebSecurityManager :2@Bean(name="securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRea1m") UserRealm userRealm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//关联UserRealmsecurityManager.setRealm(userRea1m) ; .return securityManager;}//创建realm 对象 需要自定义类 :1@Bean(name="userRealm")public UserRealm userRealm() {return new UserRealm();}//整合ShiroDialect: 用来整合shiro和thymeleaf@Beanpublic ShiroDialect getShiroDialect(){return new ShiroDialect();}}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 分布式电商项目十七:商品服务-三级分类和查询

    商品服务-三级分类和查询 我们的项目是做一个电商的网站,拿京东的网站作为对比:在右端进行商品大类的选择时,会出现很多小的类别,作为商品的三级分类,这样便于用户查询商品,本章开始开发这部分功能。 数据库支持 首先我们看一下分类查询功能的数据库支持;打开pms数据库中…...

    2024/5/9 2:26:18
  2. xp怎样升级win7系统的傻瓜教程--win10专业版

    尽管XP一直是微软的经典系统,但随着时代的发展,XP系统已经无法发挥硬件的性能。很多用户也希望体验到新版的微软系统,所以很多人会将XP系统升级到win7系统。那么xp怎样升级win7呢?win7系统升级的方法有很多,其中硬件解压安装升级和U盘安装升级是最常用的两种方法。下面的小…...

    2024/5/8 21:31:30
  3. ffmpeg音视频同步

    没有实现,可能是时间戳同步问题 #include <stdio.h> #include<iostream> #include<Windows.h> #define __STDC_CONSTANT_MACROS#ifdef _WIN32 //Windows extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avf…...

    2024/5/8 21:24:33
  4. Hadoop编译源码(面试重点)

    昨天开始编译的,也不算是踩坑。跟着尚硅谷教程走的,直接分享一下老师的笔记吧。提个醒,编译过程有几次一直出现“-------”这玩意,不代表完成了,要等到后面那张图才代表完事了。我编译了大概90分钟,按教程搞,一遍过。再说点吧,教程是这么操作的,root用户,在"/op…...

    2024/4/24 9:45:57
  5. 阿里云“在家实践”计划测试题答案(部分)

    因新冠肺炎疫情,学校延期开学。在家时间不浪费,提高技能好机会。阿里云弹性计算联合开发者社区,推出高校“在家实影”计划,全国高校学生,每人可免领取一台云服务器ECS算力资源,在线实践影课程等资源。 阿里云高校——学生“在家实践”计划MyBlog:阿里云在家实践计划测试题…...

    2024/5/8 12:54:23
  6. EfficientPS论文翻译-------第二部分:相关工作

    EfficientPS: Efficient Panoptic Segmentation论文翻译-------第二部分:相关工作 全景分割是最近提出的一个场景理解问题(Kirillov et al, 2019),它统一了语义分割和实例分割的任务。对于这些子任务,已经提出了许多方法,但是只有少数方法被引入来处理全景分割的连贯场景理…...

    2024/5/9 0:42:38
  7. MPP update优化一

    前言:对于列式存储直接update性能低下,可采用update+insert方式或者delete+insert 方式 实现更新操作例子:套牌车的一个测试例子drop table dts_vehicle_resource.fake_plate_info_sp; drop table viid_vehicle.vehiclestructured_kafka_sp; drop table dts_vehicle_resourc…...

    2024/4/24 9:45:54
  8. AOP序列化目标方法参数时报错

    问题:ServletRequest、ServletResponse不能被序列化使用google.gson会OOM使用alibaba.fastjson会抛出非法参数异常原因:ServletRequest、ServletResponse是Interface解决方案:private Object[] excludeJoinPointArgs(JoinPoint joinPoint) {Object[] args = joinPoint.getAr…...

    2024/5/8 14:10:10
  9. 查看iOS APP Bundle ID 报错 Could not connect to lockdownd. Exiting.

    IOS APP Bundle ID是APP的唯一标识,以下简称BID,可以用ideviceinstaller -l查看。 最近用此命令查看的时候报错了: Could not connect to lockdownd. Exiting.查了一些资料后,发现是因为很多依赖库太老了,更新一下就可以了。 本文使用的macOS版本是10.15.5。 # 更新brew b…...

    2024/5/8 19:39:10
  10. 饱和度和明度

    饱和度:指颜色的纯度或强度,简单点理解就是颜色中的灰色量含量的高低。明度:指的是颜色中混合了多少白色或黑色。 饱和度、明度越高,视觉冲击力越强烈;饱和度、明度较低的时候,视觉上越温和。高级感的色彩是克制的,表现的精致、稳重、具有品质感。低饱和、低明度的摄影作…...

    2024/5/8 13:05:37
  11. uni-app 修改组件默认样式

    修改 uni-app 组件默认样式 转载做下记录 切记类似于微信原生的,颜色不能修改有平台差异性。 最近刚开始使用uniapp开发,有些组件渲染之后会生成一些标签,我需要修改生成标签的样式。 直接写: <style scoped>.uni-combox__input {font-size: 14px;} </style>无…...

    2024/5/9 2:29:11
  12. 《数据结构与算法指南》01:算法概述汇总

    内容导航:前言 1、何谓算法 2、算法的特征 3、算法的发展历史 4、算法的分类 5、算法相关概念 6、算法的表示法 7、算法性能评估 8、简单案例前言 夸张点说,如果有人因为说过一句话而被授予图灵奖、计算机科学教育杰出贡献奖、Emanual Piore奖和计算机先驱奖,您是不是很惊讶…...

    2024/5/9 2:31:28
  13. DVWA——Brute Force暴力破解(Medium)

    DVWA——Brute Force 暴力破解 Low.学习源码 <?phpif( isset( $_GET[ Login ] ) ) {// Sanitise username input$user = $_GET[ username ];$user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysql…...

    2024/4/24 9:45:48
  14. Opencv中rectangle函数与Rect函数的用法

    rectangle函数是用来绘制一个矩形框的,通常用在图片的标记上。 1.rectangle(img2, Point(j,i), Point(j + img4.cols, i + img4.rows), Scalar(255, 255, 0), 2, 8);img2:被处理的图片 Point(j,i)代表矩形左上点的坐标 Point(j + cols, i + rows)代表矩形右下点的坐标【矩形的…...

    2024/4/24 9:45:50
  15. ViewDragHelper实战,实现滑动解锁

    说到滑动解锁,就回到了2012~2014年,iPhone4S、5、5S年代,如今准备踏入2020年,这些年国产机崛起,再也不是公交车上都是iPhone4S的场景。本篇来使用ViewDragHelper实现滑动解锁。成品展示先来分析一下页面的元素背景图圆角滑道圆形滑块闪动提示文字 其他一些细节:滑道和圆形…...

    2024/4/24 9:45:53
  16. 首款国产开源数据库TBase核心架构演进

    腾讯云数据库国产数据库专题线上技术沙龙正在火热进行中,4月14日李跃森的分享已经结束,没来得及参与的小伙伴不用担心,以下就是直播的视频和文字回顾。关注“腾讯云数据库”公众号,回复“0414李跃森”,即可下载直播分享PPT。大家好,我是李跃森,目前负责腾讯云TBase数据库…...

    2024/4/17 16:14:48
  17. Android - Button 添加事件的3中方法

    一 、监听器:监听器是一个存在于View类下的接口,一般以On******Llistener命名,实现该接口需要复写相应的on****(View v)方法(如onClick(View v))二、监听器的三种实现方法1、利用布局文件中的onClick属性,并在实现文件中实现该方法。注意的是这里的方法名应该和布局文件中…...

    2024/4/18 16:27:51
  18. 单片机(MCU)最强科普(万字总结,值得收藏)

    MCU是Microcontroller Unit 的简称,中文叫微控制器,俗称单片机,是把CPU的频率与规格做适当缩减,并将内存、计数器、USB、A/D转换、UART、PLC、DMA等周边接口,甚至LCD驱动电路都整合在单一芯片上,形成芯片级的计算机,为不同的应用场合做不同组合控制,诸如手机、PC外围、…...

    2024/4/16 9:51:37
  19. [斗鱼]没人比我更懂微服务--Go微服务框架Jupiter

    作者:aerox@斗鱼 项目开源地址:https://github.com/douyu/jupiter Jupiter 是斗鱼开源的,面向服务治理的Golang微服务框架,以开发效率和治理效率为核心目标,从统一开发规范、完善监控埋点、降低开发难度等多个维度来帮助Gopher开发高性能、高可靠性的微服务框架。 Jupiter…...

    2024/4/16 19:58:14
  20. Java小游戏-飞机大战(FunnyTopGun)

    效果图:游戏窗口有两个,一个类似于登录界面,点击屏幕跳转到另一个主窗口。WASD控制上下左右,空格键攻击。只用单一的主窗口线程的话键盘不能同时响应移动和攻击事件,所以创建多线程来控制事件发生:PaintThread pt = new PaintThread(); //画图线程MyBulletThread bt = n…...

    2024/4/24 9:45:45

最新文章

  1. 计算机毕业设计Python+Spark知识图谱医生推荐系统 医生门诊预测系统 医生数据分析 医生可视化 医疗数据分析 医生爬虫 大数据毕业设计 机器学习

    摘 要 随着我国社会经济发展水平的不断提高&#xff0c;人们的物质生活水平也有了很大的改善&#xff0c;越来越多的人不满足于当前的医疗服务质量&#xff0c;由于地域和空间的限制&#xff0c;医疗资源不平衡&#xff0c;无法实现全民共享。针对当今社会中存在的求医难的问题…...

    2024/5/9 8:29:33
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. AI小程序的创业方向:深度思考与逻辑引领

    随着人工智能技术的快速发展&#xff0c;AI小程序逐渐成为创业的新热点。在这个充满机遇与挑战的时代&#xff0c;我们有必要深入探讨AI小程序的创业方向&#xff0c;以把握未来的发展趋势。 一、目标市场定位 首先&#xff0c;我们要明确目标市场。针对不同的用户需求&#x…...

    2024/5/8 14:22:38
  4. Python语法总结:not(常出现错误)

    0、not是什么 在python中not是逻辑判断词&#xff0c;用于布尔型True和False之前 a not Ture # a False b not False # b True1、not的用法 &#xff08;1&#xff09;判断语句 if not a:# 如果a是False&#xff0c;执行的语句&#xff08;2&#xff09;判断元素是否在…...

    2024/5/7 15:29:37
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/7 9:45:25
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/9 4:20:59
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/8 20:48:49
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/8 19:33:07
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/8 20:38:49
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/9 7:32:17
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57