Spring、SpringMVC、SpringBoot

23 篇文章 0 订阅
1 篇文章 0 订阅

1. Spring 框架、Spring模块

Spring 是⼀种轻量级开发框架,旨在提⾼开发⼈员的开发效率以及系统的可维护性,它是很多模块的集合,使⽤这些模块可以很⽅便地协助我们进⾏开发。

这些模块是:核⼼容器、数据访问/集成,、Web、AOP(⾯向切⾯编程)、⼯具、消息和测试模块。

列举⼀些重要的Spring模块
Spring Core: 基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 反转控制(IOC) 和依赖注⼊(DI)功能。
Spring Aspects : 该模块为与AspectJ的集成提供⽀持。
Spring AOP :提供了⾯向切⾯的编程实现。
Spring JDBC : Java数据库连接。
Spring JMS :Java消息服务。
Spring ORM : ⽤于⽀持Hibernate等ORM⼯具。
Spring Web : 为创建Web应⽤程序提供⽀持。
Spring Test : 提供了对 JUnit 和 TestNG 测试的⽀持。

2. @RestController vs @Controller

Controller 返回⼀个⻚⾯
单独使⽤ @Controller 不加 @ResponseBody 的话⼀般使⽤在要返回⼀个视图的情况,这种情况属于⽐较传统的Spring MVC 的应⽤,对应于前后端不分离的情况。

@RestController 返回JSON形式数据
@RestController 只返回对象,对象数据直接以 JSON 形式写⼊ HTTP 响应(Response)中,这种情况属于 RESTful Web服务,这也是⽬前⽇常开发所接触的最常⽤的情况(前后端分离)。

@Controller +@ResponseBody 返回JSON 数据
如果你需要在Spring4之前开发 RESTful Web服务的话,你需要使⽤ @Controller 并结合 @ResponseBody 注解,也就是说 @Controller+@ResponseBody =@RestController (Spring 4 之后新加的注解)。
@ResponseBody 注解的作⽤是将 Controller 的⽅法返回的对象通过适当的转换器转换为指定的格式之后,写⼊到HTTP 响应(Response)对象的 body 中,通常⽤来返回 JSON 或者 XML 数据,返回 JSON 数据的情况⽐较多。

3. 什么是前后端分离?

要搞清楚前后端分离概念,必须先搞清楚什么是非前后端分离。
在传统的做法里,比如servlet, springmvc,struts, tomcat 都会在后台运行 Java 代码,然后在后台生成全部的html 代码,接着通过 http 协议把 html 代码传输到浏览器。
这样做的问题是:

  1. 在后台运行的时候,如果要连接很多数据库才能把需要的数据查出来,那么这个准备 html 的过程就会比较缓慢,同时生成的 html 也相对较大, 用户就有可能感受比较慢。
  2. 前后端开发的联调耦合度也很高,有时候必须互相等待,这样双方的开发效率都降低了。

那么前后端分离什么概念呢?
html 页面的内容可以简单看成 包含数据部分和不包含数据部分。 所以先准备一个不包含数据的html, 把它传给浏览器,这个速度本身会非常快,因为没有最占时间的数据库操作部分。 然后再通过 Ajax 技术,仅仅从服务器获取“纯数据”,然后把纯数据显示在html上。

这样做的好处:

  1. 即便是后台数据库比较花时间,但是用户体验也比前面的方式好,因为用户会先看到部分页面,过一小会儿再看到数据,比在空白页面打圈圈等待体验好。
  2. 后端只提供数据,所以前后端开发耦合度降低了很多,整体开发效率可以得到较大提高。

4. Spring IOC & AOP(考察3次)

IoC(Inverse of Control:控制反转) 是⼀种设计思想,将原本在程序中⼿动创建对象的控制权,交由Spring框架来管理。Spring 将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。这样可以很⼤程度上简化应⽤的开发。

IoC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如何被创建出来的。 IOC 容器负责创建对象,将对象连接在一起,配置这些对象,并从创建中处理这些对象的整个生命周期,直到它们被完全销毁。也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

DI(依赖注入)
IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。

IOC实现原理: 使用反射机制+XML技术。

DI是如何实现的?
Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
在这里插入图片描述
Spring 时代我们⼀般通过 XML ⽂件来配置 Bean,后来开发⼈员觉得 XML ⽂件来配置不太好,于是SpringBoot 注解配置就慢慢开始流⾏起来。

AOP
AOP 即 Aspect Oriented Program 面向切面编程。首先,在面向切面编程的思想里面,把功能分为核心业务功能和辅助功能。所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务,所谓的辅助功能,比如性能统计,日志,事务管理等等。其中,辅助功能被定义为切面,在AOP思想里,核心业务功能和切面功能分别独立进行开发,然后,选择性的,低耦合的把切面和核心业务功能编织在一起。
举个例子:登陆功能,即便是没有性能统计和日志输出,也可以正常运行。但是如果有需要,就把"日志输出" 功能和 “登陆” 功能 编织在一起,这样登陆的时候,就可以看到日志输出了。

Spring AOP基于动态代理,如果要代理的对象,实现了某个接⼝,那么Spring AOP会使⽤JDKProxy,去创建代理对象,⽽对于没有实现接⼝的对象,就⽆法使⽤ JDK Proxy 去进⾏代理了,这时候Spring AOP会使⽤Cglib ⽣成⼀个被代理对象的⼦类来作为代理。

当然你也可以使⽤ AspectJ ,Spring AOP 已经集成了AspectJ ,AspectJ 应该算的上是 Java ⽣态系统中最完整的 AOP 框架了。

使⽤ AOP 之后我们可以把⼀些通⽤功能抽象出来,在需要⽤到的地⽅直接使⽤即可,这样⼤⼤简化了代码量。我们需要增加新功能时也⽅便,这样也提⾼了系统扩展性。⽇志功能、事务管理等等场景都⽤到了 AOP 。

动态代理的概念:
一般接口功能的实现,需要依赖于其对应的实现类。而Java标准库提供了一种动态代理(Dynamic Proxy)的机制:可以在运行期直接动态创建某个interface的实例。

Spring AOP 和 AspectJ AOP 有什么区别?
Spring AOP 基于代理(Proxying),⽽AspectJ 基于字节码操作(Bytecode Manipulation)。Spring AOP 已经集成了 AspectJ 。AspectJ 相⽐于 Spring AOP 功能更加强⼤,但是 Spring AOP 相对来说更简单.
如果我们的切⾯⽐较少,那么两者性能差异不⼤。但是,当切⾯太多的话,最好选择 AspectJ ,它⽐Spring AOP 快很多。

5. bean 的作⽤域和线程安全问题(考察一次)

bean 的作⽤域

  1. singleton:默认的,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
  2. prototype : 每次请求都会创建⼀个新的 bean 实例。
  3. request : 每⼀次HTTP请求都会产⽣⼀个新的bean,该bean仅在当前HTTP request内有效,在请求完成以后,bean会失效并被垃圾回收器回收。
  4. session : 与request范围类似,每⼀次HTTP请求都会产⽣⼀个新的 bean,该bean仅在当前 HTTP session 内有效,在session过期后,bean会随之失效。
  5. global-session:全局作用域,global-session和Portlet应用相关。当应用部署在Portlet容器中工作时,它包含很多portlet。如果想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。

Spring 中的单例 bean 的线程安全问题了解吗?
Spring框架并没有对单例bean进行任何多线程的封装处理。 关于单例bean的线程安全和并发问题需要开发者自行去搞定。单例 bean 存在线程问题,主要是因为当多个线程操作同⼀个对象的时候,对这个对象的⾮静态成员变量的写操作会存在线程安全问题。

解决方案: 可以考虑在类中定义⼀个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中。

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

5. 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)方法。

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

(6)如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法;由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;

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

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

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

6. 声明为bean 的注解

我们⼀般使⽤ @Autowired 注解⾃动装配 bean,要想把类标识成可⽤于 @Autowired 注解⾃动装配的 bean 的类,采⽤以下注解可实现:

  1. @Component
    用于自动检测和使用类路径扫描自动配置bean。使得注释类和bean之间存在隐式的一对一映射(即每个类对应一个bean)。它是一个通用注解,其他三个注解是这个注解的拓展,并且具有了特定的功能;可标注任意类为Spring 组件。如果⼀个Bean不知道属于哪个层,可以使⽤ @Component 注解标注。
  2. @Repository
    持久层即 Dao 层注解,主要⽤于数据库相关操作,具有将数据库操作抛出的原生异常翻译转化为spring的持久层异常的功能。
  3. @Service
    服务层注解,主要涉及⼀些复杂的业务逻辑,需要⽤到 Dao层。
  4. @Controller
    Spring MVC 控制层注解,主要用于接受⽤户请求并调⽤ Service 层返回数据给前端⻚⾯,具有将请求进行转发,重定向的功能。

用这些注解对应用进行分层之后,就能将请求处理,义务逻辑处理,数据库操作处理分离出来,为代码解耦,也方便了以后项目的维护和开发。

使用上述注解的类可以被spring框架所扫描并注入到spring容器来进行管理,⼀般使⽤@Autowired 注解完成⾃动装配。

7. @Component 和 @Bean 的区别是什么?

@Component 和 @Bean 是两种使用注解来定义bean的方式。都可以使用@Autowired或者@Resource注解注入。
它们的区别在于:

  1. 作⽤对象不同: @Component 注解作⽤于类,⽽ @Bean 注解作⽤于⽅法。
  2. @Component 通常是通过类路径扫描来⾃动侦测以及⾃动装配到Spring容器中。注释类和bean之间存在隐式的一对一映射(即每个类对应一个bean)。@Bean用于显式声明单个bean。
  3. @Bean 注解⽐ @Component 注解的⾃定义性更强,⽽且有些时候我们只能通过 @Bean 注解来定义bean。如果想将第三⽅库中的类装配到 Spring 容器时,没办法使用@Component进行自动配置,这种时候使用@Bean就比较合适了。不过同样的也可以通过xml方式来定义。

8. Spring MVC

MVC是什么?
MVC 是⼀种设计模式,即 Model-View-Controller(模型-视图-控制器) 模式,这种模式用于应用程序的分层开发。

Model(模型)用于处理数据逻辑。通常模型对象负责在数据库中存取数据。
View(视图)数据可视化。通常视图是依据模型数据创建的。
Controller(控制器)处理用户交互。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

MVC 分层简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。

SpringMVC是什么?
Spring MVC 是⼀款很优秀的 MVC 框架,可以帮助我们进⾏更简洁的Web层的开发,并且它天⽣与 Spring 框架集成。在Spring MVC 下,⼀般把后端项⽬分为 Entity层(实体类)、Dao层(数据库操作)、Service层(处理业务)、Controller层(控制层,返回数据给前台⻚⾯)。

Spring MVC 的简单原理图如下:
在这里插入图片描述

9. SpringMVC ⼯作原理了解吗?

  1. 客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
  2. DispatcherServlet 根据请求信息调⽤ HandlerMapping ,解析请求对应的 Handler 。
  3. 解析到对应的 Handler (也就是我们平常说的 Controller 控制器)后,开始由HandlerAdapter 适配器处理。
  4. HandlerAdapter 会根据 Handler 来调⽤真正的处理器处理请求,并处理相应的业务逻辑。
  5. 处理器处理完业务后,会返回⼀个 ModelAndView 对象, Model 是返回的数据对象, View是个逻辑上的 View 。
  6. ViewResolver 会根据逻辑 View 查找实际的 View 。
  7. DispatcherServlet 把返回的 Model 传给 View (视图渲染)。
  8. 把 View 返回给请求者(浏览器)

10. Spring 框架中⽤到了哪些设计模式?(考察3次)

(这里总结了我项目中用到的,其他的就不进行记忆了)
1. 工厂设计模式:
用工厂方法代替new操作的一种模式,将创建对象的责任转移到工厂类;Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。

两者对比:
BeanFactory :延迟注入(使用到某个 bean 的时候才会注入),会占用更少的内存,程序启动速度更快。
ApplicationContext :容器启动的时候,不管用没用到,一次性创建所有 bean 。BeanFactory 仅提供了最基本的依赖注入支持,ApplicationContext 扩展了 BeanFactory ,除了有BeanFactory的功能还有额外更多功能,所以使用ApplicationContext会更多。

2. 单例设计模式
在我们的系统中,有一些对象其实我们只需要一个,如果制造出多个实例就可能会导致一些问题的产生,比如:程序的行为异常、资源使用过量、或者不一致性的结果。

使用单例模式的好处:
对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销;
由于 new 操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻 GC 压力,缩短 GC 停顿时间。

Spring 中 bean 的默认作用域就是 singleton(单例)的。Spring 实现单例的方式:
xml:
注解:@Scope(value = “singleton”)
Spring 通过 ConcurrentHashMap 实现单例注册表的特殊方式实现单例模式。

3. 代理设计模式

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能被直接引用,而代理对象可以起到中介的作用。
代理模式在 AOP 中进行了应用,AOP 即 Aspect Oriented Program 面向切面编程。首先,在面向切面编程的思想里面,把功能分为核心业务功能和辅助功能。所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务,所谓的辅助功能,比如性能统计,日志,事务管理等等。其中,辅助功能被定义为切面,在AOP思想里,核心业务功能和切面功能分别独立进行开发,然后,选择性的,低耦合的把切面和核心业务功能编织在一起。
Spring AOP基于动态代理,如果要代理的对象,实现了某个接⼝,那么Spring AOP会使⽤JDK Proxy,去创建代理对象,⽽对于没有实现接⼝的对象,就⽆法使⽤ JDK Proxy 去进⾏代理了,这时候Spring AOP会使⽤Cglib ⽣成⼀个被代理对象的⼦类来作为代理。

4. 装饰者模式(spring中没用到,JDK中有)
装饰者模式可以动态地给对象添加一些额外的属性或行为。相比于使用继承,装饰者模式更加灵活。其实在 JDK 中就有很多地方用到了装饰者模式,比如 InputStream家族,InputStream 类下有 FileInputStream (读取文件)在不修改InputStream 代码的情况下扩展了它的功能。

11. Spring 事务

事务可以保证逻辑处理的原子性,通过使用事务控制,可以极大的避免出现逻辑处理失败导致的脏数据等问题。但事务不可滥用,事务的过多引入会影响项目的性能。

事务最重要的两个特性,传播行为和隔离级别。传播行为定义的是事务的控制范围,隔离级别定义的是事务在数据库读写方面的控制范围。

Spring 管理事务的⽅式有⼏种?

  1. 编程式事务,在代码中硬编码。(不推荐使⽤)
  2. 声明式事务,在配置⽂件中配置(推荐使⽤)
    声明式事务⼜分为两种:
    基于XML的声明式事务; 基于注解的声明式事务。

SpringBoot设置事务隔离等级
SpringBoot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可。

一、配置步骤:
1、在启动主类添加注解:@EnableTransactionManagement 来启用注解式事务管理,相当于之前在xml中配置的<tx:annotation-driven />注解驱动。

package com.lgy.controller; 
   
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 

@SpringBootApplication  @EnableTransactionManagement
public class AppMain { 
    public static void main(String[] args) { 
        SpringApplication.run(AppMain.class, args); 
    } 
} 

2、在需要事务的类或者方法(service)上面添加@Transactional注解,里面可以配置需要的粒度,如果没有设置默认的事务等级,需要在此添加isolation和propagation属性。如果类和方法上均有@Transactional注解,则类内的方法上注解属性会覆盖类注解上的相同属性

@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED)
public class DefaultFooService implements FooService {
  public void getFoo(Foo foo) {
     // do something
  }
  //方法上注解属性会覆盖类注解上的相同属性
  @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  public void updateFoo(Foo foo) {
     // do something
  }
}

二、属性配置:
1、Isolation :隔离级别
隔离级别是指若干个并发的事务之间的隔离程度,与我们开发时候主要相关的场景包括:脏读、重复读、幻读。
org.springframework.transaction.annotation.Isolation 枚举类中定义了五个表示隔离级别的值:
public enum Isolation {
DEFAULT(-1),
READ_UNCOMMITTED(1),
READ_COMMITTED(2),
REPEATABLE_READ(4),
SERIALIZABLE(8);
}
DEFAULT :这是默认值,表示使用底层数据库的默认隔离级别。大多数的数据库系统的默认事务隔离级别都是:Read committed,而MySQL的默认事务隔离级别是:Repeatable Read;
READ_UNCOMMITTED :最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
READ_COMMITTED :允许读取并发事务已经提交的数据,可以阻⽌脏读,但是幻读或不可重复读仍有可能发⽣
REPEATABLE_READ :对同⼀字段的多次读取结果都是⼀致
的,除⾮数据是被事务本身⾃⼰所修改,可以阻⽌脏读和不可重复读,但幻读仍有可能发⽣。
SERIALIZABLE :最⾼的隔离级别,完全服从ACID的隔离级
别。所有的事务依次逐个执⾏,这样事务之间就完全不可能产⽣⼲扰,也就是说,该级别可以防⽌脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会⽤到该级别。
指定方法:通过使用 isolation 属性设置,例如:@Transactional(isolation = Isolation.DEFAULT)

2、Propagation:传播行为
事务往往在service层进⾏控制,如果出现service层⽅法A调⽤了另外⼀个service层⽅法B, A和B⽅法本身都已经被添加了事务控制,那么A调⽤B的时候,就需要进⾏事务的⼀些协商,这就叫做事务的传播⾏为。
org.springframework.transaction.annotation.Propagation 枚举类中定义了6个表示传播行为的枚举值:
public enum Propagation {
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
}

⽀持当前事务的情况:
REQUIRED :如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
SUPPORTS :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
MANDATORY :如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。 (mandatory:强制性)

不⽀持当前事务的情况:
REQUIRES_NEW :创建一个新的事务,如果当前存在事务,则把当前事务挂起。
NOT_SUPPORTED :以非事务方式运行,如果当前存在事务,则把当前事务挂起。
NEVER :以非事务方式运行,如果当前存在事务,则抛出异常。

其他情况:
NESTED :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED 。

指定方法:通过使用 propagation 属性设置,例如:@Transactional(propagation = Propagation.REQUIRED)

@Transactional(rollbackFor = Exception.class)注解了解吗?
Exception分为运行时异常RuntimeException和非运行时异常。
在@Transactional注解中如果不配置rollbackFor属性,那么事务只会在遇到运行时异常RuntimeException的时候才会回滚,反之加上rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚,即如果类或者方法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。

当@Transactional注解作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。

此外,如果异常被try{}catch{}了,事务就不回滚了,因为一旦你try{}catch{}了。系统会认为你已经手动处理了异常,就不会进行回滚操作。因此,如果我们在使用事务 @Transactional 的时候,想自己对异常进行处理的话,那么我们可以进行手动回滚事物。在catch中加上 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 方法进行手动回滚。

 1  //假设这是一个service类的片段
 2   
 3  try{ 
 4      //出现异常
 5   } catch (Exception e) {
 6               e.printStackTrace();
 7             //设置手动回滚
 8               TransactionAspectSupport.currentTransactionStatus()
 9                      .setRollbackOnly();
10          }
11  //此时return语句能够执行
12  return  xxx;

注意:方法上要加上@Transactional(rollbackFor = Exception.class) 再配合TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 才可以,否则会报错;

12. JPA

JPA(Java Persistence API)是Sun官方提出的Java持久化规范,用来方便操作数据库。真正进行SQL操作的是Hibernate。
在数据库持久层dao层,创建相应dao接口,继承JpaRepository,并且提供对应泛型<实体类,主键类型> 。
通过继承了JpaRepository 这个父接口,就提供了CRUD, 分页等等一系列的查询,可以直接使用,不需要二次开发,也不需要像Mybatis一样进行SQL语句的编写。

JPA的条件查询,也是不需要写 SQL 语句的,只需要在 dao 接口里按照规范的命名定义对应的方法名、参数和返回值,即可达到查询相应字段的效果了。

JPA 不需要用户手动写sql 语句,而是通过反射获取自定义的接口方法里提供的信息,就知道用户希望根据什么条件来查询了。 然后 JPA 底层再通过Hibernate得到对应的 sql 语句操作数据库,就达到了条件查询的效果啦。

如何使用JPA在数据库中非持久化一个字段,也就是不被数据库存储怎么办?使用注解@Transient

13. Restful标准

url中资源名称用复数,而非单数。
即:使用 /categories 而不是用 /category

CRUD的URL就都使用一样的 “/categories”,区别只是在于method不同,服务器根据method的不同来判断浏览器期望做的业务行为
增加: post; 删除: delete;
修改: put; 查询: get;

id 参数的传递都用 /id方式。
如编辑和修改:/categories/123

其他参数采用?name=value的形式:如分页参数 /categories?start=5

14. @Autowired与@Resource

@Autowired可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作,通过 @Autowired的使用来消除 set ,get方法。@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName注入。

原理:
对于@Autowired:在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。

而对于@Resource:原理和上面的相同,只是使用的后置处理器为CommonAnnotationBeanPostProcessor。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值