- spring
- 请谈一谈Spring中自动装配的方式有哪些
- 请问Spring中Bean的作用域有哪些?
- 请问什么是IoC和DI?并且简要说明一下DI是如何实现的?
- 请说明一下Spring中BeanFactory和ApplicationContext的区别是什么?
- 请说明一下springIOC原理是什么?如果你要实现IOC需要怎么做?请简单描述一下实现步骤?
- 请简单说明一下依赖注入的方式有哪几种?以及这些方法如何使用?
- 请问在以前的学习中有使用过Spring里面的注解吗?如果有请谈一下autowired 和resource区别是什么?
- 请问Spring支持的事务管理类型有哪些?以及你在项目中会使用哪种方式?
- 聊一下什么是Spring,以及核心思想?
- Spring中有哪些容器
- Spring的工作机制?
- BeanFactory和FactoryBean的区别?
- AOP的底层实现是怎样的?
- 说一下bean的生命周期
- 为什么要使用 spring?
- Spring框架主要有哪些模块?
- spring 常用的注入方式有哪些?
- spring 中的 bean 是线程安全的吗?
- spring 自动装配 bean 有哪些方式?
- spring 事务实现方式有哪些
- Spring框架中有哪些不同类型的事件?
- SpringMVC篇
- Mybatis篇
- mybatis 中 #{}和 ${} 无法防止 sql 注入
- mybatis 有几种分页方式?
- Mybatis是如何进行分页的?分页插件的原理是什么?
- 简述Mybatis的插件运行原理,以及如何编写一个插件
- Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
- 如何获取自动生成的(主)键值?
- 物理分页与逻辑分页的区别?
- 说一下Mybatis的一级缓存和二级缓存?
- mybatis 有哪些执行器(Executor)?
- Mybatis有哪些常用标签?
- 如何配置将mapper映射文件与Spring关联上?
- MyBatis实现一对一,一对多有几种方式?具体怎么操作的
- 一对一、一对多的关联查询 ?
- Mapper编写有哪几种方式?
spring
请谈一谈Spring中自动装配的方式有哪些
- no:不进行自动装配,手动设置Bean的依赖关系。
- byName:根据Bean的名字进行自动装配。
- byType:根据Bean的类型进行自动装配。
- constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。- autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。
自动装配没有自定义装配方式那么精确,而且不能自动装配简单属性(基本类型、字符串等),在使用时应注意。
请问Spring中Bean的作用域有哪些?
singleton:表示Bean以单例的方式存在
prototype:每次从容器中调用Bean时,都会返回一个新的实例
request:每次HTTP请求都会创建一个新的Bean
session:同一个HttpSession共享同一个Bean,不同的HttpSession使用不同的Bean
globalSession:同一个全局Session共享一个Bean
请问什么是IoC和DI?并且简要说明一下DI是如何实现的?
IoC叫控制反转,是Inversion of Control的缩写,DI(Dependency Injection)叫依赖注入,是对IoC更简单的诠释。控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的”控制反转”就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。IoC体现了好莱坞原则 - “Don’t call me, we will call you”。依赖注入的基本原则是应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI是对IoC更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
一个类A需要用到接口B中的方法,那么就需要为类A和接口B建立关联或依赖关系,最原始的方法是在类A中创建一个接口B的实现类C的实例,但这种方法需要开发人员自行维护二者的依赖关系,也就是说当依赖关系发生变动的时候需要修改代码并重新构建整个系统。如果通过一个容器来管理这些对象以及对象的依赖关系,则只需要在类A中定义好用于关联接口B的方法(构造器或setter方法),将类A和接口B的实现类C放入容器中,通过对容器的配置来实现二者的关联。依赖注入可以通过setter方法注入(设值注入)、构造器注入和接口注入三种方式来实现,Spring支持setter注入和构造器注入,通常使用构造器注入来注入必须的依赖关系,对于可选的依赖关系,则setter注入是更好的选择,setter注入需要类提供无参构造器或者无参的静态工厂方法来创建对象。
请说明一下Spring中BeanFactory和ApplicationContext的区别是什么?
<1>如果使用ApplicationContext,如果配置的bean是singleton,那么不管你有没有或想不想用它,它都会被实例化。好处是可以预先加载,坏处是浪费内存。
<2>BeanFactory,当使用BeanFactory实例化对象时,配置的bean不会马上被实例化,而是等到你使用该bean的时候(getBean)才会被实例化。好处是节约内存,坏处是速度比较慢。多用于移动设备的开发。
<3>没有特殊要求的情况下,应该使用ApplicationContext完成。因为BeanFactory能完成的事情,ApplicationContext都能完成,并且提供了更多接近现在开发的功能。
请说明一下springIOC原理是什么?如果你要实现IOC需要怎么做?请简单描述一下实现步骤?
IoC(Inversion of Control,控制倒转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。
IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
实现步骤:
通过applicationContext的实现类ClassPathResource来找到xml文件;接着通过BeanDefinition解析xml文件,解析后的结果封装成一个BeanDefinitionHolder;然后通过DefaultListableBeanFactory类来创建ConcurrentHashMap集合,通过beanDefinition提供的信息,将bean的name和class保存在Map集合中,完成bean的注册和实例化;最后通过BeanFactory的getBean()来获取bean实例
请简单说明一下依赖注入的方式有哪几种?以及这些方法如何使用?
1、Set注入 2、构造器注入 3、接口注入
4、静态工厂注入;
5、实例工厂;
请问在以前的学习中有使用过Spring里面的注解吗?如果有请谈一下autowired 和resource区别是什么?

请问Spring支持的事务管理类型有哪些?以及你在项目中会使用哪种方式?
Spring支持编程式事务管理和声明式事务管理。许多Spring框架的用户选择声明式事务管理,因为这种方式和应用程序的关联较少,因此更加符合轻量级容器的概念。声明式事务管理要优于编程式事务管理,尽管在灵活性方面它弱于编程式事务管理,因为编程式事务允许你通过代码控制业务。
事务分为全局事务和局部事务。全局事务由应用服务器管理,需要底层服务器JTA支持(如WebLogic、WildFly等)。局部事务和底层采用的持久化方案有关,例如使用JDBC进行持久化时,需要使用Connetion对象来操作事务;而采用Hibernate进行持久化时,需要使用Session对象来操作事务。
这些事务的父接口都是PlatformTransactionManager。Spring的事务管理机制是一种典型的策略模式,PlatformTransactionManager代表事务管理接口,该接口定义了三个方法,该接口并不知道底层如何管理事务,但是它的实现类必须提供getTransaction()方法(开启事务)、commit()方法(提交事务)、rollback()方法(回滚事务)的多态实现,这样就可以用不同的实现类代表不同的事务管理策略。使用JTA全局事务策略时,需要底层应用服务器支持,而不同的应用服务器所提供的JTA全局事务可能存在细节上的差异,因此实际配置全局事务管理器是可能需要使用JtaTransactionManager的子类,如:WebLogicJtaTransactionManager(Oracle的WebLogic服务器提供)、UowJtaTransactionManager(IBM的WebSphere服务器提供)等。
聊一下什么是Spring,以及核心思想?
主要有两大思想,IOC和AOP
(1)IOC是控制反转,就是控制权的转移,原先我们自己去创建对象的过程,现在交由Spring容器来管理,使得我们不用专注于对象的生死存亡,同时将对象的创建由原来的编译时延期到现在的运行时。
使用IOC容器来创建对象有两种方式,分别是xml方式和注解方式。
①先说一下xml方式:只需在xml配置文件中声明一个bean标签,并指定bean的id,和此bean的类型class,就可以创建一个对象了。如果需要注入属性,我们也有很多种方式注入,比如set注入(需要在对象实体中声明setter方法)、构造器注入(同样需要在对象实体中声明相应的构造器)、p命名空间注入,这个方式需要在头部引入相关的名称空间,等等。当然属性的注入支持多种类型的属性注入,有List、Map等等,使用相应的标签即可。在程序中如果需要获取注入到ioc容器中的对象,则需通过ApplicationContext的getBean(id方法将对象取出,这时候的对象就可以使用了。
②再说下注解方式:使用注解的前提是在xml配置文件中开启了注解扫描功能context:component-scan,需要定义一下要扫描的包。如果我们需要在程序中将一个对象交由springIOC容器去管理,我们可以使用@Component、@Service、@Controller、@Repository注解,这四个注解的功能其实是一样的,都是用于将类的对象放入Spring容器中,创建bean的实例,只不过使用的位置有些区别,component用在普通类、Service用在业务层、Controller用在控制层、Repository用在持久层。如果说在一个程序中需要使用刚刚放入到ioc容器的对象,可以使用@Autowired注解来将其注入到程序中,这时候对象是已经创建完成的,直接使用即可,比如说UserHandler中需要用到UserService,那就在UserService上加上@Service注解来进行实例化业务层的bean,然后在UserHandler中使用@Autowired private UserService userService进行注入。当然也可以使用@Resource注解来进行注入,具体的区别是@Autowired默认根据属性类型进行注入,而@Resource默认根据属性名称进行注入。还而已使用@Value注解来进行普通类型的属性注入,@Value(“Tom”) private String name;。
③也可以完全舍弃xml配置文件,这也是SpringBoot中的主要手段,声明一个配置类,类上使用@Configuration注解来标记此类是一个配置类。然后开启注解扫描功能,使用@ComponentScan(“”)注解,里面定义一下扫描的包即可。在此类中的方法上使用 @Bean注解,可以将此方法的return返回值作为一个bean实例放入到ioc容器中,相当于xml里面的bean标签
AOP是面向切面编程,将那些与业务无关,却为业务模块所使用的逻辑封装起来,比如说日志、通知,可以减少系统的重复代码,降低模块间的耦合度,能更好的进行扩展和维护。通俗地说:AOP可以在不修改源代码的基础上进行功能的添加、增强
Spring框架一般都是基于AspectJ实现AOP操作。有两种方式,一个是xml配合文件,一个是注解方式。
①xml配置文件:实现AOP需要在Spring配置文件中配置相应的通知和切入点。首先是要aop:pointcut来定义切入点,需要指定expression切入点表达式属性。然后使用aop:aspect来配置通知,method属性用来指定在哪个方法上应用此通知,pointcut-ref属性用于指定切入点,具体的有前置通知(在方法前执行)、后置通知(在方法后执行)、环绕通知(方法前后均执行)、最终通知(类似于finally,结束后执行,并且一定会执行)、异常通知(抛出异常后执行)。也可以使用AOP来实现事物功能,配置相应的aop:advisor切面和tx:advice事务通知,以及配置一下事物属性tx:attributes,使用tx:method可以为某些方法配置成只读,也可以配置某些方法的传播行为,以及何时回滚,这些增强配置完成后,将pointcut与当前的增强连接起来,就实现了一个AOP事物操作。
②注解方式:前提先在spring配置文件中开启注解扫描component-scan;然后实例化被增强的类,例如在User类上使用@Component注解来创建对象;接着定义一个代理类UserProxy来实现相应的增强方法,并且使用@Aspect注解来标记此类是一个增强类;配置文件中使用aspectj-*标签开启自动生成代理对象;里面的每个方法定义都需要使用@Around、@Before、@After等注解来声明此方法所对应的通知类型,并且在此注解的value属性中定义切入点表达式,声明切入点。如果多个方法使用了相同的切入点,可以使用@Pointcut注解进行抽取,然后在其他地方引用即可
Spring中有哪些容器
IOC有两大容器,分别是BeanFactory和ApplicationContext。BeanFactory是顶层接口,提供的是基础的IOC容器服务;而ApplicationContext是BeanFactory的子接口,提供更高级的IOC服务,比如有事件发布、国际化支持等等,当然我们正常情况下都是使用的ApplicationContext。ApplicationContext也有很多实现类:ClassPathXmlApplicationContext主要用在在类路径加载xml文件的场景,FileSystemXmlApplicationContext主要用在在文件系统中加载xml文件的场景,XmlWebApplicationContext主要用在在Web环境中加载xml文件的场景。
Spring的工作机制?
定位xml文件、解析xml文件、注册bean、获取bean实例。
通过applicationContext的实现类ClassPathResource来找到xml文件;接着通过BeanDefinition解析xml文件,解析后的结果封装成一个BeanDefinitionHolder;然后通过DefaultListableBeanFactory类来创建ConcurrentHashMap集合,通过beanDefinition提供的信息,将bean的name和class保存在Map集合中,完成bean的注册和实例化;最后通过BeanFactory的getBean()来获取bean实例。
BeanFactory和FactoryBean的区别?
BeanFactory是顶层IOC容器服务接口,提供了基本的容器服务。
而FactoryBean是一个Bean,Bean主要分为普通bean和工厂bean,而这个工厂bean就是FactoryBean。如果我们想自己来实现一个bean的创建操作,可以通过FactoryBean接口实现。我们可以通过该实现接口来定制实例化Bean的逻辑。接口中主要含有3个方法:
T getObject():返回由FactoryBean创建的Bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例的缓存池中。
Class<?> getObjectType():返回FactoryBean创建的Bean类型,也就是bean标签中配置的class属性,要与这里的方法返回的类型要一致。
default boolean isSingleton():返回Bean实例是singleton还是prototype的,默认是返回true,也就是使用singleton的
如果有一个类,比如说User类,并且实现了FactoryBean接口,重写了getObject()、getObjectType()、isSingleton()方法,那么在使用bean标签进行实例化bean时,在class属性是getObjectType()的值的全限定名。当取出对象getBean(“user”)时,Spring通过反射机制发现要返回的User类实现了FactoryBean接口,那么他会调用接口方法User.getObject()方法返回此实例,而不是使用默认的方法进行返回。因此也能说明,配置文件定义普通bean时,定义的bean类型就是返回类型,而定义工厂bean时,定义的bean类型可以和返回类型不一样,完全由getObject()来决定的。
AOP的底层实现是怎样的?
①在有接口的情况下,比如说对UserServiceImpl实现类进行AOP增强,则底层使用的是动态代理,创建接口实现类的代理对象,进行增强类中的方法
②在没有接口的情况下,底层使用的是cglib动态代理,创建子类的代理对象,进行增强类中的方法
动态代理的话就是新建一个代理类,实现InvocationHanler接口,重写invoke方法,此方法就是增强的功能,注意需要将被代理的对象属性注入到代理类中,即UserServiceImpl。在使用被代理的类方法时,我们可以调用Proxy.newProxyInstance()方法创建代理对象,传入动态代理的类加载器、被代理的接口、以及代理类对象,然后调用代理对象的相关方法,就能实现相应的增强功能
说一下bean的生命周期
分两种情况:一个是不带后置处理器的,一个是带后置处理器的
(1)不带后置处理器,总共5步:
①通过无参构造器构造一个bean的实例
②对bean中的属性进行设值和设置对其他bean的引用,调用setter方法,进行依赖注入
③调用bean的初始化方法
④这时bean就可以使用了
⑤容器关闭时,调用bean的销毁方法。
(2)带后置处理器,总共7步:
①通过无参构造器构造一个bean的实例
②对bean中的属性进行设值和设置对其他bean的引用,调用setter方法,进行依赖注入
③调用初始化方法之前,首先执行后置处理器的postProcessBeforeInitialization()方法,这是我们自己写的逻辑,在初始化之前完成一些特定的任务
④调用bean的初始化方法
⑤执行后置处理器的postProcessAfterInitialization()方法,对完成初始化的bean进行后续的额外操作
⑥这时bean就可以使用了
⑦容器关闭时,调用bean的销毁方法。
为什么要使用 spring?
简化开发,各个层次解耦。原本的MVC三层结构是紧密相连的,频繁使用了new创建对象操作,如果一个功能改变,其他两层的代码可能也会发生改变,这类系统进行维护和更新会变得繁琐。使用了Spring可以大大减少代码的修改,因为耦合度低了,对象的创建完全交由IOC容器完成,即时代码修改了,也不会对其他层次的代码造成太大影响。同时Spring支持aop编程,能更方便地在不修改源代码的基础上进行功能的增强。
Spring框架主要有哪些模块?
①Spring AOP 面相切面编程
②Spring ORM Hibernate|mybatis|JDO
③Spring Core 提供bean工厂 IOC
④Spring Dao JDBC支持
⑤Spring Context 提供了关于UI支持,邮件支持等
⑥Spring Web 提供了web的一些工具类的支持
⑦Spring MVC 提供了web mvc , webviews , jsp ,pdf ,export
spring 常用的注入方式有哪些?
①setter注入
②构造器注入
③p命名空间注入
④c命名空间注入
⑤接口注入(如@Service注解)
spring 中的 bean 是线程安全的吗?
不是,容器本身并没有提供Bean的线程安全策略
spring 自动装配 bean 有哪些方式?
1)在Spring框架xml配置中共有5种自动装配:
no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。
byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。
byType:通过参数的数据类型进行自动装配。
constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。
[
](https://blog.csdn.net/a745233700/article/details/80959716)
(2)基于注解的自动装配方式:
使用@Autowired、@Resource注解来自动装配指定的bean。在使用@Autowired注解之前需要在Spring配置文件进行配置,
如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
如果查询的结果不止一个,那么@Autowired会根据名称来查找;
如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。
[
](https://blog.csdn.net/a745233700/article/details/80959716)
spring 事务实现方式有哪些
pring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。Spring只提供统一事务管理接口,具体实现都是由各数据库自己实现,数据库事务的提交和回滚是通过binlog或者undo log实现的。Spring会在事务开始时,根据当前环境中设置的隔离级别,调整数据库隔离级别,由此保持一致。
1)Spring事务的种类:
spring支持编程式事务管理和声明式事务管理两种方式:
①编程式事务管理使用TransactionTemplate。
②声明式事务管理建立在AOP之上的。其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前启动一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
[
](https://blog.csdn.net/a745233700/article/details/80959716)
声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明或通过@Transactional注解的方式,便可以将事务规则应用到业务逻辑中,减少业务代码的污染。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。
(2)spring的事务传播机制:
① PROPAGATION_REQUIRED:(默认传播行为)如果当前没有事务,就创建一个新事务;如果当前存在事务,就加入该事务。
② PROPAGATION_REQUIRES_NEW:无论当前存不存在事务,都创建新事务进行执行。
③ PROPAGATION_SUPPORTS:如果当前存在事务,就加入该事务;如果当前不存在事务,就以非事务执行。‘
④ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
⑤ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则按REQUIRED属性执行。
⑥ PROPAGATION_MANDATORY:如果当前存在事务,就加入该事务;如果当前不存在事务,就抛出异常。
⑦ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
[
](https://blog.csdn.net/a745233700/article/details/80959716)
(3)Spring中的隔离级别:
① ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。
② ISOLATION_READ_UNCOMMITTED:读未提交,允许事务在执行过程中,读取其他事务未提交的数据。
③ ISOLATION_READ_COMMITTED:读已提交,允许事务在执行过程中,读取其他事务已经提交的数据。
④ ISOLATION_REPEATABLE_READ:可重复读,在同一个事务内,任意时刻的查询结果都是一致的。
⑤ ISOLATION_SERIALIZABLE:所有事务逐个依次执行。
Spring框架中有哪些不同类型的事件?
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会自动被通知。
[
](https://blog.csdn.net/a745233700/article/details/80959716)
[
](https://blog.csdn.net/a745233700/article/details/80959716)
SpringMVC篇
说一下spring mvc运行流程?
①前端发送请求,前端控制器DispatcherServlet进行拦截
②前端控制器DispatcherServlet调用处理器映射器HandlerMapping,根据url寻找相应的Handler
③寻找到Handler后生成处理器执行链HandlerExecutionChain,并返回给前端控制器
④前端控制器DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter,准备执行相应的handler
⑤执行Handler,返回ModelAndView到处理器适配器HandlerAdapter
⑥处理器适配器HandlerAdapter将Handler执行的结果ModelAndView返回到前端控制器DispatcherServlet
⑦前端控制器DispatcherServlet将ModelAndView传递给视图解析器ViewResolver
⑧视图解析器ViewResolver进行解析,返回View视图给前端控制器DispatcherServlet
⑨前端控制器DispatcherServlet进行渲染view视图,然后返回给用户
spring mvc 有哪些组件?
①前端控制器DispatcherServlet
②处理器Handler
③处理器映射器HandlerMapping
④处理器适配器HandlerAdapter
⑤拦截器HandlerInterceptor
⑥视图解析器ViewResolver
⑦视图View
⑧数据转换DataBinder
⑨消息转换组件HttpMessageConverter
@RequestMapping 的作用是什么?
用于接收请求,标识http请求地址与后端Controller层之间的映射关系,一般作用方法上,也能作用于类上。
该注解有6个属性:
value:指定请求地址
method:指定请求方式
consumes:指定请求提交的数据类型
produces:指定返回数据类型
params:指定请求中必须包含某些参数,才能进行处理
headers:指定请求中必须包含某些头部信息,才能进行处理
如何解决POST请求中文乱码问题,GET的又如何处理呢?
(1)解决post请求乱码问题:在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8;
<filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
(2)get请求中文参数出现乱码解决方法有两个:
①修改tomcat配置文件添加编码与工程编码一致,如下:
<ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
②另外一种方法对参数进行重新编码:
String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
SpringMvc里面拦截器是怎么写的
extends HandlerInterceptorAdapter或者 implements HandlerInterceptor
<!-- 配置SpringMvc的拦截器 -->
<mvc:interceptors>
<!-- 配置一个拦截器的Bean就可以了 默认是对所有请求都拦截 实现接口-->
<bean id="myInterceptor" class="com.zwp.action.MyHandlerInterceptor"></bean>
<!-- 只针对部分请求拦截 -->
<mvc:interceptor>
<mvc:mapping path="/modelMap.do" />
//继承Adapter
<bean class="com.zwp.action.MyHandlerInterceptorAdapter" />
</mvc:interceptor>
</mvc:interceptors>
注解原理
注解本质是一个继承了Annotation的特殊接口,其具体实现类是JDK动态代理生成的代理类。我们通过反射获取注解时,返回的也是Java运行时生成的动态代理对象。通过代理对象调用自定义注解的方法,会最终调用AnnotationInvocationHandler的invoke方法,该方法会从memberValues这个Map中查询出对应的值,而memberValues的来源是Java常量池————————————————
[
](https://blog.csdn.net/a745233700/article/details/80963758)
SpringMvc怎么和AJAX相互调用的?
通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下 :
(1)加入Jackson.jar
(2)在配置文件中配置json的映射
(3)在接受Ajax方法里面可以直接返回Object、List等,但方法前面要加上@ResponseBody注解。
[
](https://blog.csdn.net/a745233700/article/details/80963758)
Spring MVC的异常处理 ?
可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。
SpringMVC常用注解?
@Controller:用于标记一个类是控制层
@RequestMapping:用于定义请求
@Resource&@Autowired:进行bean的注入装配
@PathVariable:从请求路径中获取参数
@RequestParam:获取请求域中的参数
@ResponseBody:将对象放至response对象的body数据区,如json数据
@RequestBody:从request对象的body数据区获取对象
@RestController:是@Controller和@ResponseBody的合体
Mybatis篇
mybatis我遇到的问题不多,也希望各位不要仅复习下面这几个题目,仅供参考。
mybatis 中 #{}和 ${} 无法防止 sql 注入
②#{} 是预编译处理,${} 是字符串替换
Mybatis 在处理 #{} 时,会将 sql 中的 #{} 替换为 ‘?’ ,调用 PreparedStatement 的 set 方法来赋值,会将所有传入的参数作为一个字符串来处理,假设有个字符串(’’ or 1=1),那么使用 # 则直接将此字符串包裹在引号 ‘ ‘ 内,有效防止了 sql 注入
Mybatis 在处理 ${} 时,就是把 ${} 替换成变量的值,相当于进行了拼接,并没有使用引号 ‘ ‘ 包裹住
mybatis 有几种分页方式?
①数组分页,java层面的分页方式,逻辑分页。获取所有数据后,使用 List 的 subList() 进行筛选,最原始的方式
②limit分页,直接在数据库中进行分页,物理分页
③RowBounds分页,java层面的分页方式,逻辑分页
④PageHelper分页插件,也是数据库层面的分页方式,物理分页
Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的
sql,然后重写sql,添加对应的物理分页语句和物理分页参数。
简述Mybatis的插件运行原理,以及如何编写一个插件
Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,当然,只会拦截那些你指定需要拦截的方法。
编写插件:实现Mybatis的Interceptor接口并复写intercept()方法,然后再给插件编写注解,指定要拦截哪一个接口的哪些方法即可,最后在配置文件中配置你编写的插件。
[
](https://blog.csdn.net/a745233700/article/details/80977133)
Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
延迟加载的基本原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。
当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
如何获取自动生成的(主)键值?
如果采用自增长策略,自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中。
<insert id=”insertname” usegeneratedkeys=”true” keyproperty=”id”>
insert into names (name) values (#{name})
</insert>
物理分页与逻辑分页的区别?
分页插件、limit 分页,都是物理分页,优点是效率高,缺点是不同的数据库有不同的写法,无法统一
RowBounds、数组分页是 java 层面的,因此是逻辑分页,优点是所有数据库都统一,缺点是效率低
尽量使用物理分页,因为没有必要将数据库层的压力加到应用层上来,现在大多数客户需求都是低延迟的,尽量提高用户体验,使用物理分页最佳
说一下Mybatis的一级缓存和二级缓存?
一级缓存是默认开启的,也叫做本地缓存,它的作用范围是sqlSession对象的创建直至对象调用了close()。在与数据库的同一次会话中,查询到的数据会放到本地缓存中,对于sql完全一样的查询,直接从缓存中拿,无需再访问数据库
二级缓存需手动开启,也称全局缓存,是一个基于namespace级别的缓存,可以使用标签进行开启,如果未指定readOnly=true,则实体类需要实现序列化接口。只要开启了二级缓存,那么在同一个Mapper下是生效的,无论是否开启了新会话。但是,如果开启了二级缓存,所有的数据会先放在一级缓存中,只有当会话提交,或者关闭的时候,才会将一级缓存的内容提交到二级缓存中,也类似Java中的L1、L2、L3缓存。
mybatis 有哪些执行器(Executor)?
simpleexecutor简单执行器:每次进行数据库操作时,都新建一个statement对象,用完后关闭
reuseexecutor可重用执行器:每次进行数据库操作时,都以当前的sql作为key来查找statement,如果有则取出使用,如果没有则创建,使用完毕后不会关闭,而是放入一个Map集合中,以供下次使用
batchexecutor批处理执行器:会将所有的update语句都添加到批处理中,统一执行。
Mybatis有哪些常用标签?
select、update、insert、delete:编写增删查改 sql 语句
resultMap:配置结果集映射
mapper:一个mapper文件需要对应一个mapper标签,用于指定相应的namespace
sql、include:定义并重用 sql 片段,使用 include 进行引用
cache:用于开启二级缓存
if、where、set、choose、when、otherwise、foreach:用于编写动态sql,可以根据不同条件生成不同的sql语句,
association、collection:用于处理复杂映射关系,比如一对多和多对一,一对多需要使用集合collection,多对一需要使用association,注意相应的属性column和property的配置即可,同时也要结合resultMap使用
如何配置将mapper映射文件与Spring关联上?
在注入SqlSessionFactory时,配置相应的属性;
如果要绑定 mybatis 核心配置文件,使用 configLocation;如果要绑定 mapper 映射文件,使用 mapperLocations。
例如:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
<property name="mapperLocations" value="classpath*:com/gbanker/golddashi/**/mapper/*.xml" />
</bean>
MyBatis实现一对一,一对多有几种方式?具体怎么操作的
有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。
[
](https://blog.csdn.net/a745233700/article/details/80977133)
一对一、一对多的关联查询 ?
<mapper namespace="com.lcb.mapping.userMapper">
<!--association 一对一关联查询 -->
<select id="getClass" parameterType="int" resultMap="ClassesResultMap">
select * from class c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
</select>
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap">
<!-- 实体类的字段名和数据表的字段名映射 -->
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" javaType="com.lcb.user.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
</resultMap>
<!--collection 一对多关联查询 -->
<select id="getClass2" parameterType="int" resultMap="ClassesResultMap2">
select * from class c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id}
</select>
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap2">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" javaType="com.lcb.user.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
<collection property="student" ofType="com.lcb.user.Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
</mapper>
Mapper编写有哪几种方式?
(1)第一种:接口实现类继承SqlSessionDaoSupport:使用此种方法需要编写mapper接口,mapper接口实现类、mapper.xml文件
(1)在sqlMapConfig.xml中配置mapper.xml的位置
<mappers>
<mapper resource="mapper.xml文件的地址" />
<mapper resource="mapper.xml文件的地址" />
</mappers>
(2)定义mapper接口
(3)实现类继承SqlSessionDaoSupport
mapper方法中可以this.getSqlSession()进行数据增删改查。
(4)spring 配置
<bean id=" " class="mapper接口的实现">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
(2)第二种:使用org.mybatis.spring.mapper.MapperFactoryBean:
1)在sqlMapConfig.xml中配置mapper.xml的位置,如果mapper.xml和mappre接口的名称相同且在同一个目录,这里可以不用配置
<mappers>
<mapper resource="mapper.xml文件的地址" />
<mapper resource="mapper.xml文件的地址" />
</mappers>
(2)定义mapper接口:
①mapper.xml中的namespace为mapper接口的地址
②mapper接口中的方法名和mapper.xml中的定义的statement的id保持一致
③Spring中定义
<bean id="" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="mapper接口地址" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
第三种:使用mapper扫描器:
1)mapper.xml文件编写:
mapper.xml中的namespace为mapper接口的地址;
mapper接口中的方法名和mapper.xml中的定义的statement的id保持一致;
如果将mapper.xml和mapper接口的名称保持一致则不用在sqlMapConfig.xml中进行配置。
(2)定义mapper接口:
注意mapper.xml的文件名和mapper的接口名称保持一致,且放在同一个目录
(3)配置mapper扫描器:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="mapper接口包地址"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
(4)使用扫描器后从spring容器中获取mapper的实现对象。
总结:三种方式第一步都是配置xml文件的地址,第二部都是定义mapper接口。然后对于接口实现类继承SsqlSessionDAoSupport,我们就可以直接在实现的那些接口方法里面通过this.getSqlSession()进行数据增删改查。最后在把这个实现类配在ioc容器中,(记得里面有个sqlsessionFactory需要配置)。对于MapperFactoryBean,一二步也是一样的,他只需要在配置一个MapperFactoryBean的bean,里面有两个属性mapperInterface—-》指明mapper接口的地址,sqlSessionFactory—》指明sqlSessionFactory。 对于mapper扫描器MapperScannerConfigurer,一二部也是一样的,第三步,我们需要配置一个mapper扫描器,在这个扫描器当中有两个属性:basePackage—-》mapper接口的地址,sqlSessionFactoryBeanName——》sqlSessionFactory。最后我们启用扫描器,就可以从ioc容器中获取mapper的实例对象了
