第一节

Spring技术的3个大的发展历史阶段

  1. spring1.x版本阶段

所有的依赖关系,都是使用 进行描述——不管是IOC还是AOP的关系都是这样处理,都是历史背景决定的。

  1. spring2.x版本阶段

伴随着JDK1.5而来,它支持注解,使得 配置文件的体积大大减小了,配置文件的数量也大大减少了。争论了很久 ,最终统一了使用方式:一些系统的配置使用 完成,一些业务逻辑配置使用注解。

  1. spring3.x-spring4.x版本阶段

彻底的摆脱 配置,完全使用注解+java类的形式。目前项目中还没有完全使用该种方式,以后纯使用该方式的机会也不大,因为springboot技术出来了,它就是建立在0配置技术之上的一种技术——换句话说,springboot改变了我们使用spring的姿势。

 

第二节

使用注解+javabean的方式实现Bean的注入

  1. 需要声明,该节内容并非springboot内容,而是演示如何零配置实现我们的IOC注入,注解+javabean的形式
  2. 程序的实现
  1. 首先建立一个工程,我们在这里建立一个再普通不过的java工程,工程结构如如:

  1. 编写相应的dao,service,test等类,另外还要编写一个java配置类

  1.  测试

执行MainTest,查看是否能够执行到UserDao的被调用的方法,测试成功。
4)备注

@Bean注解要求方法必须是public,返回值是注入要注入的对象的类型

 

第3节

创建我的第一个springboot工程

  1. 如何创建springboot工程?
  1. 创建一个普通的maven工程,然后手动将需要的springboot依赖添加进去即可
  2. 使用springboot官方网站来生成springboot工程的骨架,然后导入到IDE即可

  1. 使用springboot提供的一个IDE插件STS,该插件集成到我们的IDE中

 

  1. 使用第三种方式即STS创建我们的springboot工程
  1. 选择new-project-spring-spring starter project

           

2)填写工程基本信息,要求必须联网才能正常执行否则报连接错误的异常

3)创建工程,如果有需要的话在这里可以修改springboot的版本号

备注:

  1. 如果第一次创建工程的话,花费的时间会比较长,因为很多依赖需要下载。
  2. 本即可主要掌握使用STS插件创建springboot工程,另外需要注意必须联网该插件才能正常执行。
  3. Springboot2.0只支持JDK1.8以上的版本
  4. 随着官网http://start.spring.io上面版本的更改STS插件也会跟着更改版本信息。
  5. 简单讲解工程结构和引入的maven依赖包

 

 

 

 

 

第4节

编写我的第一个springboot应用程序

  1. 在上节工程springboothelloworld基础上编写程序
  2. 正式编写
  1. 修改pom. 给定一个jar包的文件名称

  1. 编写pojo,dao,service,controller

这里编写的pojo,dao等所有组件跟之前springmvc工程中的所用注解或者编写流程一模一样,没有任何区别,参考代码。

  1. 测试
  1. 通过springboot的入口程序启动
  2. 通过java -jar xxx.jar来启动,可能受第一次影响占用8080,关闭eclipse即可
  3. 启动日志简单分析

可以看到,内置了8.5的tomcat,并且默认端口为8080.访问地址http://localhost:8080/getuser?id=1000

 

第5节

剖析springboot工程——工程结构

 

第一节

Spring技术的3个大的发展历史阶段

  1. spring1.x版本阶段

所有的依赖关系,都是使用 进行描述——不管是IOC还是AOP的关系都是这样处理,都是历史背景决定的。

  1. spring2.x版本阶段

伴随着JDK1.5而来,它支持注解,使得 配置文件的体积大大减小了,配置文件的数量也大大减少了。争论了很久 ,最终统一了使用方式:一些系统的配置使用 完成,一些业务逻辑配置使用注解。

  1. spring3.x-spring4.x版本阶段

彻底的摆脱 配置,完全使用注解+java类的形式。目前项目中还没有完全使用该种方式,以后纯使用该方式的机会也不大,因为springboot技术出来了,它就是建立在0配置技术之上的一种技术——换句话说,springboot改变了我们使用spring的姿势。

 

第二节

使用注解+javabean的方式实现Bean的注入

  1. 需要声明,该节内容并非springboot内容,而是演示如何零配置实现我们的IOC注入,注解+javabean的形式
  2. 程序的实现
  1. 首先建立一个工程,我们在这里建立一个再普通不过的java工程,工程结构如如:

  1. 编写相应的dao,service,test等类,另外还要编写一个java配置类

UserDao:

UserService:

SpringConfig:

MainTest:

  1.  测试

执行MainTest,查看是否能够执行到UserDao的被调用的方法,测试成功。
4)备注

@Bean注解要求方法必须是public,返回值是注入要注入的对象的类型

 

第3节

创建我的第一个springboot工程

  1. 如何创建springboot工程?
  1. 创建一个普通的maven工程,然后手动将需要的springboot依赖添加进去即可
  2. 使用springboot官方网站来生成springboot工程的骨架,然后导入到IDE即可

  1. 使用springboot提供的一个IDE插件STS,该插件集成到我们的IDE中

 

  1. 使用第三种方式即STS创建我们的springboot工程
  1. 选择new-project-spring-spring starter project

           

2)填写工程基本信息,要求必须联网才能正常执行否则报连接错误的异常

3)创建工程,如果有需要的话在这里可以修改springboot的版本号

备注:

  1. 如果第一次创建工程的话,花费的时间会比较长,因为很多依赖需要下载。
  2. 本即可主要掌握使用STS插件创建springboot工程,另外需要注意必须联网该插件才能正常执行。
  3. Springboot2.0只支持JDK1.8以上的版本
  4. 随着官网http://start.spring.io上面版本的更改STS插件也会跟着更改版本信息。
  5. 简单讲解工程结构和引入的maven依赖包

 

 

 

 

 

第4节

编写我的第一个springboot应用程序

  1. 在上节工程springboothelloworld基础上编写程序
  2. 正式编写
  1. 修改pom. 给定一个jar包的文件名称

  1. 编写pojo,dao,service,controller

这里编写的pojo,dao等所有组件跟之前springmvc工程中的所用注解或者编写流程一模一样,没有任何区别,参考代码。

  1. 测试
  1. 通过springboot的入口程序启动
  2. 通过java -jar xxx.jar来启动,可能受第一次影响占用8080,关闭eclipse即可
  3. 启动日志简单分析

可以看到,内置了8.5的tomcat,并且默认端口为8080.访问地址http://localhost:8080/getuser?id=1000

 

第5节

剖析springboot工程——工程结构

 

  1. 入口类所在的包是controller,service,pojo,dao的父目录,因为该类在启动的时候会默认扫描它的同级目录和子目录。
  2. resources一般放置配置文件,其下的所有内容打包后会计入classes目录下。
  3. Application.properties是springboot工程的核心配置文件,打包后进入classes目录。
  4. static目录用来存放网站的静态资源,例如js,css,图片等内容。
  5. Templates目录用来存放网站的模板文件,例如freemaker,thymeleaf等

在springboot目录结构中,遵循的原则就是“约定大于配置”,使得配置文件更加简化,容易维护,可以把它看成是行业标准。

 

第6节

剖析springboot工程——pom. 文件

  1. 继承的父依赖——这是必须的

从该父依赖中继承了springboot工程必须的一些jar包,该父依赖是springboot工程中必不可少依赖,它也是区别普通mavven工程的一个特点。

  1. 其他依赖——非必须的,根据选择的不同组件springboot帮我们添加相应的依赖

例如,上午创建的工程为web工程,那么它就自动添加了如下一类,如图:

  1. 打包的一个插件——这是必须的

这是springboot帮我们提供的一个插件,该插件可以根据第5节讲到的约定目录帮助我们将工程打包成可执行的jar包或者war包,如果没有这个插件,我们必须手动写pom代码。

 

第7节

剖析springboot工程——入口类

  1. 该入口类的位置

默认情况,该入口类会在比较父级的目录中,因为它要扫描同级目录和所有的子目录中带有spring注解的类(需要在spring容器创建对象)。如果放到子目录中必须指定要扫描的包的路径,不推荐这样做,按默认即可,例如:

备注:

Run方法中传入两个参数,第一个参数默认传入本类的class,也可以传入一个其他类,但是该类必须有SpringBootApplication注解。

  1. @SpringBootApplication注解

该注解是springboot工程的核心注解,没了它运行不了,同时它也是一个组合注解。

如图是定义该注解的代码:

即一旦使用了该注解,等价于把上面所有的注解都使用上了。总之,使用了该注解以后这个入口类就是一个java配置类,并且有了自动配置功能,并且还有了自动扫包的功能。

  1. 入口类的功能

根据上述描述,入口类由一个main方法启动,就会启动内嵌的tomcat或jetty容器,然后加载所有需要加载的或扫描的类或资源文件,进而初始化spring容器,完成对象的注入。

 

第8节

剖析springboot工程——可执行jar包和war包

  1. jar包的结构

备注:该配置文件是自动生成的,它里面指定了启动类,在执行java -jar命令的时候会自动加载该启动类。

  1. war包的结构

将第3节课工程中pom. 中的packaging值由原来的jar直接改为war,其他配置不做任何改变,然后打成war包,其结构如下:

备注:通过java -jar helloworld.war命令执行该war包,成功。但是非jsp的应用一般不建议打war包。

  1. 作业
  1. 在static目录放一张图片,是否能够通过http://localhost:8080/a.jpg访问?
  2. 上本节课打的war包放置到tomcat中看是否能够执行?不能

 

 

 

第9节

认识springboot工程的配置文件——application.properties文件

  1. springboot支持的配置文件的格式

Application.properties和application.yml

  1. application.properties文件

为了满足个性化的需求,所以该框架提供了一个简单的配置文件,通过健值对的形式去配置自己的参数,并且这些健同application.properties名字一样,也是约定好的,springboot就可以自动读取这些键值对,不需要我们另外写程序完成。

  1. 完成工程默认tomcat端口和虚拟目录的配置

server.port=8090

server.servlet.context-path=/helloworld

  1. 打包测试

  1. 其他演示

 

 

 

 

第10节

springboot工程的特点小结

  1. springboot的特点
  1. springboot是建立在spring之上的,或者说是以spring为基础的。例如Springboot2.0是以spring5.x为基础的。内置tomcat版本为8.5.
  2. springboot遵循的原则是“约定大于配置”。例如:工程的目录结构,配置文件的名称,配置文件中的键值对....
  3. 开箱即用,内置了很多组件,只需要进入相应的依赖即可。例如:使用web组件只需要引入spring-boot-starter-web那么springmvc中的注解requestmapping等、内置web容器就自动添加好了。
  4. 自动配置,例如我们的tomcat,事务,mybatis等自动配置。
  5. 完全兼容spring,即spring支持的,它就支持。
  6. springboot不算是一种新技术的具体实现,它只是改变了我们使用spring的姿势。

 

第10节

自定义springboot启动时的banner图标

  1. 首先,需要准备一个这样的banner文件字符

打开http://patorjk.com/software/taag输入自己想要的文字,免费帮我们只做一个banner字符样式,不支持中文字符,例如:

  1. 在我们项目的resources目录下建立一个名称为banner.txt的文件,将上述只做的banner字符复制到该文件
  2. 重启服务即可看到最新的自定义banner
  3. 注意:该banner不是一个图片,而是用字符拼写的

备注:

  1. 在springboot2.0以后的版本还支持动态banner
  2. 也可以在SpringApplication对象中使用的setBanner方法将其关闭

 

第11节

springboot自动配置的原理

  1. 在创建springboot项目的时候pom. 中的parent继承了很多的jar依赖,其中有一个名称为spring-boot-autoconfigure-2.0.2.RELEASE.jar的jar包,在该jar包中定义(实现)了组件的自动配置。
  2. 在上述jar包中的 -INF中有个一个名称为spring.fatories的声明性文件,内容部分如下:

当在pom. 中一旦引入了某一个starter组件,那么就会在里找相应的自动配置类来实现自动配置。

  1. 自动配置的实现过程

打开一个XXAutoConfiguration的类,即可看到里面自动配置的实现过来,例如solr.

实现部分代码如下:

  1. solrproperties类中获取solr在application.properties中自定义的连接地址,如果没有自动以则使用默认的http://127.0.0.1:8983/solr

  1. 真真的实现类在SolrAutoConfiguration类中

本质还是使用spring中的@Configration和@Bean两个注解实现了将SolrClient对象注入到spring容器。此时,我们就可以在我们的程序中直接使用@Autowired注入solrClient对象去使用了,因为它已经存在于spring容器中了。

 

第12节

关闭springboot的自动配置

  1. 在spring.fatories文件中目前大概有140多种自动配置,每一种自动配置对应一个独立的技术组件,application.properties中支持的键值对大概有1000多项,这1000多项都是为这140多个技术组件服务的。
  2. 关闭自动配置,如下所示即可排除不想要的自动配置内容:

 

一般情况下,不建议手动配置。

 

第13节

将springboot项目发布到独立的tomcat

  1. 将第8节内容中的helloworld.war包发布到独立的tomcat下能否运行?

不能。

  1. 为什么不能运行?

因为该war包中缺少一个非常重要的文件——web. 文件,所以外部tomcat在启动时无法知道该项目是一个标准的web项目,所以也就无法访问。备注:tomcat启动日志未看到springboot的banner图标。

  1. 如何解决上述问题?
  1. 使用sts创建一个war类型的web项目,取名springboottomcat
  2. 第一步成功后会自动生成一个ServletInitializer.java类,该类可以实现web. 的功能,以便让外部的tomcat认识到该项目是一个web项目,从而进行加载。

  1. 跟之前一样,编写controller等方法
  1. 测试
  1. 将上述工程打包成war,然后使用java -jar xxx.war启动该项目,测试结果正常
  2. 将该war包复制到外部tomcat的webapp目录下,测试结果正常
  3. 这次启动tomcat后台日志有了springboot的banner图标,如下:

这是跟上次失败实验的一个不同之处,说明tomcat已经将该项目进行了加载。

第14节

在springboot项目中配置MVC并使用jsp作为视图模板

  1. 官网为什么没有默认支持jsp?
  1. 需要编译
  2. 所见非所得
  1. 官方推荐使用什么模板?

freemarker或者thymeleaf等模板。

  1. 如何在springboot项目中使用jsp?
  1. 跟上节课一样,建立名称为springbootjspwar的war项目,并引入web依赖
  2. 在第一步的基础上的pom. 中增加对jsp编译支持的依赖,如下:

<dependency>

     <groupId>org.apache.tomcat. </groupId>

     <artifactId>tomcat- -jasper</artifactId>

</dependency>

  1. 在application.properties中进行参数配置,如下:

server.port=8080

server.servlet.context-path=/hellojsp

server.servlet-path=/

spring.mvc.view.prefix=/jsp/

spring.mvc.view.suffix=.jsp

备注:

  1. context-path的值是访问地址的虚拟路径,默认值是/
  2. servlet-path的值是dispatcherServlet的URL过滤规则,默认是/,还可以是*.do或者*.html或者其他后缀
  3. prefix的值是jsp目录前缀, 没有默认值,如果使用jsp的话必须配置
  4. suffix的值是jsp的后缀,没有默认值,如果使用jsp的话必须配置


4)编码

只需写一个简单的controller类和user.jsp即可,结构和内容如下:

  1. 测试
  1. 运行项目,访问http://localhost:8080/hellojsp/user,该war项目可以有3种运行方式:
  1. 入口类运行
  2. war包运行
  3. 放到外部tomcat运行
  1. 第一次测试没有成功,得到的页面内容为jsp源码内容或者下载jsp,原因是没有添加tomcat- -jasper依赖
  1. 备注
  1. 上述工程如果打包为jar包格式,则无法独立于eclipse环境而运行,会找不到jsp页面,除非将springboot替换为1.4.2版本;
  2. context-path的值只针对内置tomcat有效,如果将该war发布到外部tomcat则访问路径要按照server. 中的虚拟路径访问;
  3. servlet-path值如果是*.do等,controller类中的RequestMapping()要做相应书写,例如:@RequestMapping(\"/user.do\");
  4. prefix值是相对src/main/webapp而言的,这点跟传统的SpringMvc设置是一样的。
  5. 打包后的war结构如下图所示:

 

  1. 本节问题
  1. application.properties和application.yml共存导致冲突
  2. 声明的URL规则为*.do但是requestmapping中并没有写.do导致404
  3. 项目已经发布到外部tomcat但是访问是浏览器中地址写的仍是context-path中的地址导致404
  4. Controller类没有使用@controller注解导致404

 

 

 

 

 

 

第15节

使用@PropertySource读取外部资源文件

  1. 之前读取properties文件的方式
  1. 使用util包下的Properties类通过API的方式读取
  2. 使用spring. 中的一个表签来完成内容的读取

2.使用注解的方式来完成读取

1)在springboothelloworld工程中做测试,新建ReadProperties,编码如下:

备注:

  1. 如果在dao层注入该类的话,该类必须被spring容器所管理,因此必须加Compoent注解
  2. PropertySource注解可以一次读取N个资源文件,使用逗号隔开
  3. Value注解中的el表达式必须对应资源文件中的key值
  4. 类的属性名称可以任意取一个,只要是合法的即可

 

3.在程序中使用该类,例如在Dao层访问,然后通过controller访问并测试

 

4.注意事项

读取properties文件中的username属性值时,得不到正确的结果,得到是本地计算机的名称,例如:

得到的值:

 

第16节

在springboot工程中使用servlet

  1. 之前使用servlet的方式
  1. 使用web. 通过servlet标签声明
  2. 注解
  1. 在springboot工程中使用servlet

准备springbootcomponents工程,新建cn.buba.servlet包,在这个包下新建两个servlet——ServletOne和ServletTwo。注意:先新建ServletOne,走通后再建ServletTwo,新建ServletTwo的目的在于演示url匹配规则优先级。

 

  1. ServletOne代码:

2)在springboot入口类添加ServletComponetScan注解

访问http://localhost:8080/one/abc或者http://localhost:8080/one/aaa等,如下:

可以看到,servlet只进行了一次初始化——第一次被访问的时候。以后其他人再访问的时候初始化方法就不再执行。

  1. url匹配度和访问优先级问题
  1. 新建servletTwo,如下:

 

访问http://localhost:8080/one/abc/123执行给结果:

 

访问http://localhost:8080/one/abcd/123执行给结果:

小结:

  1. 匹配度越高越优先被执行
  2. 只执行一个servlet并不是所有满足规则的servlet都执行
  3. 在实际开发中,不必给它的urlPatterns加通配符

 

第17节

在springboot工程中使用Filter

  1. 使用步骤
  1. 新建自己的filter并在该filter上添加@WebFilter注解
  2. 在springboot入口类上添加@ServletComponentScan注解
  1. 新建FilterOne,代码如下:

  1. 单个Filter做测试
  1. filter的初始化是伴随着容器初始化而初始化的
  2. 在浏览器中访问http://lcoahost:8080/one/abc/123,结果如下:

即doFilter()中的代码不是顺序执行的,chain.doFilter()之前的代码在目标代码执行之前执行,chain.doFilter()之后的代码在目标方法执行完之后执行。

 

  1. 作业

编写FilterTwo,完成以下内容:

  1. 验证FilterOne和FilterTwo的初始化顺序?确定初始化顺序跟什么有关系
  2. 仍访问3中的链接,确定多个过滤器情况下过滤器的请求顺序和响应顺序?

 

第18节

在springboot中使用监听器

  1. 监听器有哪些监听的对象?

对request对象的监听;

对session的监听,包括session的创建、销毁、属性值的绑定、解绑等;

对application对象的监听,包括容器的启动、关闭等。

  1. 在springboot项目中使用监听器

加起来有10个基本的接口,我们拿着ServletContextListener接口做演示。过程如下:

  1. 在自己的监听器类上加@WebLinstener注解
  2. 在springboot入口类添加@ServletComponentScan注解
  1. 代码实现

备注:

  1. 选择哪一个监听器接口完全根据自己的业务需求
  2. 在监听器提供的方法参数中,可以获取request,session,application等对象
  1. 测试
  1. 观察该监听器初始化和销毁过程
  2. 强制关闭容器时销毁方法contextDestroyed()不执行
  1. 作业

在controller或者servlet或者jsp中获取上述程序中的encording值。

 

第19节

在springboot工程中使用拦截器

  1. 接口中可以有“已经实现”了的方法吗?static和default关键字

在1.8版本以上可以使用default和static关键字来修饰我们的方法,在这类方法上可以写具体的实现,这样在实现类上就必须每一个方法都要实现一次了,只需要重写自己需要的方法。

  1. 实现拦截器—HandlerInterceptor接口

实现上述接口,并重写里面的方法,最后为该类添加@Component注解,代码如下:

  1. 配置拦截器—WebMvcConfigurer接口
    实现上述接口,并重写addInterceptors()方法,将上面的拦截器通过@Autowired注入并注册到spring容器中,代码如下:

  1. 测试

启动程序,执行http://localhost:8080/getuser连接,后台打印结果如下:

备注:见代码。

  1. 过滤器和拦截器的执行顺序

当项目有过滤器和拦截器的时候,当在都满足URL规则的时候,Filter先执行——再执行拦截器——目标方法——Filter中的chain.doFilter()之后的代码。如图:

  1. 多个拦截器之间的执行顺序

多个拦截器的执行顺序跟在配置类中添加的顺序一致,先添加的先执行。如图:

  1. 过滤器和拦截器的区别
  1. 实现的接口不一样
  2. Filter必须依赖于web容器,但是拦截器不一定依赖web容器
  3. Filter是基于回调函数的,拦截器是基于AOP思想的一个实现
  4. Filter设计的目的是对请求和响应进行过滤,拦截器的目的是拦截

 

第20节

单元测试—RunWith、SpringBootTest、Test注解

  1. 为什么要使用单元测试来测试程序?

因为单元测试比较方便,不需要来回重启web服务器,也不需要在浏览器输入地址。

  1. 使用单元测试—方式A

要想使用web环境下的单元测试,必须提供一个web环境来支持我们的web组件,例如从request中取值,这时没有web环境是无法做到测试的。为了解决上述问题,springboot提供了两个注解来帮我们实现目的。具体的使用如下:

  1. 使用单元测试—方式B

不在controller中使用上述注解,而是写一个单独的类。如下代码所示:

  1. 备注

Junit对测试方法的签名有3个要求必须要满足,否则无法进行单元测试,如下:

  1. 方法必须是public类型否则junit没有方法权限
  2. 方法的返回类型必须为void
  3. 方法的参数必须为空,不能有任何参数

 

第21节

异常处理—ControllerAdvice和ExceptionHandler注解

  1. 传统实现过程

springmvc. 内容:

error.jsp内容:

  1. 使用注解实现

备注:

  1. 该类不需要实现任何接口也不需要继承任何其他类
  2. 只需要在该类上添加@ControllerAdvice注解即可不需要在boot的入口类再另外添加其他支持性的注解,因为ControllerAdvice注解本身就是spring的注解,能自然解析的到。
  1. 测试

  1. 观察有异常是的拦截器执行情况

  1. 作业

将上面的异常处理类处理后的视图转到jsp中。

第22节

在springboot中使用日志

  1. 日志的级别

debug-info-warn-error

日志的级别越低则输出的内容越多,越详细。

  1. 记录日志的几种方案
  1. System.out.println()打印或者自己写文件
  2. 使用log4j,slf4j等记录

建议使用log4j或者slf4j记录,不使用sysout因为它和业务代码在同一个线程中会造成业务代码的阻塞(同步执行),而log4j等是异步的操作。并且,log4j等有良好的可以自定义的输出格式。

  1. 通过配置使用slf4j日志

在application.properties文件中通过设置以下键值对来配置日志:

logging.level.org.spring work=debug

logging.file=springboot.log

logging.file.max-size=10M

springboot会根据配置,每天生产一个log文件,如果配置了文件大的最大尺寸则满足最大尺寸的时候会再次生成一个新的log文件,如图:

这样的话,如果网站的日志比较多可能一天会产生多个log文件。在生产环境中,我们建议设置的级别error。

  1. 通过程序使用slf4j日志

 

以上分别是UserController.java中的代码和springboot.log文件中的日志。即导入slf4j下的Logger并声明logger对象,然后在需要记录日志的地方通过loger.debug()或者loger.error()等方法记录日志。需要注意的是,只有满足application.properties中设置的级别时才能记录到日志文件中。

 

 

 

 

 

 

 

 

 

 

 

 

第23节

默认配置情况下访问静态资源

  1. 上课前的准备

以springbootcomponents工程为例,新建以上目录,并在每个目录添加test.txt,内容为路径名称,方便区分,网站结构如下:

 

按照左图所示的工程结构,新建如下目录:

classpath:/ -INF/resources
classpath:/resources
classpath:/static
classpath:/public
/webapp

/webapp/txt

新建好以上目录后,在每个目录添加test.txt,内容为所在路径名称,方便访问时区分。

 

  1. 什么是默认配置?
  1. 关于静态资源的任何键值对都不在appllication.properties中进行配置
  2. 默认配置项和项的值如下:

server.servlet.path=/

spring.resources.static-locations=classpath:/ -INF/resources,classpath:/resources,classpath:/static/,classpath:/public/

spring.mvc.static-path-pattern=/**

以上2个是等价的。

  1. 什么是网站的根目录?

当前看到的目录,即网站的根目录,例如上图,该网站根目录下有5个子目录。

  1. 默认情况下springboot如何寻找静态资源?

默认按照static-locations中定义的路径和网站根目录寻找资源。并且寻找资源时按照一定的优先级顺序查找资源,优先级越高的目录越最先被访问,默认优先级的顺序为:classpath:/ -INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,/webapp/

  1. 如何更改默认的优先级?

调整static-locations中目录的顺序即可调整优先级,目录之间用英文逗号隔开。如下:

另外,无论怎么调整优先级,都可以访问的到/webapp目录下的资源,并且,/webapp在以上所有路径中的优先级是最低的,即如果以上路径都找不到所要的资源,最终都会找webapp,如果webapp下也不存在该资源则报404。

  1. 如何只设定某一个(些)静态资源目录?

通过static-locations设置即可,例如:spring.resources.static-locations=classpath:/static/这样的话,只会搜索classpath:/static/和网站根目录,其他默认的路径被覆盖。

  1. 如何访问网站之外的目录?

通过在static-locations中添加file:目录地址的方式来添加这个目录,同时也受优先级规则的影响,例如:spring.resources.static-locations=file:e:/upload,classpath:/static/

这时即可以通过http://localhost:8080/components/a.jpg地址访问e:/upload中名称为a.jpg的图片。

  1. 配置访问路径的虚拟映射

通过设置spring.mvc.static-path-pattern的值来配置虚拟映射路径,它的默认值为/**,在默认配置下,访问静态资源只需要按照相对路径访问即可。也可以自定义,例如:

spring.mvc.static-path-pattern=/abc/**,这样的话,再访问静态资源时,就只能通过类似http://localhost:8080/components/abc/a.jpg这样的访问路径,才可以访问到e:/upload中的a.jpg图片。

 

第24节

非默认情况下访问静态资源

  1. 说明

上一节的默认情况,主要指的是dispatherServlet的访问规则为/的情况下,这一节非默认情况指的是在更改这个规则的情况下,例如改成*.do之后。

  1. 修改dispatherservlet的映射规则

例如,将默认的/改成*.do之后,即server.servlet.path=*.do,再次访问入上述链接地址:http://localhost:8080/components/test.txt则所有static-location下的资源都将无法访问,而是访问的/webapp目录中的资源。可见,/webapp下的资源不受dispatherservlet访问规则的影响,什么时候都可以访问的到。

 

 

  1. 访问优先级

没有优先级之分了,因为只能访问webapp下的资源了。即static-locations的设置不再起作用。

  1. 虚拟路径

虚拟路径static-path-pattern的设置也不再起作用。

  1. 建议

按照默认的走即可,如果需要访问外部目录则设置一下static-locations就好。例如:

spring.resources.static-locations=file:e:/upload,classpath:/static/

 

第25节

在springboot工程中使用mybatis

  1. 开课前的准备
  1. 新建springbootmybatis的war工程并建好相应的包和POJO等类
  2. 新建springbootmybatis库,包含product和account两个表
  3. 本节实现通过pid查询product表产品的基本信息并返回json数据的需求
  1. 程序编码
  1. 添加依赖

Web依赖,mybatis依赖,mysql依赖,C3PO依赖添加到pom. 中,这一步在新建工程的时候已经自动添加了。

  1. 基本编码

Pojo,dao,service,controller跟之前的编码过程一模一样,xxxMapper. 的编写跟之前也是一样的,代码见工程,没有粘贴。注意事项:mapper名称、命名空间的路径、方法id值、POJO的别名。

 

  1. 支持实现
  1. 配置application.properties

2)添加注解

 

  1. 在每一个mapper接口上使用@Mapper注解
  2. 在入口类上使用mybatis提供的@MapperScan(“包名”)注解来批量扫描

  1. 测试

1)通过链接访问是否成功

2)查看控制日志,可以看到连接池默认属性信息

  1. 配置日志

配置完毕后,再次访问,控制台打印出了SQL语句和参数等信息,如图:

  1. 备注

@MapperScan也可以不用在入口类上,其实只要让入口类扫到该注解即可,例如:

在cn.buba.scan包中新建一个类,添加如上两个注解即可达到同样的效果,其他的注解例如@ServletComponentScan也可以这样使用。

 

 

 

 

 

 

 

 

 

 

 

 

 

第26节

在springboot工程中使用JDBC事务以及演示

1.开课前的准备

1)继续使用springbootmybatis工程

2)使用springbootmybatis库的account表并初始化好数据

3)准备好POJO,AccountMapper. 和AccountMapper.java

4) 本节实现小李给小张转账,并用事务控制操作过程

2.回顾spring中声明式事务的配置

1)声明TrasactionManger和配置切点切面

2)事务控制的本质就是让所有的执行数据库的方法使用同一个Connection对象

3.事务控制的必要性

1)产生严重的业务逻辑错误

2)加不加事务控制完全取决于业务需求

3)只有一个方法在操作数据库的时候,可以不加事务控制,加不加效果是一样的

4.spring中事务的配置

5.springboot中使用事务支持

  1. 加入JDBC依赖,此时就可以自动的配置上述 中的TrasactionManager对象
  2. 在需要的方法上使用@Trasaction注解

6.编码AccountMapper. ,AccountMapper.java,AccountService.java,AccountController.java

  1. 测试
  1. 未加事务控制的测试
  2. 增加事务控制以后的测试
  3. 通过测试,发现加了事务控制以后,两个方法同时操作成功或者同时回滚
  1. 事务的生效条件
  1. 加注解
  2. 必须有数据库本身支持事务
  3. 在事务控制的方法中必须抛出异常的情况下事务才能生效,如果没有抛异常或者抛出的异常被try....catch捕获了,那么事务无法生效。
  1. 课堂练习

自己try....catch后验证事务控制是否生效

 

第27节

使用springdata-redis操作redis数据库

  1. 课前准备

将上一节的springbootmybatis拷贝一份并改名springbootredis,备用

  1. springdata-redis简介
  2. 使用步骤
  1. 加入spring-data-redis依赖

  1. 配置application.properties文件

spring.redis.host=127.0.0.1

spring.redis.port=6379

spring.redis.password=

spring.redis.data =0

  1. 编码

新建RedisTest并使用Controller注解声明为一个Controller,然后注入RedisTemplate和StringRedisTemplate对象,然后进行增删改查的操作即可。如图:

  1. 测试

登录redis-cli -p 6379查看数据是否操作成功

  1. 序列化方式简述

Redis定义了5种数据类型,这5种数据类型是从逻辑上来划分存储结构的。实际上,无论哪种数据类型,在物理存储上都要转换为byte数组。那么,redis在存取数据的时候,将会对存储的数据进行序列化和反序列化。SDR支持不同序列化方式,总的来看,可分为String序列化和JDK序列化方式。其中RedisTemplate和其子类StringRedisTemplate在序列化的方式上有所不同。从源码也可以看出来他们之间支持泛型的不同。

 

第28节

将redis作为mybatis操作的二级缓存使用

  1. 使用步骤
  1. 在入口加@EnableCaching注解,启动注解支持
  2. Controller需要使用缓存的方法上加@Cacheable注解
  3. 将涉及到的POJO类实现序列化接口
  4. controller中代码如下

  1. 测试

http://localhost:8080/getproduct?Id=10访问多次,查看对应方法的执行情况。如果参数等均相同那么第二次访问时不再执行该方法,如果变更了参数则再次走一次该方法,这时在redis中可以看到该缓存的key值。

  1. 注意事项
  1. 上述缓存对所有客户端有效
  2. 需要为@Cacheable指定value值
  3. 为了防止redis缓存中key的覆盖,建议@Cacheable的value使用包名+方法名形式:@Cacheable(value=\"cn.buba.controller.ProductController.getProduct\")

4)该value就是redis中的key,为每一个不同的请求地址产生一个缓存对象,下面是访问http://..../getproduct?id=10和id=11的截图:

5) Controller的方法中如果有多个参数则缓存中的key将会放入一个数组,例如以下controller中有3个参数,则对应redis中缓存的key将会放入数组中:

也可以放入POJO作为参数,但是单独request做参数会报错,原因未查。

6)建议将Cacheable放在Controller的方法上因为Controller的方法对应着用户一个请求,如果放入Dao层就不太好,例如取首页数据可能会涉及到多个Dao.

7)get key名称查看要求key中不能有空格,如果有的话用””引起来否则报错误:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

第31节

在springboot中使用ActiveMQ

  1. 回顾MQ的几个要素
  1. 生成者
  2. broker即MQ服务器的地址tcp://ip:61616
  3. 目的地—Topic和 Queue,这两个接口都继承了Destination接口
  4. 消费者
  1. 本节要实现的功能

在controller的url中输入一个参数,消费者获取这个参数并在eclipse控制台打印

  1. 添加依赖

  1. 配置application.properties文件

#连接MQ集群

#spring.activemq.broker-url=failover:(tcp://localhost:61616,tcp://localhost:61617)

#单机MQ地址

spring.activemq.broker-url=tcp://localhost:61616

#关闭超时

spring.activemq.close-timeout=5000

#最大连接数

spring.activemq.pool.max-connections=100

#发送消息超时时间

spring.activemq.send-timeout=3000

#用户名

spring.activemq.user=system

#密码

spring.activemq.password=manager

  1. 生产者-JmsMessagingTemplate

  1. 配置目的地-ActiveMQQueue

这样,在producer中注入的的Queue就是这个Queue.

  1. 消费者-@JmsListener

  1. 入口类-@EnableJms

该注解的作用为注解支持,以便能够解析@JmsListener等注解

 

 

第32节

几个注解

  1. RestController

该注解用在类上,它的作用有2个方面:第一,实现了Controller本有的功能,第二,在该类的所有方法上返回值将以json形式返回,即实现了ResponeBody的功能。

  1. GetMapping(“/test”)

用在Controller中的方法上,它的作用等价于RequestMapping+Get请求

  1. PostMapping(“/test”)

用在Controller中的方法上,它的作用等价于RequestMapping+Post请求

4.ImportResource(“ ”)

用在类上,它的作用是引入外部的 配置文件,并实例化配置文中的bean

 

第33节

Springboot中使用shiro的方式

  1. 将spring. 中的配置使用java实现

@Configuration

public class ShiroConfig {

    @Bean

    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {

        System.out.println(\"ShiroConfiguration.shirFilter()\");

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //拦截器.

        Map<String,String> filterChainDefinitionMap = new edHashMap<String,String>();

        // 配置不会被拦截的链接 顺序判断

        filterChainDefinitionMap.put(\"/static/**\", \"anon\");

        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了

        filterChainDefinitionMap.put(\"/logout\", \"logout\");

        //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;

        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->

        filterChainDefinitionMap.put(\"/**\", \"authc\");

        // 如果不设置默认会自动寻找Web工程根目录下的\"/login.jsp\"页面

        shiroFilterFactoryBean.setLoginUrl(\"/login\");

        // 登录成功后要跳转的链接

        shiroFilterFactoryBean.setSuccessUrl(\"/index\");

 

        //未授权界面;

        shiroFilterFactoryBean.setUnauthorizedUrl(\"/403\");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;

    }

 

    @Bean

收藏 打印
您的足迹: