Spring3MVC与Struts2MVC比较
1、SpringMVC支持Restful url,这感觉爽,就开发效率而言高;
2、SpringMVC基本实现了零配置,配置好Spring的ApplicationContext.xml和web.xml后,基本就不需要其他配置了。而且Spring的配置也相对简单。而struts2就不行了,需要的配置相对比较多,也比较复杂;
3、SpringMVC对每次请求是方法级的拦截,拦截到方法后根据参数上的注解,将request数据注入。一个方法对应一个request请求,并且SpringMVC方法之间是相互独立的,独享request和response数据。而StrutsMVC是类级别的拦截,每次请求来了就创建一个action,然后调用getter、setter方法。一个Action对应一个request上下文。
4、让人更爽的是SpringMVC知识JSR303,处理ajax的请求更加方面,只需要注解一个@ResponseBody,然后直接返回相应文件即可。
SpringMVC的工作流程描述:
1.用户向服务器发送请求, 请求被Spring前端控制Servlet DispatcherServlet所捕获;
2.DispatcherServlet对请求的URL进行解析,得到资源标识符.根据URI调用HandlerMapping获得该Handler配置的所有相关对象,最后以HandlerExecutionChain对象的形式返回;
3.DispatcherServlet根据获得的Handler选择一个合适的HandlerAdapter;
4.提取Request中的模型数据, 填充Handler入参,执行Controller,根据配置做一些额外的工作: 比如数据转换和验证;
5.Handler执行完成后, 向DispatcherServlet返回一个ModelAndView对象;
6.根据返回的ModelAndView,选择一个合适的ViewResolver返回给DispatcherServlet;
7.ViewResolver结合Model和View来渲染视图;
8.将视图返回给客户端.
Struts2的工作原理:
1.客户端初始化一个指向Servlet容器的请求;
2.这个请求经过一系列过滤器, Filter;
3.接着StrutsPrepareAndExecuteFilter被调用, StrutsPrepareAndExecuteFilter询问ActionMapper来决定是否需要调用某个Action;
4.如果ActionMapper决定调用某个Action, StrutsPrepareAndExecuteFilter把请求的处理交给ActionProxy;
Spring MVC:
一:配置阶段:
1.配置web.xml—DispatcherServlet;
2.设定init-param——contextConfigLocation=classpath:application…properties;
3.设定url-pattern——/*;
4.配置Annotation——@Controller @Service @Autowired @RequestMapping
二:初始化阶段:
1.调用init()方法—加载配置文件;
2.扫描相关的类——scan-package=”com.gupaodu”;
3.IOC容器初始化——Map
4.创建实例并保存至容器——通过反射机制将类实例化放入IOC容器中;
5.进行DI操作——扫描IOC容器中的实例,给没有赋值的属性自动赋值;
6.初始化HandlerMapping——将一个URL和一个Method进行一对一的关联映射Map
三:运行阶段:
1.调用doPost()/doGet()——Web容器调用doPost/doGet方法,获得request/response对象;
2.匹配HndlerMapping——从request对象中获得用户输入的url,找到其对应的Method;
3.反射调用method.invoke()——利用反射调用方法并返回结果;
4.Response.getWrite().write()——将返回结果输出到浏览器。
5. 请用自己的语言描述SpringIOC、DI、MVC的基本执行原理
SpringIOC, 控制反转(Inversion of Control),将spring中所有Bean的控制权(创建、消费、管理)交给SpringIOC容器,整个过程包括三个步骤:
①加载配置文件
通过io流读取配置文件,并存入property对象中
③扫描相关的类
通过scan-package属性指定扫描文件夹,遍历指定文件夹下的所有类文件,找出文件名称(排除非.class类型文件),保存到文件名列表
④初始化IOC容器,将扫描到的相关的类实例化,保存到IOC容器中
类似于Map
key取值有三种情况:
1)在多个包下出现相同类名,通过一种有效方式使其不同
2)默认的类名首字母小写
3)如果是接口,判断实现类个数,如果只有一个,默认选择这个实现类,如果多个,只能抛出异常
DI,依赖注入(Dependency Injection)
Spring 不仅保存了自己创建的对象,而且保存了对象与对象之间的关系,扫描IOC容器中的实例,找出实例的所有属性,如果有autowired注解,就在IOC容器中通过名字找到对应之前保存的对象,设置属性.
MVC M是返回的数据,V是ModeView解析给客户端返回的视图,C是Control相关的逻辑处理
存储url和类方法的键值对集合,客户端可以通过url找到对应的类方法,
通过反射机制,执行该方法并返回数据给客户端.
遍历IOC容器Map,找出含有注解为Controler的对象的所有方法,如果有类似RequestMapping注解,则获取url(clazz.getAnnotation的RequestMapping中的url+method.getAnnotation的RequestMapping中的url)值,并把以url作为key,method作为value的集合保存到HandlerMapping中,当客户端通过url匹配到HandlerMapping集合中的某个方法时,通过反射调用并返回数据视图给客户端.
6. 软件设计的基本原则:
设计模式:
Spring中的编程思想:
OOP: 面向对象编程(封装,继承,多态,一切皆对象),用程序来描述生活中一切事物(需求转换为代码实现).
BOP: 面向Bean编程,Java本身就是一种面向对象的编程,用一个个的Bean来体现.
不需要new Bean,只需要你声明,只需要关注bean和bean之间的联系.
AOP编程:解耦,专人做专事, 面向切面编程:找出多个bean中有一定规律的代码,开发时将其拆开,运行时再将其合并,面向切面编程就是面向规则编程.日志监控;事务开启,关闭;权限认证,统一错误管理, 自动缓存处理.
切面: 面向规则,具有相同规则的方法的集合体;
通知: 回调;
切入点: 需要代理的具体方法;
目标对象: 被代理的对象;
AOP代理: 主要有两种JDK和CGLib;
前置通知: 在invoke Pointcut之前调用;
后置通知: Pointcut之后调用, 织入的方法;
返回后通知: 返回值为Void, 织入的方法;
环绕通知: 只要触发调用, 织入的方法;
异常通知: Pointcut抛出异常.
a. Aspect(切面),通常是一个类,里面可以定义切入点和通知;
b. JoinPoint(连接点),程序执行过程中明确的点,一般是方法的调用;
c. Advice(通知):Aop在特定的切入点上执行的增强处理;
d. Pointcut(切入点),就是带有通知的连接点,在程序中主要体现为书写切入点表达式;增强同一规律的方法.
IoC:控制反转:控制权反转,把创建对象的控制权反转给Spring(BeanFactory)DI: 依赖注入,依赖查找,自动赋值,三种赋值方法:构造方法, set赋值,直接赋值(反射,暴力强吻).(@Autowired private Object object; @Resource(“bean”) public void setName(){} )
事务用法:
原子性:要么全部完成, 要么全部不起作用;
一致性: 使一个一致性状态变成另一个一致性状态;
隔离性: 一个事务的执行不能被另一个事务干扰;
持久性: 事务一旦被提交, 它对数据库中数据的改变就是永久性的.
Spring中的设计模式:
工厂模式: 只对结果负责, 封装创建过程.(BeanFactory, Calender)
单例模式:保证独一无二.(ApplicationContext, Calender)
原型模式:拔一根猴毛,吹出千万根.(ArrayList[extends Cloneable], PrototypeBean)
代理模式:找人办事增强职责.(ProxyFactoryBean, CglibAopProxy)
委派模式:干活算你的(普通员工),功劳算我的(项目经理).(DispatcherServlet)
策略模式:用户选择, 结果统一.(InstantiationStrategy)
模板模式:流程标准化,自己实现定制.(jdbcTemplate, HttpServlet)
适配器模式:兼容转换头.(AdvisorAdapter, HandlerAdapter)
装饰器模式:他大舅他二舅都是他舅.(BufferedReader)
观察者模式:广播, 任务完成时通知.(ContextLoaderListener)
Spring框架能给我们带来哪些好处:
简化开发:
a) DI:使得JavaBean之间的依赖关系一目了然;
b) IOC:帮助我们管理好系统中的Bean,分阶段,分层次系统地管理,性能提高了;
万能胶:能够兼容市面上很多成熟的框架:比如Struts,MyBatis,Quartz,Timer,Shiro,Data
模块化设计:将包和类通过不同的模块完整的隔离开来,能够在使用的时候即插即用,按需分配;比如插件的引用,用哪个就引用哪个;
自带测试组件:JUnit;
Web MVC:支持的非常合理,过度设计的嫌疑(Struts中Form和Action对应出现, Spring只需要Bean和Attribute不需要Form),完美分离了Servlet和普通的Bean的关联关系;
声明式事务:将非功能性代码和功能性代码分离,提出了事务管理提前声明,通过不同的切面实现不同的切面模型,大大提高了维护成本。
BeanFactory和ApplicationContext的区别:
ApplicationContext是BeanFactory的子接口: getBean();1.IOC容器中的Bean监控,生命周期;
支持国际化i18n;
拓展了统一资源文件读取方式URL,可以是一个本地的URL,也可以是一个网络URL,ClassPathXmlApplicationContext从ClassPath的XML中配置文件中读取上下文,生成上下文定义,即指的是程序运行的环境;
FileSystemXmlApplicationContext,由文件系统中的XML配置文件读取上下文;
XmlWebApplicationContext由Web应用的XML文件读取上下文;,
AnnotationConfigApplicationContext使用他可以实现基于Java的配置类加载Spring应用的上下文,避免使用application.xml进行配置,相比XML配置来说更加敏捷。
Spring Bean的生命周期:
初始化之后的回调:initializingBean;
销毁之前的回调:DisposableBean;
init()和destroy();
通过注解:@PostConstruct和@PreDestroy
Spring Bean各作用域之间的区别:
总共5个范围,对象何时创建,何时销毁:
prototype: 为每一个Bean请求提供一个实例:【顶层1岁】
singleton: 默认的,单例模式由Bean Factory自身来维护,跟spring同生共死;【顶层100岁】
request: 用户发出请求的时候request出生【Web层10岁】
session:确保每个session中有一个Bean实例,session过期Bean自然失效【Web层20岁】;
globel-session Context:【80岁】
Spring中的Bean是线程安全的吗:
Spring中的Bean是由IOC容器来创建的,而创建的对象是自己定义的,BeanDefinition->BeanWrapper->Class.newInstance()->Map
MVC是什么?:
MVC是Model—View—Controler的简称。即模型—视图—控制器。MVC是一种设计模式,它强制性的把应用程序的输入、处理和输出分开。MVC中的模型、视图、控制器它们分别担负着不同的任务。
视图: 视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。
模型: 模型表示业务数据和业务处理。相当于JavaBean。一个模型能为多个视图提供数据。这提高了应用程序的重用性
控制器: 当用户单击Web页面中的提交按钮时,控制器接受请求并调用相应的模型去处理请求。 然后根据处理的结果调用相应的视图来显示处理的结果。
MVC的处理过程:首先控制器接受用户的请求,调用相应的模型来进行业务处理,并 返回数据给控制器。控制器调用相应的视图来显示处理的结果。并通过视图呈现给用户。
MVC 缺点:
(1)增加了系统结构和实现的复杂性。
(2)视图与控制器间的过于紧密的连接。
(3)视图对模型数据的低效率访问。
(4) 目前,一般高级的界面工具或构造器不支持MVC 模式。
MVC 优点:
(1)将用户显示(视图)从动作(控制器)中分离出来,提高了代码的重用性。
(2)实现一个模型的多个视图;采用多个控制器;当模型改变时,所有视图将自动刷新;所有的控制 器将相互独立工作。(3)它还有利于软件工程化管理。
为什么要用MVC:
优点:降低耦合度、增强内聚性。
使人员职能分工明确,有助于团队开发
有助于分布式开发。4. 封装分解系统的复杂性
Struts2框架?:
定义: Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。
底层执行过程:
Struts1和Struts2框架的区别?:
1.Action方面: 前者继承一个抽象基类, 后者的Action可以实现接口, 也可以实现其他接口, 也可以不实现任何接口,继承ActionSupport类;
2.线程模式方面: 前者的Action与Servlet API是紧耦合的, 后者不依赖于Servlet容器;
3.输入捕获:前者使用ActionForm对象捕获输入, 后者直接使用Action属性作为输入属性;
4.表达式语言: 前者整合了JSTL使用他的EL;后者支持OGNL;
5.数据校验方面: 前者支持在ActionForm的validate方法中手动校验;后者通过validate方法和XWork校验框架(拦截器机制)来进行校验;
6.前者所有模块中的Action必须共享相同的生命周期单例; 后者支持通过堆栈为每一个Action创建不同的生命周期,多例;
Spring事务的特性:
原子性:要么全部完成, 要么全部不起作用;
一致性: 使一个一致性状态变成另一个一致性状态;
隔离性: 一个事务的执行不能被另一个事务干扰;
持久性: 事务一旦被提交, 它对数据库中数据的改变就是永久性的.
Spring的常用注解:
Spring部分
1、声明bean的注解
@Component 组件,没有明确的角色
@Service 在业务逻辑层使用(service层)
@Repository 在数据访问层使用(dao层)
@Controller 在展现层使用,控制器的声明(C)
2、注入bean的注解
@Autowired:由Spring提供
@Inject:由JSR-330提供
@Resource:由JSR-250提供
都可以注解在set方法和属性上,推荐注解在属性上(一目了然,少写代码)。
3、java配置类相关注解
@Configuration 声明当前类为配置类,相当于xml形式的Spring配置(类上)
@Bean 注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式(方法上)
@Configuration 声明当前类为配置类,其中内部组合了@Component注解,表明这个类是一个bean(类上)
@ComponentScan 用于对Component进行扫描,相当于xml中的(类上)
@WishlyConfiguration 为@Configuration与@ComponentScan的组合注解,可以替代这两个注解
4、切面(AOP)相关注解
Spring支持AspectJ的注解式切面编程。
@Aspect 声明一个切面(类上)
使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。
@After 在方法执行之后执行(方法上)
@Before 在方法执行之前执行(方法上)
@Around 在方法执行之前与之后执行(方法上)
@PointCut 声明切点
在java配置类中使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持(类上)
5、@Bean的属性支持
@Scope 设置Spring容器如何新建Bean实例(方法上,得有@Bean)
其设置类型包括:
Singleton (单例,一个Spring容器中只有一个bean实例,默认模式),
Protetype (每次调用新建一个bean),
Request (web项目中,给每个http request新建一个bean),
Session (web项目中,给每个http session新建一个bean),
GlobalSession(给每一个 global http session新建一个Bean实例)
@StepScope 在Spring Batch中还有涉及
@PostConstruct 由JSR-250提供,在构造函数执行完之后执行,等价于xml配置文件中bean的initMethod
@PreDestory 由JSR-250提供,在Bean销毁之前执行,等价于xml配置文件中bean的destroyMethod
6、@Value注解
@Value 为属性注入值(属性上)
支持如下方式的注入:
》注入普通字符
》注入操作系统属性
》注入表达式结果
》注入其它bean属性
》注入文件资源
》注入网站资源
》注入配置文件
注入配置使用方法:
① 编写配置文件(test.properties)
book.name=《三体》
② @PropertySource 加载配置文件(类上)③
还需配置一个PropertySourcesPlaceholderConfigurer的bean。
7、环境切换
@Profile 通过设定Environment的ActiveProfiles来设定当前context需要使用的配置环境。(类或方法上)
@Conditional Spring4中可以使用此注解定义条件话的bean,通过实现Condition接口,并重写matches方法,从而决定该bean是否被实例化。(方法上)
8、异步相关
@EnableAsync 配置类中,通过此注解开启对异步任务的支持,叙事性AsyncConfigurer接口(类上)
@Async 在实际执行的bean方法使用该注解来申明其是一个异步任务(方法上或类上所有的方法都将异步,需要@EnableAsync开启异步任务)
9、定时任务相关
@EnableScheduling 在配置类上使用,开启计划任务的支持(类上)
@Scheduled 来申明这是一个任务,包括cron,fixDelay,fixRate等类型(方法上,需先开启计划任务的支持)
10、@Enable*注解说明
这些注解主要用来开启对xxx的支持
@EnableAspectJAutoProxy 开启对AspectJ自动代理的支持
@EnableAsync 开启异步方法的支持
@EnableScheduling 开启计划任务的支持
@EnableWebMvc 开启Web MVC的配置支持
@EnableConfigurationProperties 开启对@ConfigurationProperties注解配置Bean的支持
@EnableJpaRepositories 开启对SpringData JPA Repository的支持
@EnableTransactionManagement 开启注解式事务的支持
@EnableTransactionManagement 开启注解式事务的支持
@EnableCaching 开启注解式的缓存支持
11、测试相关注解
@RunWith 运行器,Spring中通常用于对JUnit的支持
@ContextConfiguration 用来加载配置ApplicationContext,其中classes属性用来加载配置类
SpringMVC部分
@EnableWebMvc 在配置类中开启Web MVC的配置支持,如一些ViewResolver或者MessageConverter等,若无此句,重写WebMvcConfigurerAdapter方法(用于对SpringMVC的配置)。
@Controller 声明该类为SpringMVC中的Controller
@RequestMapping 用于映射Web请求,包括访问路径和参数(类或方法上)
@ResponseBody 支持将返回值放在response内,而不是一个页面,通常用户返回json数据(返回值旁或方法上)
@RequestBody 允许request的参数在request体中,而不是在直接连接在地址后面。(放在参数前)
@PathVariable 用于接收路径参数,比如@RequestMapping(“/hello/{name}”)申明的路径,将注解放在参数中前,即可获取该值,通常作为Restful的接口实现方法。
@RestController 该注解为一个组合注解,相当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都默认加上了@ResponseBody。
@ControllerAdvice 通过该注解,我们可以将对于控制器的全局配置放置在同一个位置,注解了@Controller的类的方法可使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上,
这对所有注解了 @RequestMapping的控制器内的方法有效。
@ExceptionHandler 用于全局处理控制器里的异常
@InitBinder 用来设置WebDataBinder,WebDataBinder用来自动绑定前台请求参数到Model中。
@ModelAttribute 本来的作用是绑定键值对到Model里,在@ControllerAdvice中是让全局的@RequestMapping都能获得在此处设置的键值对。
@Component
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注
@Repository
用于标注数据访问组件,即DAO组件
@Controller
标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象.
@RestController
Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式。
@Service
用于标注业务层组件,说白了就是加入你有一个用注解的方式把这个类注入到spring配置中
@Autowired
用来装配bean,都可以写在字段上,或者方法上。
默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,例如:@Autowired(required=false)
@RequestMapping
类定义处: 提供初步的请求映射信息,相对于 WEB 应用的根目录。
方法处: 提供进一步的细分映射信息,相对于类定义处的 URL。
@RequestParam
用于将请求参数区数据映射到功能处理方法的参数上
@Cacheable
用来标记缓存查询。可用用于方法或者类中,当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。
@Resource
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。
@PostConstruct
用来标记是在项目启动的时候执行这个方法。用来修饰一个非静态的void()方法
也就是spring容器启动时就执行,多用于一些全局配置、数据字典之类的加载
被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次
PostConstruct在构造函数之后执行,init()方法之前执行。PreDestroy()方法在destroy()方法执行执行之后执行
@PreDestroy
被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,
类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前
@Qualifier
当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,
在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。
@ComponentScan
默认是代表进行扫描当前包
含有两个参数:
basePackages:可以扫描多个包,是一个数组类型,可能会造成产生多个Bean实例
basePackageClasses:可以扫描多个方法,是一个数组类型,可能会造成产生多个Bean实例
@Scope
用来配置 spring bean 的作用域,它标识 bean 的作用域。
默认值是单例
1、singleton:单例模式,全局有且仅有一个实例
2、prototype:原型模式,每次获取Bean的时候会有一个新的实例
3、request:request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
4、session:session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
5、global session:只在portal应用中有用,给每一个 global http session 新建一个Bean实例。
20. MyBatis与Hibernate的区别:
相同点:
1. 针对简单逻辑,Hibernate和MyBatis都有相应的代码生成工具,可以生成简单基本的DAO层方法;
2.Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。
最大区别: 针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程。
开发难度对比: Hibernate的开发难度要大于Mybatis。主要由于Hibernate比较复杂、庞大,学习周期较长。而Mybatis则相对简单一些,并且Mybatis主要依赖于sql的书写,让开发者感觉更熟悉。缺点就是框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
3 数据库扩展性比较: Mybatis由于所有SQL都是依赖数据库书写的,所以扩展性,迁移性比较差。Hibernate与数据库具体的关联都在XML中,所以HQL对具体是用什么数据库并不是很关心。
总结:
mybatis:小巧、方便、高效、简单、直接、半自动
hibernate:强大、方便、高效、复杂、绕弯子、全自动
MyBatis框架:
(1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
(2)MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
(3)通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。
优点:
JDBC连接数据库会出现代码重复,资源管理,结果集处理,SQL耦合等问题。
ORM框架能够很好的解决这些问题。
Hibernate自动生成SQL,基于SQL去做一些优化比较困难。不够灵活
Mybatis半自动化,主要解决SQL和对象映射问题。
MyBatis是一个半自动的ORM框架。它解决了如下问题:
(1)避免执行SQL操作时的重复代码。
(2)对连接池资源进行统一封装。
(3)对资源的释放关闭等进行统一封装。
(4)对数据库操作的常规步骤使用模板模式进行封装。
(5)对数据库的入参、出参转换进行封装。
(6)支持缓存。
(7)支持SQL、出入参的转换映射可配置化。
(8)支持四大组件的添加拦截器。
(9)对一些组件,像日志、statement进行了代理增强等。
MyBatis框架的缺点:
(1)SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
(2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
JDBC编程有哪些不足之处,Mybatis是如何解决这些问题的?
jdbc连接数据库,会对每一次的连接创建一个线程,使用完毕后关闭线程,频繁的操作会造成系统资源的浪费从而影响性能
在mybatis的配置文件中配置数据库连接池
jdbc的sql语句写在代码中造成代码不易维护 sql变动需要改变Java代码
mybatis将sql语句配置在mapper.xml文件中与Java代码分离 也可以接口映射(约定大于配置)
jdbc的sql语句传参比较麻烦 sql语句的where条件不一定 占位符和参数一一对应
mybatis会自动将Java对象映射至sql语句
jdbc对结果集解析比较麻烦 需要使用游标将结果集一条一条的遍历出来
mybatis自动将sql执行结果映射到Java对象
22. 基于Spring JDBC手写定制自己的ORM框架:
1.加载驱动 Class.forName(驱动名)
2.建立连接 DriverManager.getConnection(URL,用户名,密码)
3.根据传入的对象获取对象实例 Class> clazz = obj.getClass();
4.通过反射获取对象注解@Table表名,@Column列名(
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
field.setAccessible(true);
if(field.isAnnotationPresent(Column.class)){
Column column = field.getAnnotation(Column.class);}})
5.维护实体属性名和列名映射关系。
6.实体属性名和列名组装sql
7.创建语句集 connection.prepareStatement(sql)
8.判断是否开启事务
9.执行语句集 prepareStatement.executeQuery(sql)
10.获取结果集 ResultSet
11.处理结果集,根据实体属性名和列名将结果集组装成对象.
12.如果有事务,提交事务
13.关闭结果集,关闭语句集,关闭连接
MyBatis源码中用到了哪些设计模式?
1.工厂模式:SqlSessionFactory, ObjectFactory, DataSourceFactory, TransactionFactory, ReflectorFactory;
2.建造者模式:SqlSessionFactoryBuilder, XMLConfigBuilder, XMLMapperBuilder, XMLStatementBuilder, CacheBuilder;
3.代理模式: MapperProxy, Plugin, PooledConnection, ConnectionLogger, ResultSetLogger, StatementLogger, PreparedStatementLogger;
4.模板方法模式: AttributeValueTemplate, CallTemplate;
5.适配器模式: ComponentAdapter, ContainerAdapter, BeanAdapter;
6.单例模式: LogFactory;
7.享元模式: MapperRegistry, TypeHandlerRegistry, TypeAliasRegistry;
8.策略模式: DataSource, 还有根据MappedStatement里面的statementType决定StatementHandler的类型;
9.装饰器模式: LRUCache;
10.解释器模式: ParameterExpression.
Statement和PrepareStatement的区别:
1.两个都是接口, PrepareStatement是继承自Statement的;
#和KaTeX parse error: Expected 'EOF', got '#' at position 6: 的区别: #̲{}是预编译处理,{}是字符串替换.
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理 时 , 就 是 把 {}时,就是把 时,就是把{}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。
总结:
1.是否能防止SQL注入: $方式不会对符号转义, 不能防止SQL注入;
2.性能方面: KaTeX parse error: Expected 'EOF', got '#' at position 20: …预编译, 不会缓存; 3.能用#̲号的地方尽量用#号; 4.常量….
XML中怎样使用特殊字符:
1.转义<<(大于可以直接写);
2.使用–当XML遇到这种格式就会把[]里面的内容原样输出, 不进行解析.
通用Mapper可以解决哪些问题:
1.每个Mapper接口中大量的重复方法的定义;
2.屏蔽数据库的差异;
3.提供批量操作的方法;
4.实现分页.
用注解还是用xml配置:
常用注解: @Insert, @Select, @Update, @Delete, @Param, @Results, @Result
在MyBatis的工程中,我们有两种配置SQL的方式,一种是在Mapper.xml中集中管理, 一种是在Mapper接口上,用注解方式配置SQL: 注解的缺点是SQL无法集中管理, 复杂的SQL很难配置. 所以建议在业务复杂的项目中只使用XML配置的形式,业务简单的项目中可以使用注解和XML混用的形式.
association和collection的区别:
association是用于一对一和多对一,
而collection是用于一对多的关系.
一对一关联查询的几种配置方式:
当实体类中的属性名和表中的字段名不一样 ,怎么办 :
第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
第2种: 通过来映射字段名和实体类属性名的一一对应的关系。
在mapper中如何传递多个参数?
Mybatis动态sql有什么用?执行原理?有哪些动态sql?
Mybatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,
执行原理是根据表达式的值 完成逻辑判断并动态拼接sql的功能。
Mybatis提供了9种动态sql标签:
trim(替换) | where (where条件的追加)| set(用于修改多个列) | foreach(循环结果集) | if(判断) | choose | when | otherwise (相当于Java中的if(){}else{} 两者选其一)| bind。
Xml映射文件中,除了常见的select|insert|update|delete标签之外,还有哪些标签?
(结果集映射)、、、、(生成主键),
加上动态sql的9个标签,其中为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。
35.Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
不同的Xml映射文件,如果配置了namespace,那么id可以重复;
如果没有配置namespace,那么id不能重复;
原因: namespace+id是作为Map
但是,在以前的Mybatis版本的namespace是可选的,不过新版本的namespace已经是必须的了。
36.一对一关联查询和一对多关联查询:
37.一对一关联查询有几种方式?
有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。
38. 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,支持延迟加载的原理都是一样的.
39. Mybatis的一级、二级缓存:
1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear 掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新。
40. 什么是MyBatis的接口绑定?有哪些实现方式?
接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。
接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多。
41、使用MyBatis的mapper接口调用时有哪些要求?
① Mapper接口方法名和mapper.xml中定义的每个sql的id相同;
② Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;
③ Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;
④ Mapper.xml文件中的namespace即是mapper接口的类路径。
42.简述Mybatis的插件运行原理,以及如何编写一个插件。
Mybatis采用责任链模式,通过动态代理组织多个插件(拦截器),
通过这些插件可以改变Mybatis的默认行为(诸如SQL重写之类的).
• Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
• ParameterHandler (getParameterObject, setParameters)
• ResultSetHandler (handleResultSets, handleOutputParameters)
• StatementHandler (prepare, parameterize, batch, update, query)
总体概括为:
• 拦截执行器的方法
• 拦截参数的处理
• 拦截结果集的处理
• 拦截Sql语法构建的处理
Mybatis的插件是采用对四大接口的对象生成动态代理对象的方法来实现的。
Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
编写插件:实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
43.Mybatis是否可以映射Enum枚举类?
Mybatis可以映射枚举类,不单可以映射枚举类,Mybatis可以映射任何对象到表的一列上。映射方式为自定义一个TypeHandler,实现TypeHandler的setParameter()和getResult()接口方法。TypeHandler有两个作用,一是完成从javaType至jdbcType的转换,二是完成jdbcType至javaType的转换,体现为setParameter()和getResult()两个方法,分别代表设置sql问号占位符参数和获取列查询结果。
44.mybatis编程步骤是什么样的?
1.创建SqlSessionFactory:
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
2.通过SQLSessionFactory创建SqlSession
SqlSession openSession = sqlSessionFactory.openSession();
3、通过sqlsession执行数据库操作
4、调用session.commit()或session.rollback()
5、调用session.close()关闭会话
45. Hibernate工作原理及为什么要用?:
对 JDBC 访问数据库的代码做了封装,简化了数据访问层繁琐的重复性代码
映射的灵活性, 它支持各种关系数据库, 从一对一到多对多的各种复杂关系.
非侵入性、移植性会好
缓存机制: 提供一级缓存和二级缓存
②. 缺点:
无法对 SQL 进行优化
框架中使用 ORM原则, 导致配置过于复杂
执行效率和原生的JDBC 相比偏差: 特别是在批量数据处理的时候
不支持批量修改、删除
com.example.myproject 目录下:
• Application.java:建议放到根目录下面,是项目的启动类,Spring Boot 项目只能有一个 main 方法。
• comm:目录建议放置公共的类,如全局的配置文件、工具类等。
• domain:目录主要用于实体(Entity)与数据访问层(Repository)。
• repository:数据库访问层代码。
• service:该层主要是业务类代码。
• web:该层负责页面访问控制。
resources 目录下:
• static:目录存放 Web 访问的静态资源,如 JS、CSS、图片等。
• templates:目录存放页面模板。
• application.properties:项目的配置信息。
test 目录存放单元测试的代码;pom.xml 用于配置项目依赖包,以及其他配置。
采用默认配置可以省去很多设置,当然也可以根据自己的喜好来进行更改。最后,启动 Application main 方法,至此一个 Java 项目搭建好了!
什么是YAML?
YAML是一种人类可读的数据序列化语言。它通常用于配置文件。 与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。
springboot自动配置的原理 :
在spring程序main方法中 添加@SpringBootApplication或者@EnableAutoConfiguration 会自动去maven中读取每个starter中的spring.factories文件 该文件里配置了所有需要被创建spring容器中的bean.
springboot读取配置文件的方式:
springboot默认读取配置文件为application.properties或者是application.yml;
Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
@SpringBootConfiguration:组合了 @Configuration 注解它是JavaConfig形式的基于SpringIoC容器的配置类使用的一种注解,标注它也是一个IoC容器的配置类,在这个配置类中任何标注了@Bean的方法,它的返回值都会作为Bean定义注册到Spring的IoC容器,方法名默认为这个Bean的id ,实现配置文件的功能。
@ComponentScan:相当于xml配置文件中的context:component-scan主要作用是扫描指定路径下的标识了需要装配的类, 自动装配到Spring的IoC容器中, 包括: @Component, @Repository, @Service, @Controller.
@EnableAutoConfiguration:主要作用就是帮助springboot应用把所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器中.
包含@Import注解: 这个注解就是把多个分来的容器配合合并在一个配置中.
AutoConfigurationImportSelector:根据上下文激活不同类型的Bean
@Import注解可以配合三种不同的class: 1.基于普通bean或者带有@Configuration的bean进行注入; 2.实现ImportSelector接口进行动态注入; 3.实现ImportBeanDefinitionRegistrar接口进行动态注入.
工具类SpringFactoriesLoader的作用是从classpath/META-INF/spring.factories文件中根据key加载对应的类到spring IoC容器中.
条件过滤@Conditional: 扫描spring-autoconfiguration-metadata.properties文件, 最后在扫描spring.facotories对应的类时, 会结合元数据进行过滤,通过条件过滤可以有效地减少@Configuraiton类的数量从而降低SpringBoot的启动时间.如@ConditionalOnBean/OnMissingBean/OnClass/OnResource/OnProperty
47.微服务框架:SpringCloud:
微服务是一种架构模式或者说是一种架构风格, 他提倡将单一应用程序划分成一组小的服务: 服务之间采用轻量级的通信机制互相沟通, 通常是基于HTTP的Restful API, 能够被独立部署到生产环境.
微服务的优点:
1.每个服务足够内聚, 足够小, 代码容易理解这样能聚焦一个指定的业务功能和需求;
2.开发简单开发效率高, 一个服务专一干一件事情;
3.能够被小团队单独开发;
4.使用不同语言开发;
5.容易与第三方集成;
6.微服务只是业务逻辑的代码不会和HTML, CSS或者其他界面组件混合;
7.每个服务都有自己的存储能力, 可以有自己的数据库也可以有统一的数据库.
微服务的缺点:
1.开发人员要处理分布式系统的复杂性;
2.多服务运维难度增加;
3.系统部署依赖;
4.服务间的通讯成本;
5.系统集成测试.
48.Activity工作流: