ssm的框架:

Spring:利用IOC(控制反转)来为所有的组件创建、封装、注入、管理。不需要手动创建对象,可以自动依赖注入,利用了AOP(声明式事务)。

SpringMVC:负责对客户端与服务器响应做出处理。
Mybatis:实现持久化层的操作,基于JDBC原理,把实体类和SQL语句之间建立了映射关系。

Spring框架的理解:

1)spring的工作原理

  1. spring 是按照设计模式精心打造的,它实现了工厂模式的工厂类,这个类名为BeanFactory(接口),在程序中通常使用它的子类ApplicationContext(也是接口//程序上下文)。
  2. spring的核心是IOC(控制反转)容器IOC也是一种编程思想,用于实现模块之间的解耦,在Spring中它的作用是对对象的创建,维护和销毁等生命周期的控制。IOC:把对象的创建、初始化、销毁交给spring来管理,而不是由开发者控制,实现控制反转
  3. spring是一个大的工厂类,spring的特点就是基于配置,在其配置文件中通过< bean >元素来创建实例对象。
  4. 根据业务逻辑来看,对象经常不是独立的,一个对象的创建往往涉及另一个对象的创建,当然这个对象也要由IOC容器负责,负责的方式就是依赖注入DI,通过反射机制实现。有三种注入方式:(1)接口注入(2)构造器注入(3)Setter方法注入。

2)spring的核心技术

  • spring的核心技术有:IOC(反转控制)有助于应用对象之间的解耦,AOP(面向切面编程)可以实现横切关注点与他们所影响的对象之间的解耦。
    java 的高级特性:反射机制,代理

AOP面向切面编程,AOP主要包含了通知、切点和连接点等术语。

  1. Before 在方法被调用之前调用通知
  2. After 在方法完成之后调用通知,无论方法执行是否成功
  3. After-returning 在方法成功执行之后调用通知
  4. After-throwing 在方法抛出异常后调用通知
  5. 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的容器。

Spring框架的用法:一是xml配置的方式,二是自动注解的模式

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中声明切面并调用
webappdispatcher-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框架

SpringMVC概念:

他是一个轻量级的开源框架,应用于表现层,基于MVC的设计模式.

SpringMVC的特点:

  1. 他是单例的可以设置成多例.
  2. 他的线程是安全的
  3. 他是基于方法级别的拦截
  4. 接受请求参数的方式是参数绑定
  5. 携带参数到页面是通过request域对象.

SpringMVC流程(重点)

  1. 用户向服务器发送一个请求,被SpringMVC的前端控制器DispatchServlet 捕获.
  2. DispatcherServlet接收到请求后调用HandlerMapping处理器映射器.
  3. 处理器映射器找到具体的处理器(xml配置或者注解,RequesrtMapper),生成处理器对象及处理器拦截器一并返回给DispatcherServlet
  4. DispatcherServlet调用HandlerAdapter处理器适配器
  5. HandlerAdapter经过适配器调用具体的处理器(Controller)
  6. Controller执行完成后返回ModelAndView
  7. HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  9. ViewReslover解析后返回具体的View
  10. DispatcherServlet根据View进行渲染视图
  11. 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来管理,一下又两种方式:

  1. 直接写这个类的全路径
    <bean class="com.xxx.xxx.当前类"/>
  2. 路径写到当前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中的六个属性:

  1. --value:请求的实际地址
  2. --method:请求的类型.GET,POST,PUT,DELETE等
    @RequestMapping(value="",method="RequestMethod.GET")
  3. --consumes:指定请求的提交内容的类型(Content-Type),例如text/html
  4. --produces:指定返回的内容类型
  5. --params:指定request中必须包含某些参数值,才让该方法进行处理
  6. --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方法
  • 不同点:
  1. @Autowired是Spring提供的注解需要导报,按照byType注入,默认情况下他要求依赖对象必须存在,如果允许为null值,设置他的required属性为false.
  2. @Resource默认按照byName自动注入,他有两个重要的属性,name和type,Spring将该注解的name属性解析为bean的名字,type属性解析为bean的类型,如果想要使用name属性,需要使用byName的自动注入,使用type属性需要使用byType自动注入策略.如果什么属性都不制定,她会通过反射使用byName自动注入策略.

Mybatis框架

1、MyBatis原理

Mybatis是对jdbc的封装,它让数据库底层操作变的透明。MyBatis应用程序根据XML配置文件创建SqlSessionFactory,SqlSessionFactory再根据配置,配置来源于两个地方:

  • 一处是配置文件,
  • 一处是Java代码的注解,

获取一个SqlSession。SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句,完成对数据的增删改查和事务提交等,用完之后关闭SqlSession。

2、MyBatis的优缺点

优点:
  1. 简单易学:MyBatis本身就很小且简单。没有任何第三方依赖,安装只要两个jar文件+配置几个sql映射文件就行了,易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  2. 灵活:MyBatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
  3. 解除sql与程序代码的耦合通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  4. 提供映射标签,支持对象与数据库的orm字段关系映射
  5. 提供对象关系映射标签,支持对象关系组建维护
  6. 提供xml标签,支持编写动态sql。
缺点:
  1. 编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
  2. SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
  3. 框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。 4、二级缓存机制不佳
    总结:

MyBatis的优点同样是MyBatis的缺点,正因为MyBatis使用简单,数据的可靠性、完整性的瓶颈便更多依赖于程序员对sql的使用水平上了。sql写在xml里,虽然方便了修改、优化和统一浏览,但可读性很低,调试也非常困难,也非常受限


Spring boot框架

  1. Spring boot是Spring家族中的一个全新的框架,它用来简化Spring应用程序的创建和开发过程,也可以说Spring boot能简化我们之前采用Spring mvc + Spring+ MyBatis 框架进行开发的过程;
  2. 在以往我们采用 Spring mvc + Spring + MyBatis 框架进行开发的时候,搭建和整合三大框架,我们需要做很多工作,比如配置web.xml,配置Spring,配置MyBatis,并将它们整合在一起等,而Spring boot框架对此开发过程进行了革命性的颠覆,完全抛弃了繁琐的xml配置过程,采用大量的默认配置简化我们的开发过程;
  3. 所以采用Spring boot可以非常容易和快速地创建基于Spring 框架的应用程序,它让编码变简单了,配置变简单了,部署变简单了,监控变简单了;

什么是SpringBoot?

SpringBoot是一个快速开发框架,快速的将一些常用的第三方依赖整合(原理:通过Maven子父工程的方式),简化XML配置,全部采用注解形式,内置Http服务器(Jetty和Tomcat),最终以java应用程序进行执行。

SpringBoot核心原理

  • 基于SpringMVC无配置文件(纯Java)完全注解化+内置tomcat-embed-core实现SpringBoot框架,Main函数启动。
  • SpringBoot核心快速整合第三方框架原理:Maven继承依赖关系。

Spring boot 的特性

  1. 能够快速创建基于Spring的应用程序;
    2 .能够直接使用java main方法启动内嵌的Tomcat服务器运行Spring boot程序,不需要部署war包文件;
  2. 提供约定的starter POM来简化Maven配置,让Maven的配置变得简单;
    4 .根据项目的Maven依赖配置,Spring boot自动配置Spring、Spring mvc等;
  3. 提供了程序的健康检查等功能;
  4. 基本可以完全不使用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


Last modification:September 12th, 2019 at 10:52 am
如果觉得不错,请随意赞赏