spring全栈分享

1 Spring 基础

1.1 Spring是什么

        Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于XML的配置、基于注解的配置、基于Java的配置。

主要由以下几个模块组成:

Spring Core:核心类库,提供IOC服务;

Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);

Spring AOP:AOP服务;

Spring DAO:对JDBC的抽象,简化了数据访问异常的处理;

Spring ORM:对现有的ORM框架的支持;

Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传;

Spring MVC:提供面向Web应用的Model-View-Controller实现。

1.2 Spring的优点

(1)spring属于低侵入式设计,代码的污染极低;

(2)spring的DI机制将对象之间的依赖关系交由框架处理,减低组件的耦合性;

(3)Spring提供了AOP技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用。

(4)spring对于主流的应用框架提供了集成支持。

1.3 Spring的AOP理解

  Aop是面向切面编程,实现方式主要基于动态代理,可以是jdk的动态代理也可以是CGLIB动态代理

1.4 Spring的IoC理解

  IOC解释为依赖注入,最直观的表达就是依赖的对象不要去new了,而是交由spring自动完成,使用Java的反射机制,常用的注入方式有基于配置文件的构造器注入和setter方法注入还有就是使用注解的方式注入@Autowired,@resource

1.5 BeanFactory和ApplicationContext有什么区别

   BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

(1)BeanFactory是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:

①继承MessageSource,因此支持国际化。

②统一的资源文件访问方式。

③提供在监听器中注册bean的事件。

④同时加载多个配置文件。

⑤载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。

(2)①BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。

ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

③相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

(3)BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。

  1. BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

1.6 请解释Spring Bean的生命周期

首先说一下Servlet的生命周期:实例化,初始init,接收请求service,销毁destroy;

Spring上下文中的Bean生命周期也类似,如下:

(1)实例化Bean:

对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。

(2)设置对象属性(依赖注入):

实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。

(3)处理Aware接口:

接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:

①如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的就是Spring配置文件中Bean的id值;

②如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。

③如果这个Bean已经实现了ApplicationContextAware接口,

会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文;

(4)BeanPostProcessor:

如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization(Object obj, String s)方法。由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;

(5)InitializingBean 与 init-method:

如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。

  1. 如果这个Bean实现了BeanPostProcessor接口,
  2. 将会调用postProcessAfterInitialization(Object obj, String s)方法;

 

以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了。

 

(7)DisposableBean:

当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;

(8)destroy-method:

最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

1.7 Spring支持几种bean的作用域。

Spring容器中的bean可以分为5个范围:

(1)singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。

(2)prototype:为每一个bean请求提供一个实例。

(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。

(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。

(5)global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。

1.8 Spring框架中的单例Beans是线程安全的么

 Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Spring bean并没有可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多种状态的话(比如 View Model 对象),就需要自行保证线程安全。最浅显的解决办法就是将多态bean的作用域由“singleton”变更为“prototype”

1.9 Spring如何处理线程并发问题

在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。

ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

1.10 Spring 框架中都用到了哪些设计模式

(1)工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;

(2)单例模式:Bean默认为单例模式。

(3)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;

(4)模板方法:用来解决代码重复的问题。比如.RestTemplate,JmsTemplate,JpaTemplate。

(5)观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现--ApplicationListener。

java 设计模式实例分享全解https://blog.csdn.net/higherzjm/article/details/108952928

1.11 Spring事务的实现方式和实现原理(4种事务特性,7种传播行为,5种隔离级别

(1)spring事务的特性(ACID)

原子性:事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么完成要么都不完成

一致性:事务被提交后,数据和资源就处于一种满足业务规则的一致性状态中。

隔离性:可能有许多事务会同时处理相同的数据,因此要求每个事务都与其他事务隔离起来,防止数据损坏

持久性:事务一旦完成,无论发生系统错误,它的结果都不会受到影响。(事务结果被写道持久化存储器中)

(2)spring事务的传播行为

PROPAGATION_REQUIRED–支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择(大部分项目默认配置)。
PROPAGATION_SUPPORTS–支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY–支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW–新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED–以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER–以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED–如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

使用实例:

@Service
public class User1ServiceImpl implements User1Service {
    //省略其他...
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addRequired(User1 user){
        user1Mapper.insert(user);
    }
}

(3)Spring事务的隔离级别

default:使用底层数据库的默认隔离级别对于大多数的数据库来说,默认的隔离级别都是read_commted
read_commted:只允许事务读取已经被其他事务提交的变更,可以避免脏读,但不可以避免不可重复读和幻读
read_uncommted:允许事务读取未被其他事务提交的变更,脏读,不可重复读,幻读都会出现。
repeatable_read: 可避免脏读和不可重复读,但幻读问题仍然存在
serlalizable:所有问题都可以避免,但性能十分低下。

MYSQL: 默认为REPEATABLE_READ级别
SQLSERVER: 默认为READ_COMMITTED
Oracle 默认隔离级别 READ_COMMITTED

使用实例:

@Service
public class User1ServiceImpl implements User1Service {
    //省略其他...
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)://读取已提交数据(会出现不可重复读和幻读)
    public void addRequired(User1 user){
        user1Mapper.insert(user);
    }
}

1.12 Spring框架中有哪些不同类型的事件

Spring 提供了以下5种标准的事件:

(1)上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。

(2)上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。

(3)上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。

(4)上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。

(5)请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean会自动被通知。

1.13 解释一下Spring AOP里面的几个名词

(1)切面(Aspect):被抽取的公共模块,可能会横切多个对象。 在Spring AOP中,切面可以使用通用类(基于模式的风格) 或者在普通类中以 @AspectJ 注解来实现。

(2)连接点(Join point):指方法,在Spring AOP中,一个连接点 总是 代表一个方法的执行。 

(3)通知(Advice):在切面的某个特定的连接点(Join point)上执行的动作。通知有各种类型,其中包括“around”、“before”和“after”等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链。

(4)切入点(Pointcut):切入点是指 我们要对哪些Join point进行拦截的定义。通过切入点表达式,指定拦截的方法,比如指定拦截add*、search*。

(5)引入(Introduction):(也被称为内部类型声明(inter-type declaration))。声明额外的方法或者某个类型的字段。Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。

(6)目标对象(Target Object): 被一个或者多个切面(aspect)所通知(advise)的对象。也有人把它叫做 被通知(adviced) 对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个 被代理(proxied) 对象。

(7)织入(Weaving):指把增强应用到目标对象来创建新的代理对象的过程。Spring是在运行时完成织入。

切入点(pointcut)和连接点(join point)匹配的概念是AOP的关键,这使得AOP不同于其它仅仅提供拦截功能的旧技术。 切入点使得定位通知(advice)可独立于OO层次。 例如,一个提供声明式事务管理的around通知可以被应用到一组横跨多个对象中的方法上(例如服务层的所有业务操作)。

1.14 Spring通知有哪些类型

(1)前置通知(Before advice):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。

(2)返回后通知(After returning advice):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。 

(3)抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。 

(4)后通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 

(5)环绕通知(Around Advice):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。 环绕通知是最常用的一种通知类型。大部分基于拦截的AOP框架,例如Nanning和JBoss4,都只提供环绕通知。

同一个aspect,不同advice的执行顺序:

①没有异常情况下的执行顺序:

around before advice

before advice

target method 执行

around after advice

after advice

afterReturning

②有异常情况下的执行顺序:

around before advice

before advice

target method 执行

around after advice

after advice

afterThrowing:异常发生

java.lang.RuntimeException: 异常发生

1.15 spring怎么实现多态的

使用工厂模式实现多态

1.16 spring 集成 Redis使用实例

1 maven引入Redis依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>${version.clients.jedis}</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>${version.data.redis}</version>
</dependency>

properties配置

#最大连接数
redis.pool.maxTotal=30
#最大空闲时间
redis.pool.maxIdle=10
...
#JedisConnectionFactory的参数
#主机地址,默认:localhost
redis.hostName=127.0.0.1
#主机端口,默认:6379
redis.port=6379
#超时时间,默认:2000
redis.timeout=3000
#密码
redis.pass=
.....

3 spring配置bean.xml 

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <!-- 最大连接数 -->
    <property name="maxTotal" value="${redis.pool.maxTotal}"/>
    <!-- 最大空闲时间 -->
    <property name="maxIdle" value="${redis.pool.maxIdle}"/>
 ....
</bean>

<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
      p:host-name="${redis.hostName}" p:port="${redis.port}" p:password="${redis.pass}"  p:pool-config-ref="jedisPoolConfig"/>

<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory" />
 ........
    <!--开启事务  -->
    <property name="enableTransactionSupport" value="false"></property>
</bean>

4 缓存工具类

//Description:redis缓存工具类
@Service
public class RedisCacheUtil {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
   //普通缓存获取
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    //普通缓存放入
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    .......
}

5 spring 控制器类

@Controle
publice Class MyCongtrole{
   @Autowried
   private RedisCacheUtil redisCacheUtil; 
  .....
}

1.17  spring保证service关联调用事务的一致性 

springmvc如果一个SERVICE调用另一个SERVICE时如何保持事务一致?在事务传播为propagation=”REQUIRED”的时候,如果SERVICE抛出运行时异常,则所有的SERVICE共享同一事务。 如果想要SERVICE抛出所有异常都能回滚,那么就要propagation="REQUIRED"后面加上rollback-for="Exception"

2 SpringMVC

2.1 什么是Spring MVC

Spring MVC通常来讲是把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

2.2 SpringMVC的流程

(1)用户发送请求至前端控制器DispatcherServlet

(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;

(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet

(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;

(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);

(6)Handler执行完成返回ModelAndView

(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet

(8)DispatcherServletModelAndView传给ViewResolver视图解析器进行解析;

(9)ViewResolver解析后返回具体View;

(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)

(11)DispatcherServlet响应用户。

 

2.3 Springmvc的优点

 

(1)可以支持各种视图技术,而不仅仅局限于JSP;

(2)与Spring框架集成(如IoC容器、AOP等);

(3)清晰的角色分配:前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)。

(4)支持各种请求资源的映射策略。

2.4 Spring MVC的主要组件

(1)前端控制器 DispatcherServlet(不需要程序员开发)

作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。

(2)处理器映射器HandlerMapping(不需要程序员开发)

作用:根据请求的URL来查找Handler

(3)处理器适配器HandlerAdapter

注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。

(4)处理器Handler(需要程序员开发)

(5)视图解析器 ViewResolver(不需要程序员开发)

作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)

(6)视图View(需要程序员开发jsp)

View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)

2.5 springMVC和struts2的区别有哪些 

(1)springmvc的入口是一个servlet即前端控制器(DispatchServlet),而struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilter)。

(2)springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。

(3)Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。

2.6 SpringMVC怎么样设定重定向和转发的

(1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4"

(2)重定向:在返回值前面加"redirect:",譬如

2.7 SpringMvc的控制器是不是单例模式,如果是,有什么问题,怎么解决

是单例模式,默认的作用域是singleton,每个容器中只有一个bean实例,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段。@Controller之前增加@Scope("prototype"),就可以改变单例模式为多例模式(改为每接收到一次请求就创建一个bean)

2.8 SpringMVC常用的注解有哪些

@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。

@RequestBody:注解实现接收http请求的json数据,将json转换为java对象。

@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。

2.9 SpringMvc里面拦截器是怎么写的

  有两种写法,一种是实现HandlerInterceptor接口,另外一种是继承HandlerInterceptorAdapter适配器类,接着在接口或抽象方法当中实现处理逻辑,然后在SpringMvc的配置文件中配置拦截器即可:

2.10 SpringMVC异常处理的三种方式 

一、使用 @ExceptionHandler 注解

该方式进行异常处理的方法必须与出错的方法在同一个Controller里面。使用如下:

@ExceptionHandler(RuntimeException.class) // 这个异常处理只会在本类中起作用

public String catchException(RuntimeException e){ 

System.out.println(e.getMessage());

return "error"; }

这种异常处理可以根据不同的异常在同一个Controller中配置多个,但是它们只能在该Controller中起作用。

二、实现 HandlerExceptionResolver 接口

HandlerExceptionResolver是SpringMVC为我们提供的一个统一异常处理的接口,实现机制也十分简单。注意该类要注入到spring中。

@Component

public class GlobalException implements HandlerExceptionResolver {

@Override    // 自定义全局异常处理在mvc一直起作用

public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {

if (e instanceof MyException) {

return new ModelAndView("error1");

} else if (e instanceof RuntimeException){

return new ModelAndView("error2");

}

return new ModelAndView("error3");

}

这种方式也可以进行异常处理,而且是全局。但是这种方式也有一定的弊端,全部的处理都打在一个方法里面,没有解耦合,后期不利于我们维护。

三、使用 @ControllerAdvice+ @ ExceptionHandler 注解

为了结合上面俩种方式的优点,Spring3.2为我们提供了一个新的注解@ControllerAdvice。注意该类要注入到spring中。

@ControllerAdvice

@Component

public class HandlerAndAdvice {

@ExceptionHandler(RuntimeException.class)

@ResponseStatus(value = HttpStatus.BAD_REQUEST) //这里还可以配置响应的状态哦

@ResponseBody

public String catchRuntime() {

return "运行时发生了不可描述的错误偶偶偶偶局";

}

@ExceptionHandler(MyException.class)

public String catchMy(){

return "myError";

}

}

这种方式在本类使用@ControllerAdvice+ @ExceptionHandler的方式实现全局配置,代码解耦合,可以对不同的异常进行单独处理,配置更加灵活,后期的维护和添加异常处理也更加方便。

3 SpringBoot

3.1 springBoot的优点和缺点

优点

1 快速构建项目,通过了自动配置功能;2 springboot内嵌了servlet容器,降低了对环境的要求;3 提供运行时的应用监控;

4 快速整合第三方框架(如Spring JDBC,Spring ORM,Spring Data,Spring Security等,无需配置文件;

5 极大地提高了开发、部署效率,可以打包成jar文件直接main函数运行;6代码少了、配置文件少了、减少来开发时间和提高了工作效率

缺点

1版本迭代速度很快,一些模块改动很大;2由于不用自己做配置,报错时很难定位

3.2 springboot中常用的starter的组件有哪些.

spring-boot-starter-parent //boot项目继承的父项目模块.

spring-boot-starter-web //boot项目集成web开发模块.

spring-boot-starter-tomcat //boot项目集成tomcat内嵌服务器.

spring-boot-starter-test //boot项目集成测试模块.

mybatis-spring-boot-starter //boot项目集成mybatis框架.

spring-boot-starter-jdbc //boot项目底层集成jdbc实现数据库操作支持.

spring-boot-starter-security:使用 Spring Security 的 starter

3.3 SpringBoot DevTools 的用途是什么

SpringBoot 开发者工具,或者说 DevTools,是一系列可以让开发过程变得简便的工具。为了引入这些工具,我们只需要在 POM.xml 中添加如下依赖:

 <dependency>

     <groupId>org.springframework.boot</groupId>

     <artifactId>spring-boot-devtools</artifactId>

     <version>1.5.4.RELEASE</version>

 </dependency>

spring-boot-devtools 模块在生产环境中是默认禁用的,archives 的 repackage 在这个模块中默认也被排除。因此,它不会给我们的生产环境带来任何开销。

通常来说,DevTools 应用属性适合于开发环境。这些属性禁用模板缓存,启用 web 组的调试日志记录等等。最后,我们可以在不设置任何属性的情况下进行合理的开发环境配置。

每当 classpath 上的文件发生更改时,使用 DevTools 的应用程序都会重新启动。这在开发中非常有用,因为它可以为修改提供快速的反馈。

默认情况下,像视图模板这样的静态资源修改后是不会被重启的。相反,资源的更改会触发浏览器刷新。注意,只有在浏览器中安装了 LiveReload 扩展并以与 DevTools 所包含的嵌入式 LiveReload 服务器交互时,才会发生。

3.4 怎么禁用某些自动配置特性

如果我们想禁用某些自动配置特性,可以使用 @EnableAutoConfiguration 注解的 exclude 属性来指明。例如,下面的代码段是使 DataSourceAutoConfiguration 无效:

@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)

public class MyConfiguration { }

3.5 SpringBoot的 Actuator 是做什么的

  是对服务进行监视和管理的集成工具,也形容为端点,集成SpringBoot Actuator 到项目中非常简单。我们需要做的只是将 spring-boot-starter-actuator starter 引入到 POM.xml 文件当中(版本号记得添加上去,不然有时候会无效)

 <dependency>

     <groupId>org.springframework.boot</groupId>

     <artifactId>spring-boot-starter-actuator</artifactId>

     <version>1.5.4.RELEASE</version>

 </dependency>

一些常用的内置 endpoints Actuator:

auditevents:查看 audit 事件信息;env:查看 环境变量;health:查看应用程序健康信息;httptrace:展示 HTTP 路径信息info展示 arbitrary 应用信息;metrics:展示 metrics 信息;loggers:显示并修改应用程序中日志器的配置;mappings:展示所有 @RequestMapping 路径信息;scheduledtasks:展示应用程序中的定时任务信息;threaddump:执行 Thread Dump;beans:描述上下文所有bean,以及它们之间的关系;refresh:刷新操作,比如刷新修改的配置文件,不要重启服务;Routes:  路由刷新,就是查询zuul网关转发路径映射列表

Actuator 端点扫描springBoot默认是不支持的,如果出现了扫描不到情况,需要在配置文件添加不需要安全管理的配置management.security.enabled=false,如下:

4 SpringCloud

4.1 springCloud中用到的一些技术点

1 Eureka 服务管理,相互注册;2 Ribbon 负载均衡框架;3 Feign 服务调用接口;4 Hystrix 容错框架;5 Zuul 网关,消息转发的设置;6消息驱动,与rabbit或kafka消息中间件的整合;7 配置中心,从SVN或Git上读取配置文件;8 微服务与数据库的整合

4.2 SpringCloud和Dubbo

SpringCloud和Dubbo都是现在主流的微服务架构

SpringCloud是Apache旗下的Spring体系下的微服务解决方案

Dubbo是阿里系的分布式服务治理框架

从技术维度上,其实SpringCloud远远的超过Dubbo,Dubbo本身只是实现了服务治理,而SpringCloud现在以及有21个子项目以后还会更多

所以其实很多人都会说Dubbo和SpringCloud是不公平的

但是由于RPC以及注册中心元数据等原因,在技术选型的时候我们只能二者选其一,所以我们常常为用他俩来对比

服务的调用方式Dubbo使用的是RPC远程调用,而SpringCloud使用的是 Rest API,其实更符合微服务官方的定义

服务的注册中心来看,Dubbo使用了第三方的ZooKeeper作为其底层的注册中心,实现服务的注册和发现,SpringCloud使用Spring Cloud Netflix Eureka实现注册中心,当然SpringCloud也可以使用ZooKeeper实现,但一般我们不会这样做

服务网关,Dubbo并没有本身的实现,只能通过其他第三方技术的整合,而SpringCloud有Zuul路由网关,作为路由服务器,进行消费者的请求分发,SpringCloud还支持断路器,与git完美集成分布式配置文件支持版本控制,事务总线实现配置文件的更新与服务自动装配等等一系列的微服务架构要素。

目前国内的分布式系统选型主要还是Dubbo毕竟国产,而且国内工程师的技术熟练程度高,并且Dubbo在其他维度上的缺陷可以由其他第三方框架进行集成进行弥补

而SpringCloud目前是国外比较流行,当然我觉得国内的市场也会慢慢的偏向SpringCloud,就连刘军作为Dubbo重启的负责人也发表过观点,Dubbo的发展方向是积极适应SpringCloud生态,并不是起冲突。

 SpringCloud社区活跃度远高于Dubbo

4.3 Rest和RPC对比

RPC最主要的缺陷就是服务提供方和调用方式之间依赖太强,我们需要为每一个微服务进行接口的定义,并通过持续继承发布,需要严格的版本控制才不会出现服务提供和调用之间因为版本不同而产生的冲突

而REST是轻量级的接口,服务的提供和调用不存在代码之间的耦合,只是通过一个约定进行规范,但也有可能出现文档和接口不一致而导致的服务集成问题,但可以通过swagger工具整合,是代码和文档一体化解决,所以REST在分布式环境下比RPC更加灵活

这也是为什么当当网的DubboX在对Dubbo的增强中增加了对REST的支持的原因

4.4 SpringBoot和SpringCloud

SpringBoot专注于快速方便的开发单个个体的微服务

SpringCloud是关注全局的微服务协调整理治理框架,整合并管理各个微服务,为各个微服务之间提供,配置管理,服务发现,断路器,路由,事件总线等集成服务

SpringBoot不依赖于SpringCloud,SpringCloud依赖于SpringBoot,属于依赖关系

SpringBoot专注于快速,方便的开发单个的微服务个体,SpringCloud关注全局的服务治理框架

4.5 Eureka和ZooKeeper都可以提供服务注册与发现的功能,请说说两个的区别

1 ZooKeeper是Dubbo使用的注册中心,Eureka主要是springCLoud使用的注册中心

2 ZooKeeper有Leader和Follower角色,Eureka各个节点平等

3 ZooKeeper采用过半数存活原则,Eureka采用自我保护机制解决分区问题

4 Eureka本质上是一个工程,而ZooKeeper只是一个进程

4.6 什么是服务熔断?什么是服务降级

在固定时间窗口内,接口调用超时比率达到一个阈值,会开启熔断。进入熔断状态后,后续对该服务接口的调用不再经过网络,直接执行本地的默认方法fallback,达到服务降级的效果。熔断不可能是永久的。当经过了规定时间之后,服务将从熔断状态回复过来,再次接受调用方的远程调用

4.7 微服务的优缺点分别是什么

优点

1每一个服务足够内聚,代码容易理解;2开发效率提高,一个服务只做一件事;3微服务能够被小团队单独开发;4微服务是松耦合的,是有功能意义的服务;5可以用不同的语言开发,面向接口编程;6易于与第三方集成;7微服务只是业务逻辑的代码,不会和HTML,CSS或者其他界面组合开发中,两种开发模式:前后端分离、全栈工程师;8可以灵活搭配,连接公共库/连接独立库

缺点:

1分布式系统的负责性;2多服务运维难度,随着服务的增加,运维的压力也在增大;3系统部署依赖;4服务间通信成本;5数据一致性;6系统集成测试;7性能监控

4.8 微服务技术栈有哪些

服务开发:SpringBoot,Spring,SpringMVC; 服务配置与管理:Netfilx公司的Archaiusm,阿里的Diamond;  服务注册与发现:Eureka,ZooKeeper; 服务调用:Rest,RPC,gRPC; 服务熔断器:Hystrix; 服务负载均衡:Ribbon,Nginx; 服务接口调用:Feign; 消息队列:Kafka,RabbitMq,ActiveMq; 服务配置中心管理:SpringCloudConfing; 服务路由(API网关):Zuul; 事件消息总线:SpringCloud Bus

4.9 springcloud分布式事务一致性解决方案

背景:对于cloud分布式架构,最难避免的就是多服务调用问题,然而在某些难以避免的情况下会发生一次请求会协调多个服务调用去完成这一个事件的任务,正式这种情况的存在,才会造成先调用的服务已经对数据库操作完成了,后面的对于数据库操作却失败了,在这种情况下就会存在数据库的一次操作数据处理残缺,所以才引入了今天我们要说的分布式事务。事务是由一组操作构成的可靠的独立的工作单元,事务具备ACID的特性,即原子性、一致性、隔离性和持久性。但是lcntx不生产事务,只是事务的协调者!在一个分布式系统下存在多个模块协调来完成一次业务。那么就存在一次业务事务下可能横跨多种数据源节点的可能。TX-LCN将可以解决这样的问题。例如存在服务模块A 、B、 C。A模块是mysql作为数据源的服务,B模块是基于redis作为数据源的服务,C模块是基于mongo作为数据源的服务。若需要解决他们的事务一致性就需要针对不同的节点采用不同的方案,并且统一协调完成分布式事务的处理

解决方案:1 seata: UNDO LOG 记录,把提交事务前的记录放这边,以便回滚用 ;2 tx-lcn: 事务补偿机制,重试方案

4.10 实例分享

1 服务管理者配置和启动函数

application.yml:
server:
  port: 8761
eureka:
  client: 
    register-with-eureka: false
    fetch-registry: false


启动main函数:

@SpringBootApplication
@EnableEurekaServer
public class ServerApp {

	public static void main(String[] args) {
		new SpringApplicationBuilder(ServerApp.class).web(true).run(args);
	}

}

2  服务注册者配置与实例

application.yml:

server:
  port: 8080
spring:
  application:
    name: springboot-serviceprovider
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

启动函数:

@SpringBootApplication
@EnableEurekaClient
public class ProviderApp1 {

	public static void main(String[] args) {
		new SpringApplicationBuilder(ProviderApp1.class).web(true).run(args);
	}

}

测试control:

@RestController
public class PoliceController {

	//http://localhost:8080/restTemplateTestServer1
	@RequestMapping("/restTemplateTestServer1")
	public String restTemplateTestServer1(HttpServletRequest request){
		String name=request.getParameter("name");
		return "restTemplate测试_服务提供者1:用服务提供方的服务id访问的;name:"+name;
	}

	/**
	 * 简单负载均衡服务调用者1
	 * @param request
	 * @return
	 */
	@RequestMapping("/baseRibbonServer")
	public String baseRibbonServer(HttpServletRequest request){

		return "简单负载均衡服务提供者1:"+request.getRequestURL().toString();
	}
}

3 主服务注册者的配置(包括了feign,ribbon,zuul,rest,hystrix,jpa)

源码参考博客地址:https://blog.csdn.net/higherzjm/article/details/95475901

application.yml:

server:
  port: 9000
spring:
  application:
    name: springboot-main
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/SPRING_DATA
    username: root
    password: zjm@cat


management:
  security:
    enabled: false   #为了端点的测试需要关闭安全认证

#hystrix的全套配置begin-----------------------
feign:
  hystrix:
    enabled: true   #打开hystrix开关
hystrix:
  command:
      #HytrixHelloClient#baseHytrixServer_test1(): #单个接口中的方法的配置
    default: #全局的配置
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1500 #设置超时时间1500毫秒
      circuitBreaker:
        requestVolumeThreshold: 3 #设置10秒内3次请求

#hystrix的全套配置end-------------------------------------


#zuul的全套配置begin-----------------------
zuul:
  routes:
    sourcezjm:   #  sourcezjm(可修改)的url请求都会转发至http://localhost:8082
      url: http://localhost:8082  #简单路由,可以省略path配置,没有path的话sourcezjm当后缀直接访问
    zuultest:
      path: /zuultest/**     # 所有zuultest开头的请求路径都会转发至:springboot-serviceprovider3的服务id
      serviceId: springboot-serviceprovider3   #服务提供者,ribbon路由,面向服务的路由
    forwardZuul:
          path: /forwardZuul/**
          url: forward:/forwardZuul_test1 #跳转路由 URL参数需要由forward:...构成 访问方式->http://localhost:9000/forwardZuul/**

# 路由的端点访问路径 http://localhost:9000/routes

#zuul的全套配置end-----------------------

#jpa 数据库的配置begin------------------------



#jpa 数据库的配置end--------------------------

#default:
  #ribbon:
    #NFLoadBalancerRuleClassName: org.crazyit.ribbon.RibbonDiyRuleDiyRule  #调用自定义负载均衡器

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/



5 分布式CAP原则

CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值