第一节
Spring技术的3个大的发展历史阶段
- spring1.x版本阶段
所有的依赖关系,都是使用 进行描述——不管是IOC还是AOP的关系都是这样处理,都是历史背景决定的。
- spring2.x版本阶段
伴随着JDK1.5而来,它支持注解,使得 配置文件的体积大大减小了,配置文件的数量也大大减少了。争论了很久 ,最终统一了使用方式:一些系统的配置使用 完成,一些业务逻辑配置使用注解。
- spring3.x-spring4.x版本阶段
彻底的摆脱 配置,完全使用注解+java类的形式。目前项目中还没有完全使用该种方式,以后纯使用该方式的机会也不大,因为springboot技术出来了,它就是建立在0配置技术之上的一种技术——换句话说,springboot改变了我们使用spring的姿势。
第二节
使用注解+javabean的方式实现Bean的注入
- 需要声明,该节内容并非springboot内容,而是演示如何零配置实现我们的IOC注入,注解+javabean的形式
- 程序的实现
- 首先建立一个工程,我们在这里建立一个再普通不过的java工程,工程结构如如:
- 编写相应的dao,service,test等类,另外还要编写一个java配置类
- 测试
执行MainTest,查看是否能够执行到UserDao的被调用的方法,测试成功。
4)备注
@Bean注解要求方法必须是public,返回值是注入要注入的对象的类型
第3节
创建我的第一个springboot工程
- 如何创建springboot工程?
- 创建一个普通的maven工程,然后手动将需要的springboot依赖添加进去即可
- 使用springboot官方网站来生成springboot工程的骨架,然后导入到IDE即可
- 使用springboot提供的一个IDE插件STS,该插件集成到我们的IDE中
- 使用第三种方式即STS创建我们的springboot工程
- 选择new-project-spring-spring starter project
2)填写工程基本信息,要求必须联网才能正常执行否则报连接错误的异常
3)创建工程,如果有需要的话在这里可以修改springboot的版本号
备注:
- 如果第一次创建工程的话,花费的时间会比较长,因为很多依赖需要下载。
- 本即可主要掌握使用STS插件创建springboot工程,另外需要注意必须联网该插件才能正常执行。
- Springboot2.0只支持JDK1.8以上的版本
- 随着官网http://start.spring.io上面版本的更改STS插件也会跟着更改版本信息。
- 简单讲解工程结构和引入的maven依赖包
第4节
编写我的第一个springboot应用程序
- 在上节工程springboothelloworld基础上编写程序
- 正式编写
- 修改pom. 给定一个jar包的文件名称
- 编写pojo,dao,service,controller
这里编写的pojo,dao等所有组件跟之前springmvc工程中的所用注解或者编写流程一模一样,没有任何区别,参考代码。
- 测试
- 通过springboot的入口程序启动
- 通过java -jar xxx.jar来启动,可能受第一次影响占用8080,关闭eclipse即可
- 启动日志简单分析
可以看到,内置了8.5的tomcat,并且默认端口为8080.访问地址http://localhost:8080/getuser?id=1000
第5节
剖析springboot工程——工程结构
|
第一节 Spring技术的3个大的发展历史阶段
所有的依赖关系,都是使用 进行描述——不管是IOC还是AOP的关系都是这样处理,都是历史背景决定的。
伴随着JDK1.5而来,它支持注解,使得 配置文件的体积大大减小了,配置文件的数量也大大减少了。争论了很久 ,最终统一了使用方式:一些系统的配置使用 完成,一些业务逻辑配置使用注解。
彻底的摆脱 配置,完全使用注解+java类的形式。目前项目中还没有完全使用该种方式,以后纯使用该方式的机会也不大,因为springboot技术出来了,它就是建立在0配置技术之上的一种技术——换句话说,springboot改变了我们使用spring的姿势。
第二节 使用注解+javabean的方式实现Bean的注入
UserDao: UserService: SpringConfig: MainTest:
执行MainTest,查看是否能够执行到UserDao的被调用的方法,测试成功。 @Bean注解要求方法必须是public,返回值是注入要注入的对象的类型
第3节 创建我的第一个springboot工程
2)填写工程基本信息,要求必须联网才能正常执行否则报连接错误的异常 3)创建工程,如果有需要的话在这里可以修改springboot的版本号 备注:
第4节 编写我的第一个springboot应用程序
这里编写的pojo,dao等所有组件跟之前springmvc工程中的所用注解或者编写流程一模一样,没有任何区别,参考代码。
可以看到,内置了8.5的tomcat,并且默认端口为8080.访问地址http://localhost:8080/getuser?id=1000
第5节 剖析springboot工程——工程结构
在springboot目录结构中,遵循的原则就是“约定大于配置”,使得配置文件更加简化,容易维护,可以把它看成是行业标准。
第6节 剖析springboot工程——pom. 文件
从该父依赖中继承了springboot工程必须的一些jar包,该父依赖是springboot工程中必不可少依赖,它也是区别普通mavven工程的一个特点。
例如,上午创建的工程为web工程,那么它就自动添加了如下一类,如图:
这是springboot帮我们提供的一个插件,该插件可以根据第5节讲到的约定目录帮助我们将工程打包成可执行的jar包或者war包,如果没有这个插件,我们必须手动写pom代码。
第7节 剖析springboot工程——入口类
默认情况,该入口类会在比较父级的目录中,因为它要扫描同级目录和所有的子目录中带有spring注解的类(需要在spring容器创建对象)。如果放到子目录中必须指定要扫描的包的路径,不推荐这样做,按默认即可,例如: 备注: Run方法中传入两个参数,第一个参数默认传入本类的class,也可以传入一个其他类,但是该类必须有SpringBootApplication注解。
该注解是springboot工程的核心注解,没了它运行不了,同时它也是一个组合注解。 如图是定义该注解的代码: 即一旦使用了该注解,等价于把上面所有的注解都使用上了。总之,使用了该注解以后这个入口类就是一个java配置类,并且有了自动配置功能,并且还有了自动扫包的功能。
根据上述描述,入口类由一个main方法启动,就会启动内嵌的tomcat或jetty容器,然后加载所有需要加载的或扫描的类或资源文件,进而初始化spring容器,完成对象的注入。
第8节 剖析springboot工程——可执行jar包和war包
备注:该配置文件是自动生成的,它里面指定了启动类,在执行java -jar命令的时候会自动加载该启动类。
将第3节课工程中pom. 中的packaging值由原来的jar直接改为war,其他配置不做任何改变,然后打成war包,其结构如下: 备注:通过java -jar helloworld.war命令执行该war包,成功。但是非jsp的应用一般不建议打war包。
第9节 认识springboot工程的配置文件——application.properties文件
Application.properties和application.yml
为了满足个性化的需求,所以该框架提供了一个简单的配置文件,通过健值对的形式去配置自己的参数,并且这些健同application.properties名字一样,也是约定好的,springboot就可以自动读取这些键值对,不需要我们另外写程序完成。
server.port=8090 server.servlet.context-path=/helloworld
第10节 springboot工程的特点小结
第10节 自定义springboot启动时的banner图标
打开http://patorjk.com/software/taag输入自己想要的文字,免费帮我们只做一个banner字符样式,不支持中文字符,例如:
备注:
第11节 springboot自动配置的原理
当在pom. 中一旦引入了某一个starter组件,那么就会在里找相应的自动配置类来实现自动配置。
打开一个XXAutoConfiguration的类,即可看到里面自动配置的实现过来,例如solr. 实现部分代码如下:
本质还是使用spring中的@Configration和@Bean两个注解实现了将SolrClient对象注入到spring容器。此时,我们就可以在我们的程序中直接使用@Autowired注入solrClient对象去使用了,因为它已经存在于spring容器中了。
第12节 关闭springboot的自动配置
一般情况下,不建议手动配置。
第13节 将springboot项目发布到独立的tomcat
不能。
因为该war包中缺少一个非常重要的文件——web. 文件,所以外部tomcat在启动时无法知道该项目是一个标准的web项目,所以也就无法访问。备注:tomcat启动日志未看到springboot的banner图标。
这是跟上次失败实验的一个不同之处,说明tomcat已经将该项目进行了加载。 第14节 在springboot项目中配置MVC并使用jsp作为视图模板
freemarker或者thymeleaf等模板。
<dependency> <groupId>org.apache.tomcat. </groupId> <artifactId>tomcat- -jasper</artifactId> </dependency>
server.port=8080 server.servlet.context-path=/hellojsp server.servlet-path=/ spring.mvc.view.prefix=/jsp/ spring.mvc.view.suffix=.jsp 备注:
只需写一个简单的controller类和user.jsp即可,结构和内容如下:
第15节 使用@PropertySource读取外部资源文件
2.使用注解的方式来完成读取 1)在springboothelloworld工程中做测试,新建ReadProperties,编码如下: 备注:
3.在程序中使用该类,例如在Dao层访问,然后通过controller访问并测试
4.注意事项 读取properties文件中的username属性值时,得不到正确的结果,得到是本地计算机的名称,例如: 得到的值:
第16节 在springboot工程中使用servlet
准备springbootcomponents工程,新建cn.buba.servlet包,在这个包下新建两个servlet——ServletOne和ServletTwo。注意:先新建ServletOne,走通后再建ServletTwo,新建ServletTwo的目的在于演示url匹配规则优先级。
2)在springboot入口类添加ServletComponetScan注解 访问http://localhost:8080/one/abc或者http://localhost:8080/one/aaa等,如下: 可以看到,servlet只进行了一次初始化——第一次被访问的时候。以后其他人再访问的时候初始化方法就不再执行。
访问http://localhost:8080/one/abc/123执行给结果:
访问http://localhost:8080/one/abcd/123执行给结果: 小结:
第17节 在springboot工程中使用Filter
即doFilter()中的代码不是顺序执行的,chain.doFilter()之前的代码在目标代码执行之前执行,chain.doFilter()之后的代码在目标方法执行完之后执行。
编写FilterTwo,完成以下内容:
第18节 在springboot中使用监听器
对request对象的监听; 对session的监听,包括session的创建、销毁、属性值的绑定、解绑等; 对application对象的监听,包括容器的启动、关闭等。
加起来有10个基本的接口,我们拿着ServletContextListener接口做演示。过程如下:
备注:
在controller或者servlet或者jsp中获取上述程序中的encording值。
第19节 在springboot工程中使用拦截器
在1.8版本以上可以使用default和static关键字来修饰我们的方法,在这类方法上可以写具体的实现,这样在实现类上就必须每一个方法都要实现一次了,只需要重写自己需要的方法。
实现上述接口,并重写里面的方法,最后为该类添加@Component注解,代码如下:
启动程序,执行http://localhost:8080/getuser连接,后台打印结果如下: 备注:见代码。
当项目有过滤器和拦截器的时候,当在都满足URL规则的时候,Filter先执行——再执行拦截器——目标方法——Filter中的chain.doFilter()之后的代码。如图:
多个拦截器的执行顺序跟在配置类中添加的顺序一致,先添加的先执行。如图:
第20节 单元测试—RunWith、SpringBootTest、Test注解
因为单元测试比较方便,不需要来回重启web服务器,也不需要在浏览器输入地址。
要想使用web环境下的单元测试,必须提供一个web环境来支持我们的web组件,例如从request中取值,这时没有web环境是无法做到测试的。为了解决上述问题,springboot提供了两个注解来帮我们实现目的。具体的使用如下:
不在controller中使用上述注解,而是写一个单独的类。如下代码所示:
Junit对测试方法的签名有3个要求必须要满足,否则无法进行单元测试,如下:
第21节 异常处理—ControllerAdvice和ExceptionHandler注解
springmvc. 内容: error.jsp内容:
备注:
将上面的异常处理类处理后的视图转到jsp中。 第22节 在springboot中使用日志
debug-info-warn-error 日志的级别越低则输出的内容越多,越详细。
建议使用log4j或者slf4j记录,不使用sysout因为它和业务代码在同一个线程中会造成业务代码的阻塞(同步执行),而log4j等是异步的操作。并且,log4j等有良好的可以自定义的输出格式。
在application.properties文件中通过设置以下键值对来配置日志: logging.level.org.spring work=debug logging.file=springboot.log logging.file.max-size=10M springboot会根据配置,每天生产一个log文件,如果配置了文件大的最大尺寸则满足最大尺寸的时候会再次生成一个新的log文件,如图: 这样的话,如果网站的日志比较多可能一天会产生多个log文件。在生产环境中,我们建议设置的级别error。
以上分别是UserController.java中的代码和springboot.log文件中的日志。即导入slf4j下的Logger并声明logger对象,然后在需要记录日志的地方通过loger.debug()或者loger.error()等方法记录日志。需要注意的是,只有满足application.properties中设置的级别时才能记录到日志文件中。
第23节 默认配置情况下访问静态资源
以springbootcomponents工程为例,新建以上目录,并在每个目录添加test.txt,内容为路径名称,方便区分,网站结构如下:
server.servlet.path=/ spring.resources.static-locations=classpath:/ -INF/resources,classpath:/resources,classpath:/static/,classpath:/public/ spring.mvc.static-path-pattern=/** 以上2个是等价的。
当前看到的目录,即网站的根目录,例如上图,该网站根目录下有5个子目录。
默认按照static-locations中定义的路径和网站根目录寻找资源。并且寻找资源时按照一定的优先级顺序查找资源,优先级越高的目录越最先被访问,默认优先级的顺序为:classpath:/ -INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,/webapp/
调整static-locations中目录的顺序即可调整优先级,目录之间用英文逗号隔开。如下: 另外,无论怎么调整优先级,都可以访问的到/webapp目录下的资源,并且,/webapp在以上所有路径中的优先级是最低的,即如果以上路径都找不到所要的资源,最终都会找webapp,如果webapp下也不存在该资源则报404。
通过static-locations设置即可,例如:spring.resources.static-locations=classpath:/static/这样的话,只会搜索classpath:/static/和网站根目录,其他默认的路径被覆盖。
通过在static-locations中添加file:目录地址的方式来添加这个目录,同时也受优先级规则的影响,例如:spring.resources.static-locations=file:e:/upload,classpath:/static/ 这时即可以通过http://localhost:8080/components/a.jpg地址访问e:/upload中名称为a.jpg的图片。
通过设置spring.mvc.static-path-pattern的值来配置虚拟映射路径,它的默认值为/**,在默认配置下,访问静态资源只需要按照相对路径访问即可。也可以自定义,例如: spring.mvc.static-path-pattern=/abc/**,这样的话,再访问静态资源时,就只能通过类似http://localhost:8080/components/abc/a.jpg这样的访问路径,才可以访问到e:/upload中的a.jpg图片。
第24节 非默认情况下访问静态资源
上一节的默认情况,主要指的是dispatherServlet的访问规则为/的情况下,这一节非默认情况指的是在更改这个规则的情况下,例如改成*.do之后。
例如,将默认的/改成*.do之后,即server.servlet.path=*.do,再次访问入上述链接地址:http://localhost:8080/components/test.txt则所有static-location下的资源都将无法访问,而是访问的/webapp目录中的资源。可见,/webapp下的资源不受dispatherservlet访问规则的影响,什么时候都可以访问的到。
没有优先级之分了,因为只能访问webapp下的资源了。即static-locations的设置不再起作用。
虚拟路径static-path-pattern的设置也不再起作用。
按照默认的走即可,如果需要访问外部目录则设置一下static-locations就好。例如: spring.resources.static-locations=file:e:/upload,classpath:/static/
第25节 在springboot工程中使用mybatis
Web依赖,mybatis依赖,mysql依赖,C3PO依赖添加到pom. 中,这一步在新建工程的时候已经自动添加了。
Pojo,dao,service,controller跟之前的编码过程一模一样,xxxMapper. 的编写跟之前也是一样的,代码见工程,没有粘贴。注意事项:mapper名称、命名空间的路径、方法id值、POJO的别名。
2)添加注解
1)通过链接访问是否成功 2)查看控制日志,可以看到连接池默认属性信息
配置完毕后,再次访问,控制台打印出了SQL语句和参数等信息,如图:
@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中使用事务支持
6.编码AccountMapper. ,AccountMapper.java,AccountService.java,AccountController.java
自己try....catch后验证事务控制是否生效
第27节 使用springdata-redis操作redis数据库
将上一节的springbootmybatis拷贝一份并改名springbootredis,备用
spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= spring.redis.data =0
新建RedisTest并使用Controller注解声明为一个Controller,然后注入RedisTemplate和StringRedisTemplate对象,然后进行增删改查的操作即可。如图:
登录redis-cli -p 6379查看数据是否操作成功
Redis定义了5种数据类型,这5种数据类型是从逻辑上来划分存储结构的。实际上,无论哪种数据类型,在物理存储上都要转换为byte数组。那么,redis在存取数据的时候,将会对存储的数据进行序列化和反序列化。SDR支持不同序列化方式,总的来看,可分为String序列化和JDK序列化方式。其中RedisTemplate和其子类StringRedisTemplate在序列化的方式上有所不同。从源码也可以看出来他们之间支持泛型的不同。
第28节 将redis作为mybatis操作的二级缓存使用
http://localhost:8080/getproduct?Id=10访问多次,查看对应方法的执行情况。如果参数等均相同那么第二次访问时不再执行该方法,如果变更了参数则再次走一次该方法,这时在redis中可以看到该缓存的key值。
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
在controller的url中输入一个参数,消费者获取这个参数并在eclipse控制台打印
#连接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
这样,在producer中注入的的Queue就是这个Queue.
该注解的作用为注解支持,以便能够解析@JmsListener等注解
第32节 几个注解
该注解用在类上,它的作用有2个方面:第一,实现了Controller本有的功能,第二,在该类的所有方法上返回值将以json形式返回,即实现了ResponeBody的功能。
用在Controller中的方法上,它的作用等价于RequestMapping+Get请求
用在Controller中的方法上,它的作用等价于RequestMapping+Post请求 4.ImportResource(“ ”) 用在类上,它的作用是引入外部的 配置文件,并实例化配置文中的bean
第33节 Springboot中使用shiro的方式
@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
继续阅读与本文标签相同的文章下一篇 :
Node.js实现简单的GET请求
您的足迹:
|
