ssm的框架:
Spring:利用IOC(控制反转)来为所有的组件创建、封装、注入、管理。不需要手动创建对象,可以自动依赖注入,利用了AOP(声明式事务)。
SpringMVC:负责对客户端与服务器响应做出处理。
Mybatis:实现持久化层的操作,基于JDBC原理,把实体类和SQL语句之间建立了映射关系。
1)spring的工作原理
- spring 是按照设计模式精心打造的,它实现了工厂模式的工厂类,这个类名为BeanFactory(接口),在程序中通常使用它的子类ApplicationContext(也是接口//程序上下文)。
- spring的核心是IOC(控制反转)容器,IOC也是一种编程思想,用于实现模块之间的解耦,在Spring中它的作用是对对象的创建,维护和销毁等生命周期的控制。IOC:把对象的创建、初始化、销毁交给spring来管理,而不是由开发者控制,实现控制反转。
- spring是一个大的工厂类,spring的特点就是基于配置,在其配置文件中通过< bean >元素来创建实例对象。
- 根据业务逻辑来看,对象经常不是独立的,一个对象的创建往往涉及另一个对象的创建,当然这个对象也要由IOC容器负责,负责的方式就是依赖注入DI,通过反射机制实现。有三种注入方式:(1)接口注入(2)构造器注入(3)Setter方法注入。
2)spring的核心技术
- spring的核心技术有:IOC(反转控制)有助于应用对象之间的解耦,AOP(面向切面编程)可以实现横切关注点与他们所影响的对象之间的解耦。
java 的高级特性:反射机制,代理
AOP:面向切面编程,AOP主要包含了通知、切点和连接点等术语。
- Before 在方法被调用之前调用通知
- After 在方法完成之后调用通知,无论方法执行是否成功
- After-returning 在方法成功执行之后调用通知
- After-throwing 在方法抛出异常后调用通知
- Around 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
面向切面编程,系统中有很多各不相干的类的方法,在这众多方法中加入某种系统功能的代码,如加入日志,权限判断等,AOP可以实现横切关注点(如日志,安全,缓存和事务管理)与他们所影响的对象之间的解耦。
- 实现AOP 功能采用的是代理技术,调用代理类,代理类与目标类具有相同的方法声明。
AOP 在spring中主要表现在两个方面:提供声明式的事务管理、spring支持用户自定义切面。
3)spring的优缺点
Spring 的核心概念是IOC和AOP,这两个核心服务的对象算是bean(POJO),定位是一个轻量级的框架,但是随着他的发展变得很庞大,我们称它为spring 全家桶。
优点:
- spring中避免了关键字new造成的耦合问题。
- spring本身就是一个工厂,不需要再编写工厂类了。
- spring不需要进行明确的引用关系的传递,直接通过配置完成
- 所有框架几乎都可以在spring中整合在一起使用。
- spring编程=factory设计模式+proxy设计模式
缺点
- spring基于大量的xml 配置文件,使得我们花了大量的时间放在配置上,拖慢了开发的进度,springboot 问世后,提倡代码优于配置解决了这个问题。
- spring 的内容太庞大,随便打断点查看的时候会出现十几二十层代码,阅览性不强,在实际开发的过程中spring的角色更像是胶水一样,充当整合各种技术的角色,同时作为bean的容器。
xml配置方式
在xml中,我们使用如下AOP配置元素声明切面
`<aop:advisor>` | 定义AOP通知器
`<aop:after>` | 定义AOP后置通知(不管该方法是否执行成功)
`<aop:after-returning>` | 在方法成功执行后调用通知
`<aop:after-throwing>` | 在方法抛出异常后调用通知
`<aop:around>` | 定义AOP环绕通知
`<aop:aspect>` | 定义切面
`<aop:aspect-autoproxy>` | 定义`@AspectJ`注解驱动的切面
`<aop:before>` | 定义AOP前置通知
`<aop:config>` | 顶层的AOP配置元素,大多数的<aop:*>包含在<aop:config>元素内
`<aop:declare-parent>` | 为被通知的对象引入额外的接口,并透明的实现
`<aop:pointcut>` | 定义切点
定义切面
我们在com.etc,service
层添加类XmlAopDemoUserLog
实现了拦截方法:
package com.ganji.demo.service.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* Created by admin on 2015/9/2.
*/
public class XmlAopDemoUserLog {
//方法执行前通知
public void beforeLog() {
System.out.println("开始执行前置通知 日志记录");
}
//方法执行完后通知
public void afterLog() {
System.out.println("开始执行后置通知 日志记录");
}
//执行成功后通知
public void afterReturningLog() {
System.out.println("方法成功执行后通知 日志记录");
}
//抛出异常后通知
public void afterThrowingLog() {
System.out.println("方法抛出异常后执行通知 日志记录");
}
//环绕通知
public Object aroundLog(ProceedingJoinPoint joinpoint) {`
Object result = null;
try {
System.out.println("环绕通知开始 日志记录");
long start = System.currentTimeMillis();
//有返回参数 则需返回值
result = joinpoint.proceed();
long end = System.currentTimeMillis();
System.out.println("总共执行时长" + (end - start) + " 毫秒");
System.out.println("环绕通知结束 日志记录");
} catch (Throwable t) {
System.out.println("出现错误");
}
return result;
}
}
xml中声明切面并调用
在webapp
层 dispatcher-servlet.xml
中定义切面
<!--定义切面 指定拦截方法时 做什么-->
<bean id="xmlAopDemoUserLog" class="com.ganji.demo.service.aspect.XmlAopDemoUserLog"></bean>
<aop:config>
<aop:aspect ref="xmlAopDemoUserLog"> <!--指定切面-->
<!--定义切点-->
<aop:pointcut id="logpoint" expression="execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..))"></aop:pointcut>
<!--定义连接点-->
<aop:before pointcut-ref="logpoint" method="beforeLog"></aop:before>
<aop:after pointcut-ref="logpoint" method="afterLog"></aop:after>
<aop:after-returning pointcut-ref="logpoint" method="afterReturningLog"></aop:after-returning>
<aop:after-throwing pointcut-ref="logpoint" method="afterThrowingLog"></aop:after-throwing>
</aop:aspect>
</aop:config>
最后在控制器com.etc.controller
下创建的控制器中调用:
DemoUserEntity demoUser=userService.GetDemoUser(1);
运行起来可以看见打印如下日志:
- 开始执行前置通知 日志记录
- 开始执行后置通知 日志记录
- 方法成功执行后通知 日志记录
自动注解配置AOP
上面通过xml配置的形式 实现了AOP编程,
现在我们通过配置注解的形式实现AOP。
- 在xml的根目录beans下引用aop的命名空间和xsi
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
webapp层的web-inf/dispatcher-servlet.xml
文件中配置如下一句话即可<aop:aspectj-autoproxy />
(将切面在spring上下文中声明成自动代理bean)
声明一个切面,只需要在类名上添加@Aspect
属性即可,具体的连接点,我们用@Pointcut
和@Before
、@After
等标注
在声明前 我们需要在IDEA依赖配置pom.XML
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.0</version>
</dependency>
声明切面类,包含了注解@Aspect
以及何时(如@Before
)执行通知
package com.ganji.demo.service.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Service;
/**
* Created by admin on 2015/9/2.
*/
@Aspect
@Service
public class XmlAopDemoUserLog {
// 配置切点 及要传的参数
@Pointcut("execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..)) && args(id)")
public void pointCut(int id){ }
// 配置连接点 方法开始执行时通知
@Before("pointCut(id)")
public void beforeLog(int id) {
System.out.println("开始执行前置通知 日志记录:"+id);
}
// 方法执行完后通知
@After("pointCut(id)")
public void afterLog(int id) {
System.out.println("开始执行后置通知 日志记录:"+id);
}
// 执行成功后通知
@AfterReturning("pointCut(id)")
public void afterReturningLog(int id) {
System.out.println("方法成功执行后通知 日志记录:"+id);
}
// 抛出异常后通知
@AfterThrowing("pointCut(id)")
public void afterThrowingLog(int id) {
System.out.println("方法抛出异常后执行通知 日志记录"+id);
}
// 环绕通知
@Around("pointCut(id)")
public Object aroundLog(ProceedingJoinPoint joinpoint,int id) {
Object result = null;
try {
System.out.println("环绕通知开始 日志记录"+id);
long start = System.currentTimeMillis();
//有返回参数 则需返回值
result = joinpoint.proceed();
long end = System.currentTimeMillis();
System.out.println("总共执行时长" + (end - start) + " 毫秒");
System.out.println("环绕通知结束 日志记录");
} catch (Throwable t) {
System.out.println("出现错误");
}
return result;
}
}
SpringMVC概念:
他是一个轻量级的开源框架,应用于表现层,基于MVC的设计模式.
SpringMVC的特点:
- 他是单例的可以设置成多例.
- 他的线程是安全的
- 他是基于方法级别的拦截
- 接受请求参数的方式是参数绑定
- 携带参数到页面是通过request域对象.
SpringMVC流程(重点)
- 用户向服务器发送一个请求,被SpringMVC的前端控制器DispatchServlet 捕获.
- DispatcherServlet接收到请求后调用HandlerMapping处理器映射器.
- 处理器映射器找到具体的处理器(xml配置或者注解,RequesrtMapper),生成处理器对象及处理器拦截器一并返回给DispatcherServlet
- DispatcherServlet调用HandlerAdapter处理器适配器
- HandlerAdapter经过适配器调用具体的处理器(Controller)
- Controller执行完成后返回ModelAndView
- HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- ViewReslover解析后返回具体的View
- DispatcherServlet根据View进行渲染视图
- DispatcherServlet将渲染完的视图界面最后响应给用户.
SpringMVC中的几个组件说明
- DispatcherServlet:前- 端控制器,控制整个流程,他是SpringMVC的入口
- HandlerMapper:处理器映射器
- HandlerAdapter:处理器适配器
- ViewResolver:视图解析器,可以解析JSP,freemarker,pdf等
SpringMVC的三大件:(面试可能会问)
-HandlerMapper
-HandlerAdapter
-ViewResolver
MVC设计模式概念
M-Model(模型,完成业务逻辑:主要有JavaBean构成,service+dao+entity)
V-View(视图层,主要是做页面的展示,jsp,html...)
C-Controller(控制器,主要是接受请求之后调用模型层(M)根据结果返回页面)
SpringMVC常用注解
1.@Controller:标记在类上,他会表明这个类是一个SpringMVC Controller对象.处理器将会扫描该注解的类的方法,并检测该方法是否使用了@RequestMapping注解.@Controller只是定义类控制器类,真正处理请求的注解是@RequestMapping.大多数框架使用的时候都是整合因此在一个类上标记@Controller还不能真正意义上说他是SpringMVC的控制器,这个时候Spring不认识这个注解,需要把控制器类交给Spring来管理,一下又两种方式:
- 直接写这个类的全路径
<bean class="com.xxx.xxx.当前类"/>
- 路径写到当前Controller注解类的上一层
<context:component-scan base-package = "com.xxx"/>
注意当前配置@Controller这个类就不要写上去了Controller不会依赖HttpServletRequest和HttpServletResponse等HttpServlet对象,他是可以直接通过Controller的方法参数获取到的.小Demo
@Controller
public class SaveController() {
@RequestMapping("/save")
public String save() {
System.out.println("保存save");
return "success";
}
}
2.@RequestMapping
RequestMapping是用来处理请求url的注解
RequestMapping中的六个属性:
- --value:请求的实际地址
- --method:请求的类型.GET,POST,PUT,DELETE等
@RequestMapping(value="",method="RequestMethod.GET") - --consumes:指定请求的提交内容的类型(Content-Type),例如text/html
- --produces:指定返回的内容类型
- --params:指定request中必须包含某些参数值,才让该方法进行处理
- --headers: 指定request中必须包含某些指定的header值,才让该方法处理请求
3.@ResponseBody
该注解用于将Controller的方法返回对象通过HtpMessageConverter转换成指定个时候写到Response对象的body数据中,
使用场景:当返回的数据不是html标签,而是其他的数据格式比如json,xml等使用.
4.@PathVariable
用于将请求url中的模版变量映射到功能处理方法的参数上,取出url模版中的变量作为参数
5.@RequestParam
用于将请求参数区数据映射到功能处理方法的参数上.
6.@CookieValue
- 参数: value 参数名
- required:是否必须
- defaultValue:默认值
7.@Resource和@Autowired
他们都是做bean注入时候使用,@Resource不是Spring的注解他的宝石javax.annotation.Resource需要导包,但是Spring支持该注解的注入
- 共同点:两者都可以卸载字段和setter方法上,如果都写在字段上就不需要在写setter方法
- 不同点:
- @Autowired是Spring提供的注解需要导报,按照byType注入,默认情况下他要求依赖对象必须存在,如果允许为null值,设置他的required属性为false.
- @Resource默认按照byName自动注入,他有两个重要的属性,name和type,Spring将该注解的name属性解析为bean的名字,type属性解析为bean的类型,如果想要使用name属性,需要使用byName的自动注入,使用type属性需要使用byType自动注入策略.如果什么属性都不制定,她会通过反射使用byName自动注入策略.
1、MyBatis原理
Mybatis是对jdbc的封装,它让数据库底层操作变的透明。MyBatis应用程序根据XML配置文件创建SqlSessionFactory,SqlSessionFactory再根据配置,配置来源于两个地方:
- 一处是配置文件,
- 一处是Java代码的注解,
获取一个SqlSession。SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句,完成对数据的增删改查和事务提交等,用完之后关闭SqlSession。
2、MyBatis的优缺点
优点:
- 简单易学:MyBatis本身就很小且简单。没有任何第三方依赖,安装只要两个jar文件+配置几个sql映射文件就行了,易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:MyBatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
- 解除sql与程序代码的耦合通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
缺点:
- 编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
- SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
- 框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。 4、二级缓存机制不佳
总结:
MyBatis的优点同样是MyBatis的缺点,正因为MyBatis使用简单,数据的可靠性、完整性的瓶颈便更多依赖于程序员对sql的使用水平上了。sql写在xml里,虽然方便了修改、优化和统一浏览,但可读性很低,调试也非常困难,也非常受限。
- Spring boot是Spring家族中的一个全新的框架,它用来简化Spring应用程序的创建和开发过程,也可以说Spring boot能简化我们之前采用Spring mvc + Spring+ MyBatis 框架进行开发的过程;
- 在以往我们采用 Spring mvc + Spring + MyBatis 框架进行开发的时候,搭建和整合三大框架,我们需要做很多工作,比如配置web.xml,配置Spring,配置MyBatis,并将它们整合在一起等,而Spring boot框架对此开发过程进行了革命性的颠覆,完全抛弃了繁琐的xml配置过程,采用大量的默认配置简化我们的开发过程;
- 所以采用Spring boot可以非常容易和快速地创建基于Spring 框架的应用程序,它让编码变简单了,配置变简单了,部署变简单了,监控变简单了;
什么是SpringBoot?
SpringBoot是一个快速开发框架,快速的将一些常用的第三方依赖整合(原理:通过Maven子父工程的方式),简化XML配置,全部采用注解形式,内置Http服务器(Jetty和Tomcat),最终以java应用程序进行执行。
SpringBoot核心原理
- 基于SpringMVC无配置文件(纯Java)完全注解化+内置tomcat-embed-core实现SpringBoot框架,Main函数启动。
- SpringBoot核心快速整合第三方框架原理:Maven继承依赖关系。
Spring boot 的特性
- 能够快速创建基于Spring的应用程序;
2 .能够直接使用java main方法启动内嵌的Tomcat服务器运行Spring boot程序,不需要部署war包文件; - 提供约定的starter POM来简化Maven配置,让Maven的配置变得简单;
4 .根据项目的Maven依赖配置,Spring boot自动配置Spring、Spring mvc等; - 提供了程序的健康检查等功能;
- 基本可以完全不使用XML配置文件,采用注解配置;
SpringBoot 的启动原理
//我们打开POM.XML, 注意看下面两个依赖:
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<!-- Add typical dependencies for a web application -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
项目就会自动给我们导入关于WEB项目所需要的配置和JAR
开发任何一个Spring Boot项目,都会用到如下的启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
可以看出注解定义(@SpringBootApplication)和类定义(SpringApplication.run)且项目的启动也是从这里运行的
SpringBootApplication
@Target(ElementType.TYPE) // 注解的适用范围,其中TYPE用于描述类、接口(包括包注解类型)或enum声明
@Retention(RetentionPolicy.RUNTIME) // 注解的生命周期,保留到class文件中(三个生命周期)
@Documented // 表明这个注解应该被javadoc记录
@Inherited // 子类可以继承该注解
@SpringBootConfiguration // 继承了Configuration表示当前是注解类(也是Springboot的注解配置)
@EnableAutoConfiguration // 开启springboot的注解功能,springboot的四大神器之一,其借助@import的帮助
@ComponentScan(excludeFilters = { // 扫描路径设置(具体使用待确认)
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
前面 4 个是注解的元数据信息,
虽然定义使用了多个Annotation进行了原信息标注,但实际上重要的只有三个Annotation(注解):
- @Configuration(@SpringBootConfiguration点开查看发现里面还是应用了@Configuration)
- @EnableAutoConfiguration
- @ComponentScan
所以,如果我们使用如下的SpringBoot启动类
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这里使用到了三个注解样式:
@Configuration
@Configuration对我们来说不陌生,它就是JavaConfig形式的Spring Ioc容器的配置类使用的那个@Configuration,SpringBoot社区推荐使用基于JavaConfig的配置形式,所以,这里的启动类标注了@Configuration之后,本身其实也是一个Ioc容器的配置类。
@ComponentScan
@ComponentScan这个注解在Spring中很重要,它对应XML配置中的元素,@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到Ioc容器中。
我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。
@EnableAutoConfiguration
@EnableAutoConfiguration这个Annotation最为重要。Spring中也定义了很多@Enable开头的注解。比如@EnableScheduling、@EnableCaching、@EnableMBeanExport等,他们都是通过@import来导入对应的配置类。@EnableAutoConfiguration的理念和做事方式其实一脉相承,简单概括一下就是,借助@Import的支持,收集和注册特定场景相关的bean定义。
- @EnableScheduling是通过@Import将Spring调度框架相关的bean定义都加载到IoC容器。
- @EnableMBeanExport是通过@Import将JMX相关的bean定义加载到IoC容器。
而@EnableAutoConfiguration也是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器注:所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages
版权属于:月丶小柒’s Blog
本文链接:https://www.xiaoqi22.cn/20190907/cid=86.html
版权声明:若无注明,本文皆为“月丶小柒’s Blog”原创,所有原创文章采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。 您可以自由的转载和修改,但请务必注明文章来源且不可用于商业目的