龙空技术网

Java框架开发面试题汇总

CameSawConquer 248

前言:

眼前你们对“java ee框架技术课后题答案”可能比较着重,大家都想要了解一些“java ee框架技术课后题答案”的相关知识。那么小编在网络上收集了一些对于“java ee框架技术课后题答案””的相关知识,希望看官们能喜欢,兄弟们一起来了解一下吧!

1.Hibernate与Mybatis

1.hibernate

1、hibernate的开发流程

1、加载hibernate的配置文件,读取配置文件的参数(jdbc连接参数,数据库方言,hbm表与对象关系的映射文件)

2、创建sessionfactory会话工厂(内部有连接池参数)

3、打开session获取连接,构造session对象(一次会话维持一个数据连接,也是一级缓存)

4、开启事务

5、进行操作

6、提交事务

7、关闭session(会话)将连接释放

8、关闭连接池

2、Hibernate与MyBatis的区别

相同点

都是对jdbc的封装,都是应用于持久层的框架

不同点

映射关系MyBatis 是一个半自动映射的框架,配置Java对象与sql语句执行结果的对应关系,多表关联关系配置简单Hibernate 是一个全表映射的框架,配置Java对象与数据库表的对应关系,多表关联关系配置复杂SQL优化和移植性Hibernate 对SQL语句封装,提供了日志、缓存、级联(级联比 MyBatis 强大)等特性,此外还提供 HQL(Hibernate Query Language)操作数据库,数据库无关性支持好,但会多消耗性能。如果项目需要支持多种数据库,代码开发量少,但SQL语句优化困难。MyBatis 需要手动编写 SQL,支持动态 SQL、处理列表、动态生成表名、支持存储过程。开发工作量相对大些。直接使用SQL语句操作数据库,不支持数据库无关性,但sql语句优化容易。

3、Hibernate和JDBC优缺点对比

相同点:

两者都是java数据库操作的中间件两者对数据库进行直接操作的对象都是线程不安全的,都需要及时关闭两者都可对数据库的更新操作进行显式的事务处理

不同点:

JDBC是SUN公司提供一套操作数据库的规范,使用java代码操作数据库。Hibernate是一个基于jdbc的主流持久化框架,对JDBC访问数据库的代码做了封装使用的SQL语言不同:JDBC使用的是基于关系型数据的标准SQL语言,Hibernate使用的是HQL(Hibernate query language)语言操作的对象不同:JDBC操作的是数据,将数据通过SQL语句直接传送到数据库中执行,Hibernate操作的是持久化对象,由底层持久化对象的数据更新到数据库中数据状态不同:JDBC操作的数据是“瞬时”的,变量的值无法与数据库中的值保持一致,而Hibernate操作的数据是可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的

4、hibernate中对象的三种状态

瞬时态(临时态、自由态):不存在持久化标识OID,尚未与hibernate session关联对象,被认为处于瞬时态,失去引用将被JVM回收

持久态:存在持久化标识OID,与当前session有关联,并且相关联的session没有关闭,并且事务未提交

托管太(离线态、游离态):存在持久化标识OID,但没有与当前session关联,托管态改变hibernate不能检测到

5、hibernate的缓存机制

hibernate缓存分为两层:hibernate的一级缓存和hibernate的二级缓存

1、hibernate一级缓存(session的缓存):

(1)Session实现了第一级Cache,属于事务级数据缓冲,一旦事务结束,缓存随之失效,一个session的生命周期对应一个数据库事务或一个程序事务

(2)Session-Cache总是被打开并且不能被关闭的。

(3)Session-Cache保证一个Session中两次请求同一个对象时,取得的对象是同一个Java实例,有时它可以避免不必要的数据冲突

a.在对于同一个对象进行循环引用时,不至于产生堆栈溢出。

b.当数据库事务结束时,对于同一个数据表行,不会产生数据冲突,因为对于数据库中的一行,最多有一个对象来表示它。

​ c.一个事务中可能会有很多个处理单元,在每一个处理单元中做的操作都会立即被其他的数据单元得知。

2、hibernate二级缓存(SqlSessionFactory的缓存):

(1)二级缓存是SessionFactory范围内的缓存,所有的Session共享同一个二级缓存。在二级缓存中保持持久化实例的散装形式的数据

(2)持久化不同的数据需要不同的Cache策略,比如一些因素将影响Cache策略的选择:数据的读/写比例、数据表是否能被其他的应用程序所访问等。

(3)设置Hibernate二级缓存需要分两步:首先,确认使用什么数据并发策略。然后,配置缓存过期时间并设置Cache提供器。

6、get和load的区别

1.get是立即加载,load是延时加载

2.get会先查一级缓存,再查二级缓存,然后查数据库;load会先查一级缓存,如果没有找到,就创建代理对象,等需要的时候去查询二级缓存和数据库。(这里体现load的延迟加载的特性)

3.get如果没有找到会返回null,load如果没有找到会抛出异常

4.当我们使用session.load()方法来加载一个对象时,此时并不会发出sql语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的id值,只有当我们要使用这个对象,得到其他属性时,这个时候才会发出sql语句,从数据库中去查询我们的对象,相对于load的延迟加载方式,get就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们使不使用这个对象,此时都会发出sql语句去从数据库中查询出来。

7、如何进行Hibernate的优化

1.数据库设计调整

2.HQL优化

3.API的正确使用(如根据不同的业务类型选用不同的集合及查询API)

4.主配置参数(日志,查询缓存,fetch_size,batch_size等)

5.映射文件优化(ID生成策略,二级缓存,延迟加载,关联优化)

6.一级缓存的管理

7.针对二级缓存,还有许多特有的策略

8.事务控制策略

2.mybatis

1、概念

mybatis 是一个持久层框架,是 apache 下的开源项目,前身是 itbatis, 是一个不完全(半自动)的 ORM 框架,mybatis 提供输入和输出的映射,需要程序员自己写 sql 语句,mybatis 重点对 sql 语句的灵活操作

适合用于:需求变化频繁, 数据模型不固定的项目,例如:互联网项目。

2、为什么mapper接口没有实现类,却能被正常调用?

Mybatis在Mapper接口上使用到了动态代理

3、Mybatis的优缺点

优点

小巧,学习成本低,会写sql上手就很快接近JDBC,基本上配置好了,大部分的工作量就专注在sql上方便维护管理,sql不需要在Java代码中找,sql可以分离出来,重用。接近jdbc灵活,支持动态sql支持对象和数据库orm字段关系映射

缺点

由于工作量在sql上,需要sql的熟练度高移植性差,sql语法依赖数据库,不同数据库的切换会因语法差异,会报错

4、mybatis的核心组件

sqlsession(会话):是一个既可以发送sql去执行返回结果,也可以获取mapper接口sqlsessionfactory(工厂接口):依靠工厂来生成sqlsessionsqlsessionfactorybuilder(构造器):根据配置信息或代码来生成sqlsessionfactorysqlmapper:它是 一个新设计的组件,是由一个Java接口和xml文件(或注解)构成的,需要给出对象的sql和映射规则,负责sql去执行,并返回结果。

5、mybatis的缓存

1、缓存的优缺点

优点:

只是查询才有缓存(增删改没有缓存的),可以增块访问的速度sqlsession级缓存-(一级缓存)默认开启的所有的操作是公用同一个SQLsession对象并且执行的是同一条SQL语句的时候才会走缓存

缺点:

可能存在数据的脏读执行修改、删除、添加默认的把缓存中数据全部清空问题不同的用户访问的时候创建了不同的sqlsession对象,这个时候我们缓存的数据没有办法实现共享

2、一级缓存与二级缓存

一级缓存

也称为本地缓存,用于保存用户在一次会话过程中查询的结果,用户一次会话中只能使用一个sqlSession,一级缓存是自动开启的,不允许关闭。

一级缓存图

二级缓存

也称为全局缓存,是mapper级别的缓存,是针对一个表的查结果的存储,可以共享给所有针对这张表的查询的用户。也就是说对于mapper级别的缓存不同的sqlsession是可以共享的。

查询数据顺序二级->一级>数据库一>把数据保存到一级,当sqlsession关闭或者提交的时候,把数据刷入到二级缓存中

3、一级缓存失效的原因

同一个用户使用不同的SqlSession对象导致无法看到一级缓存工作。在一个SqlSession中使用条件查询不同一级缓存也会失效。在一个SqlSession使用相同条件,但是,此时在查询之间进行数据修改操作会导致一级缓存失效。在一个SqlSession使用相同查询条件此时手动刷新缓存时导致一级缓存失败。

4、注意

MyBatis一级缓存的生命周期和SqlSession一致MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据。mybatis和spring整合后进行mapper代理开发,不支持一级缓存。

5、二级缓存配置

1、需要在MyBatis核心配置文件,通过settings标签开发二级缓存<setting name="cacheEnabled" value="true"/>

2、在对应的Mapper文件中添加cache标签

3、cache标签属性

①type:cache使用的类型,默认是PerpetualCache,这在一级缓存中提到过。

②eviction: 定义回收的策略,常见的有FIFO,LRU。

③flushInterval: 配置一定时间自动刷新缓存,单位是毫秒。

④size: 最多缓存对象的个数。

⑤readOnly: 是否只读,若配置可读写,则需要对应的实体类能够序列化。

⑥blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。

4、cache-ref代表引用别的命名空间的Cache配置,两个命名空间的操作使用的是同一个Cache。

6、Mybatis的编程步骤

1、创建SqlSessionFactory

2、通过SqlSessionFactory创建SqlSession

3、通过SqlSession执行数据库操作

4、调用session.commit()提交事务

5、调用session.close()关闭会话

7、Mybatis的缓存机制

MyBatis提供了一级缓存和二级缓存

一级缓存:也称为本地缓存,用于保存用户在一次会话过程中查询的结果,用户一次会话中只能使用一个sqlSession,一级缓存是自动开启的,不允许关闭。二级缓存:也称为全局缓存,是mapper级别的缓存,是针对一个表的查结果的存储,可以共享给所有针对这张表的查询的用户。也就是说对于mapper级别的缓存不同的sqlsession是可以共享的。

8、Mybatis的分页插件PageHelper

1、使用步骤

1.导入依赖

<dependency>    <groupId>com.github.pagehelper</groupId>    <artifactId>pagehelper</artifactId>    <version>5.1.10</version></dependency>

2.设置mybatis-config.xml

<?xml version="1.0" encoding="utf-8" ?><!DOCTYPE configuration    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"    ";><configuration>  <plugins>    <plugin interceptor="com.github.pagehelper.PageInterceptor">      <!-- 该参数默认为false -->      <!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 -->      <!-- 和startPage中的pageNum效果一样-->      <property name="offsetAsPageNum" value="true"/>      <!-- 该参数默认为false -->      <!-- 设置为true时,使用RowBounds分页会进行count查询 -->      <property name="rowBoundsWithCount" value="true"/>      <!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 -->      <!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)-->      <property name="pageSizeZero" value="true"/>      <!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 -->      <!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->      <!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->      <property name="reasonable" value="true"/>      <!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 -->      <!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 -->      <!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,orderBy,不配置映射的用默认值 -->      <!-- 不理解该含义的前提下,不要随便复制该配置 -->      <property name="params" value="pageNum=start;pageSize=limit;"/>      <!-- 支持通过Mapper接口参数来传递分页参数 -->      <property name="supportMethodsArguments" value="true"/>      <!-- always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page -->      <property name="returnPageInfo" value="check"/>    </plugin>  </plugins></configuration>

3.给两个参数(pageNum,pageSize)

public Object getUsers(int pageNum, int pageSize) {    PageHelper.startPage(pageNum, pageSize);    // 不带分页的查询    List<UserEntity> list = userMapper.selectAllWithPage(null);    // 可以将结果转换为 Page , 然后获取 count 和其他结果值    com.github.pagehelper.Page listWithPage = (com.github.pagehelper.Page) list;    System.out.println("listCnt:" + listWithPage.getTotal());    return list;}

9、Mybatis中#和$的区别

#{}${}是两种不同的参数占位符使用方式。

1、#{}占位符:#{}预编译的占位符,它会将传入的参数转义并作为预编译语句的参数传递给数据库。使用#{}可以防止SQL注入攻击,因为它会将传入的参数进行安全处理,比如对特殊字符进行转义

2、${}占位符:${}字符串替换的占位符,它会将传入的参数直接替换到SQL语句中,产生最终的SQL语句。使用${}不会对传入的参数进行转义或预编译处理,因此需要谨慎使用,否则可能导致SQL注入问题。

与SQL注入相关的是使用#{}占位符,因为它会对参数进行转义和预编译处理,可以防止恶意用户通过参数注入恶意的SQL代码。而${}占位符不会对参数进行处理,所以存在SQL注入的风险

性能方面,#{}占位符可以提高应用的安全性,但会增加一定的性能开销,因为在执行过程中需要进行参数的转义和预编译处理。相比之下,${}占位符在替换字符串时没有这些额外的处理,可能性能上略优于#{}。

在项目中,因为考虑到安全性和防止SQL注入的风险,应该倾向于使用#{}占位符来传递参数。但在某些特定的场景下,如果确保传入的参数经过了合适的验证和处理,并且无安全风险,可以使用${}占位符来获得更好的性能。使用哪种占位符需要根据实际情况进行权衡。

10、JDBC编程有哪些不足之处,Mybatis是如何解决这些问题的?

1.数据库连接创建、释放频繁造成系统资源从而影响系统性能,如果使用数据库连接池可解决此问题。

解决:在SqlMapConfig.xml中配置数据库连接池,使用连接池管理数据库连接。

2.sql语句在代码中造成代码不易维护,实际应用中sql变化可能较大,sql变化需要改变java代码。

解决:在sql语句配置在xxxmapper.xml文件中与java代码分离。

3.向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

解决:Mybatis自动将java对象映射至sql语句。

4.对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。

解决:Mybatis自动将sql执行结果映射至java对象。

11、使用MyBatis的mapper接口调用时有哪些要求?

1.Mapper接口方法名和mapper.xml中定义的每个sql的id相同。

2.Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同。

3.Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。

4.Mapper.xml文件中的namespace即是mapper接口的类路径。

12、MyBatis和MyBatisPlus的关系

(1)MyBatis是一种持久层框架,用来连接数据库并对其进行增删改查操作的开源框架,底层就是一个JDBC封装的组件,访问数据库的sql语句存放在mapper(或Dao)包下的xml配置文件中。

(2)MyBatisPlus是MyBatis的一个增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。MyBatis-Plus已经封装好了一些CRUD方法,因此不需要再写xml了,仅仅通过少量配置即可实现单表大部分的CRUD操作,使用时直接调用这些方法就行。

13、Mybatis-plus的优缺点

MyBatis-Plus(简称MP)是一个基于MyBatis的增强工具,旨在简化与MyBatis的整合过程并提供更多方便的功能。下面是MyBatis-Plus的一些优缺点:

优点:

1、简化CRUD操作:MyBatis-Plus提供了丰富的CRUD操作方法,可以快速和方便地进行数据库操作,减少了手动编写SQL语句的工作量。

2、自动生成SQL语句:MyBatis-Plus具有自动生成SQL语句的功能,可以根据实体类自动生成对应的表和字段,简化了数据库的设计和维护工作。

3、内置分页插件:MyBatis-Plus内置了分页插件,可以方便地进行分页查询操作,极大地提高了查询数据的效率。

4、支持代码生成:MyBatis-Plus提供了代码生成器,可以根据数据库表自动生成对应的实体类、Mapper接口和XML文件,提高了开发效率。

5、支持Lambda表达式:MyBatis-Plus支持Lambda表达式,可以通过Lambda方式进行条件查询,使代码更加简洁易读。

缺点:

1、学习成本:使用MyBatis-Plus需要学习其特有的API和使用方式,对于初次接触的开发者可能需要花费一些时间来适应和学习。

2、依赖版本限制:MyBatis-Plus对于MyBatis的版本有一定的依赖性,需要根据不同的MyBatis版本选择相应的MyBatis-Plus版本,可能会对项目的升级和维护带来一定的影响。

3、灵活性有限:MyBatis-Plus的设计目标是简化和增强MyBatis,因此在某些特定的需求下可能会有一些局限性,无法满足个性化的定制需求。

14.mybatis常用标签

1、<select>:用于执行查询操作,从数据库中获取数据。

2、<insert>:用于执行插入操作,向数据库中插入数据。

3、<update>:用于执行更新操作,修改数据库中的数据。

4、<delete>:用于执行删除操作,删除数据库中的数据。

5、<if>:在SQL语句中用于条件判断,根据条件动态生成不同的SQL片段。

6、<choose><when><otherwise>:类似于Java中的switch语句,用于按条件选择不同分支。

7、<trim><where><set><foreach>:用于在SQL语句中动态生成条件或者循环处理相关的代码。

8、<resultMap>:用于定义结果集与Java对象之间的映射关系。

9、<result>:定义如何将查询结果中的映射到Java对象的属性。

10、<association><collection>:用于处理复杂类型(如嵌套关系、一对多关系等)的映射。

11、<sql>:定义可重用的SQL片段,在其他地方通过引用进行复用。

12、<include>:引用外部的SQL片段,实现SQL代码的复用。

15.mybatis实现批量删除

一、第一种方式:将任意多个 id 拼接成字符串,以参数形式传递进去,通过 in 函数 的方式来删除

①首先定义接口类

/*** 批量删除 * @param ids* @return* *///通过id所组成的字符串实现批量删除public void deleteId(@Param("ids") String ids);

②在实现类中配置Mapper.xml

<delete id="deleteId">	delete from accounts where id in (${ids})</delete>

注意: #{}中字符串类型会使用单引号,则无需。这里只能使用{}方式,不能使用#{}***

二、第二种方式:使用 foreach 标签来进行删除

①首先定义接口类

//    通过list集合实现批量删除brpublic void deleteByIds(@Param("ids") List<Integer> ids);

②在实现类中配置Mapper.xml

 <!--    public void deleteByIds(@Param("ids") List<Integer> ids);--><select id="deleteByIds" parameterType="Integer">    delete from accounts where id in    <foreach collection="ids" open="(" close=")" separator="," item="id">        #{id}    </foreach></select>

16.mybatis 是否支持延迟加载?延迟加载的原理是什么?

1、mybatis 是否支持延迟加载?

延迟加载其实就是讲数据加载时机推迟,比如推迟嵌套查询的时机。

延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,一定程度上提高了效率。

mybatis仅支持关联对象association和关联集合对象collection的延迟加载,association是一对一,collection是一对多查询,在mybatis配置文件中可以配置lazyloadingEnable=true/false。

2、延迟加载的原理是什么?

使用CGLIB为目标对象建立代理对象,当调用目标对象的方法时进入拦截器方法。

比如调用a.getB().getName(),拦截器方法invoke()发现a.getB()为null,会单独发送事先准备好的查询关联B对象的sql语句,把B查询出来然后调用a.setB(b),也是a的对象的属性b就有值了,然后调用getName(),这就是延迟加载的原理。

2.Spring

1.对Spring的理解

什么是pring?

Spring是个java企业级应用的开源开发框架,Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用。Spring框架目标是简化Java企业级应用开发,并通过POJO为基础的编程模型促进良好的编程习惯

对Spring的理解

1、Spirng是个开源框架,主要是为简化企业级应用开发而生的。可以实现EJB可以实现的功能,Spring是一个IOC和AOP容器框架

控制反转(IOC):Spring容器使用了工厂模式为我们创建了所需要的对象,我们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可,这就是控制反转的思想。

依赖注入(DI):Spring使用Java Bean对象的Set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本思想。

面向切面编程(AOP):在面向对象编程(OOP)思想中,我们将事务纵向抽象成一个个的对象,而在面向切面编程中,我们将一个个对象某些类似的方面横向抽象成一个切面,对这个切面进行一个如权限验证,事务管理,记录日志等公用操作处理的过程就是面向切面编程的思想

2、在Spring中,所有管理的都是JavaBean对象,而BeanFactoy和ApplicationContext就是Spring框架的那个IOC容器,现在一般使用ApplicationContext,其不但包括了BeanFactory的作用,同时还进行了更多的扩展。

2.spring组成

spring组成图

3.spring的常用模块

Spring常用模块图

4.spring 的 aop,ioc

面向切面编程(AOP),在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事务管理,记录日志等公用操作处理的过程就是面向切面编程的思想。AOP 底层是动态代理,如果是接口采用JDK 动态代理,如果是类采用 CGLIB 方式实现动态代理。

控制反转(IOC),传统的 java 开发模式中,当需要一个对象时,我们会自己使用 new或者getInstance 等直接或者间接调用构造方法创建一个对象。而在spring 开发模式中,spring 容器使用了工厂模式为我们创建了所需要的对象,不需要我们自己创建了,直接调用spring 提供的对象就可以了,这是控制反转的思想

5.Spring的事务

1、概念

Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring 是无法提供事务功能的。

2、Spring事务管理

Spring 事务管理有两种方式:编程式事务管理、声明式事务管理

Spring 事务管理为我们提供了三个高层抽象的接口,分别是 TransactionProxyFactoryBean,TransactionDefinition,TransactionStatus

编程式事务管理通过 TransactionTemplate 手动管理事务,在实际应用中很少使用,我们来重点学习声明式事务管理

声明式事务管理有三种实现方式:基于 TransactionProxyFactoryBean 的方式、基于 AspectJ 的 XML 方式、基于注解的方式

3、声明事务管理用到哪些原理

声明式事务管理:基于AOP,将具体业务逻辑与事务处理解耦,声明式事务属于无侵入式,不会影响业务逻辑的实现,声明式事务实现方式主要有两种,一种为通过使用Spring的定义事务通知与AOP相关配置,另为一种通过@Transactional实现事务管理实现注:声明式事务管理使业务代码逻辑不受污染,因此在实际使用中声明式事务用的比较多声明式事务有两种配置:基于xml配置基于@Transactional注解方式

4、与分布式事务如何区分

其实在Spring中里面并没有提供事务,它只是提供了对数据库事务的一个管理的封装,可以通过声明式事务的配置使得开发人员可以从一些复杂的事务处理里面去脱离出来,不需要关心连接的获取,连接的关闭,事务的提交,回滚这样的一些操作,可以更加聚焦在业务的开发层面,所以Spring的事务本质上是数据库层面的一个事。

而这种事务管理,主要针对单个数据库里面的多个数据表的操作,它去满足一个事务的ACID特性,而分布式事务是解决多个数据库事务操作的一个管理一致性问题,传统的数据库事务不支持跨库的事务操作,所以需要引入分布式事务的解决方案,而Spring里面并没有提供分布式事务场景的支持,所以Spring里面的事务和分布式事务在使用上并没有直接的关联关系,但是我们可以使用一些主流的分布式事务解决框架,比如Seata集成到Spring生态里面去解决分布式事务的一个问题。

6、Spring框架的设计目标,设计理论和核心是什么

设计目标:Spring为开发者提供一个一站式轻量级应用开发平台;

设计理念:在JavaEE开发中,支持pojo和JavaBean开发方式,使应用面向接口开发,充分支持OOP(面向对象),设计方法;Spring通过IOC容器实现对象耦合关系的管理, 并实现依赖反转,将对象之间的依赖关系交给ioc容器,实现解耦;

核心IOC容器和AOP模块。通过ioc容器管理pojo对象以及他们之间的耦合关系;通过aop以动态非侵入的方式增强服务,ioc让相互协作的组件保持松散的耦合,而aop编程允许你把遍布与应用各层的功能分离出来形成可重用的功能组件

7、Spring框架的优缺点

优点

方便解耦,简化开发Spring就是一个大工厂,可以将所有的创建和依赖关系的维护,交给Spring管理AOP编程的支持Spring提供面向切面编程,可以方便的实现对程序进行权限拦截,运行监控等功能声明式事务的支持只需要通过配置就可以完成对事务的管理,而无需手动编程方便程序的测试Spring对junit4的支持,可以通过注解的方式测试Spring编程方便集成各种优秀框架Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的直接支持(如:struct2,mybatis,hibernate等)降低JavaEE API的使用难度Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低

缺点

Spring明明是一个很轻量级的框架,却给人感觉大而全Spring依赖反射,反射影响性能使用门槛高,入门时间长

8、使用Spring的好处(优点升级版)

1、轻量:Spring是轻量的,基本的版本大约是2MB;

2、控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们;

3、面向切面编程(AOP):Spring支持面向切面编程,并且把应用业务逻辑和系统服务分开;

4、容器:Spring包含并管理应用对象的生命周期和配置;

5、MVC框架:Spring的WEB框架是一个精心设计的框架,是WEB框架的一个很好的替代品;

6、事务管理:Spring提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA);

7、异常处理:Spring提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked异常。

9、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 会自动被通知

10、Bean

1、简介

在Spring中,构成应用程序主干并由SpringIOC容器管理的对象称为beans,bean是由SpringIOC容器实例化、组装和管理的对象

1、bean是对象,数量不限,即可以为多个

2、bean是由SpringIOC容器管理

3、应用程序由一个个bean构建

Spring帮助我们通过两种方式管理bean,一种是注册bean,另一种是装配Bean

2、Bean注入的方式

Set注入构造器注入静态工厂的方法注入实例工厂的方法注入

3、Bean的作用域范围

类别

说明

singleton

在SpringIOC容器中仅存在一个Bean实例,Bean以单例方式存在,默认值

prototype

每次从容器中调用Bean时,都返回一个新的实例,及每次调用getBean()时,相当于执行new XxxBean()

request

HTTP请求都会创建一个新到的Bean,该作用域仅适用于WebApplicationContext环境

session

同一个HTTP Session共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext环境

globalSession

一般用域Porlet应用环境,该作用域仅适用于WebApplicationContext环境

4、注册Bean的注解

1、@Component:用于将一个类标识为 Spring 容器中的组件,通常用于自动扫描和装配 bean。

2、@Controller:用于标识一个类为 Spring MVC 的控制器,处理 HTTP 请求和响应。

3、@Service:用于标识一个类为业务逻辑层的组件,通常作为服务层的实现类。

4、@Repository:用于标识一个类为数据访问层的组件,通常作为 DAO 层的实现类。

5、@Configration:用于标识一个类为配置类。

5、Spring(Bean)的生命周期

Spring(Bean)的生命周期图

(创建+赋值+初始化+销毁

1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean

2)利用依赖注入完成 Bean 中所有属性值的配置注入

3)如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值

4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用

5)如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用

6)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的

7)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法

8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。

9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了

10)如果在 <bean> 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 <bean> 中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean

11)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁

11、Spring设计模式

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

2、单例模式:Bean默认为单例模式

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

4、模板方法:用来解决代码重复问题。比如:RestTemplate, JmsTemplate, JpaTemplate;

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

6、前端控制器模式:Spring提供了DispatherServlet来对请求进行分发;

7、依赖注入模式:贯穿于Beanfactory/ApplicationContext接口的核心理念

12、BeanFactory和FactoryBean的区别

BeanFactory:

BeanFactory是Spring的核心接口之一,用于管理和获取应用程序中的Bean对象它是一个工厂模式的实现,负责创建、配置和管理Bean实例BeanFactory充当了IoC容器的角色负责创建和维护Bean对象的生命周期,并通过依赖注入解决对象之间的关系

FactoryBean:

FactoryBean是另一个Spring接口,它是BeanFactory的一个扩展点FactoryBean用于创建特定类型的对象,这些类型的对象可以是任意复杂的Java对象。FactoryBean允许开发人员在Spring容器中配置自定义的Bean创建逻辑,从而提供更灵活、可扩展的对象创建方式FactoryBean本身就是一个Bean对象,因此它也可以受到Spring的管理和生命周期控制2、springCore

1.Spring Core核心模块

核心模块最重要的就是提供了一个对象容器,更加便于整合第三方开源框架。

先要了解两个重要的概念:

1、IOC Inverse Of Controll 控制反转

​ 主要针对的是对象的创建和管理方式。传统的对象的创建方式,是以new关键字的方式在程序中硬编码创建出来的。所谓“反转”指的是,对象的创建方式不再由程序员能过编码创建,而是能通过spring的对象容器来创建。也称为“容器托管”。例如:Servlet就是通过web容器托管的对象,通过生命周期管理servlet实例的。

2、DI Dependency Injection 依赖注入

​ 依赖: 应用程序中的对象与对象、组件 与组件之间的关联关系

​ 依赖注入:由容器对依赖关系进行初始化的赋值

与IOC的关系:DI是实现IOC的一种方法

2.Spring IOC

1、IOC概述

IOC全称为Inversion Of Control,也就是控制反转,它的核心思想是把对象的管理权限交给了容器,应用程序如果需要使用某个对象的实例,那么直接从IOC容器里面去获取就可以了。

2、优缺点

优点:组件之间的解耦、提高了程序可维护性,灵活性

缺点:创建对象复杂、有一定的学习成本;利用反射创建对象,效率上有损

3、依赖注入的方式

setter注入构造器注入接口注入注解注入

4、Spring提供的四种自动装配类型

Spring四种自动装配类型图

5、Spring管理Bean的作用域范围

singleton 单例 (默认)prototype 原型 (多例)request websession webglobal session web3.springAop

1、概念

AOP Aspect Oriented Programming 面向切面编程,其实就是“拦截器”。在不修改源代码的情况下,可以实现功能的增强

Spring AOP 的面向切面编程,是面向对象编程的一种补充,用于处理系统中分布的各个模块的横切关注点,比如说事务管理、日志、缓存等。它是使用动态代理实现的,在内存中临时为方法生成一个 AOP 对象,这个对象包含目标对象的所有方法,在特定的切点做了增强处理,并回调原来的方法。

2、AOP编程的实现方式

实现接口的方式(spring低版本),不建议用schema的方式(xml配置),schema就是xml中的元素的类型定义注解配置方式

3、JavaEE应用中,“拦截”的技术

原生平台, Filter 过滤器,主要拦截的目标是一切可访问的资源。包括:页面、js、css、images、jsp/servlet等等。mvc框架(struts2和springmvc),提供了拦截器,拦截的目标是控制器。spring框架,AOP编程就是拦截器,拦截的目标是业务层的业务方法

4、拦截的概念

拦截的本质就是对目标对象的功能的增强。使用了动态代理设计模式,对目标对象进行代理,代理目标对象的作用就是要增强目标对象的功能。

5、拦截的作用

解决共性问题,解耦合。如果OOP解决不了的共性问题,可以使用AOP来解决这种“通用性”的问题。AOP是OOP的补充作用。

6、AOP的术语

aspect 切面 对共性问题的抽象,拦截器类pointcut 切入点 被拦截的(业务)方法advice 通知,对某种功能的增强方式。功能增强方式:前置增强、后置增强、环绕增强、最终增强、异常增强。

7、应用场景

1、日志记录:通过AOP可以在方法执行前后插入日志记录的逻辑,方便跟踪和记录方法的执行情况,帮助排查问题和监控系统运行状态。

2、事务管理:AOP可以用于实现声明式事务管理,通过在方法执行前后进行事务的开启、提交或回滚,简化了代码中的事务处理逻辑。

3、安全性检查:AOP可以在方法执行前进行权限检查,确保只有具备相应权限的用户才能执行敏感操作,提高系统的安全性。

4、性能监控:AOP可以在方法执行前后进行性能监控,记录方法的执行时间、资源消耗等指标,帮助进行系统性能分析和优化。

5、异常处理:AOP可以捕获方法执行过程中的异常,并进行统一的处理,例如记录异常日志、发送告警等,提高系统的容错性和可维护性。

6、缓存管理:AOP可以在方法执行前后进行缓存的读取和更新,提高系统的响应速度和性能。

8、Spring中有哪些不同的通知类型

1、前置通知(Before Advice): 在连接点之前执行的Advice,不过除非它抛出异常,否则没有能力中断执行流。使用 @Before 注解使用这个Advice。

2、返回之后通知(After Retuning Advice): 在连接点正常结束之后执行的Advice。例如,如果一个方法没有抛出异常正常返回。通过 @AfterReturning 关注使用它。

3、抛出(异常)后执行通知(After Throwing Advice): 如果一个方法通过抛出异常来退出的话,这个Advice就会被执行。通用 @AfterThrowing 注解来使用。

4、后置通知(After Advice): 无论连接点是通过什么方式退出的(正常返回或者抛出异常)都会执行在结束后执行这些Advice。通过 @After 注解使用。

5、围绕通知(Around Advice): 围绕连接点执行的Advice,就你一个方法调用。这是最强大的Advice。通过 @Around 注解使用。

9、SpringAOP的实现原理

Spring AOP 的动态代理主要有两种方式实现,JDK 动态代理和 cglib 动态代理。JDK 动态代理通过反射来接收被代理的类,但是被代理的类必须实现接口,核心是 InvocationHandler和 Proxy 类。cglib 动态代理的类一般是没有实现接口的类,cglib 是一个代码生成的类库,

可以在运行时动态生成某个类的子类,所以,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。

重点:JDK动态代理和CGLIB代理的区别

Spring的AOP是通过动态代理来实现的,动态代理主要有两种方式JDK动态代理和Cglib动态代理,这两种动态代理的使用和原理有些不同。

JDK 动态代理

1、Interface:对于 JDK 动态代理,目标类需要实现一个Interface。

2、InvocationHandler:InvocationHandler是一个接口,可以通过实现这个接口,定义横切逻辑,再通过反射机制(invoke)调用目标类的代码,在次过程,可能包装逻辑,对目标方法进行前置后置处理。

3、Proxy:Proxy利用InvocationHandler动态创建一个符合目标类实现的接口的实例,生成目标类的代理对象。

CgLib 动态代理

1、使用JDK创建代理有一大限制,它只能为接口创建代理实例,而CgLib 动态代理就没有这个限制。

2、CgLib 动态代理是使用字节码处理框架 ASM,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

3、CgLib 创建的动态代理对象性能比 JDK 创建的动态代理对象的性能高不少,但是 CGLib 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLib 合适,反之,使用 JDK 方式要更为合适一些。同时,由于 CGLib 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理。

4、Spring事务管理

1、分类

事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式两种

2、编程式事务管理和声明式事务管理区别

编程式事务指的是通过编码方式实现事务;(但不是都是通过编码的方式,也可通过拦截器完成)

声明式事务基于 AOP,将具体的逻辑与事务处理解耦。

3、声明式事务管理

在spring的框架中,使用aop编程来实现事务管理,对目标业务方法进行事务的增强。声明式事务管理是AOP在spring框架中的“特例”。声明式指的是无需硬编码,只需配置

主要思想是将事务管理作为一个“切面”代码单独编写,然后通过AOP技术将事务管理的“切面”代码植入到业务目标类中。

声明式事务管理分两种:

注解配置xml配置

4、事务传播途径(propagation):

REQUIRED 当前方法要事务环境,如果已经有事务就不创建,使用当前的事。如果没有事务就要创建。REQUIRES_NEW 当前方法要有独立的事务环境,如果已经有事务,也要创建新的事务环境。SUPPORTS 当前方法支持事务环境,如果已经有事务就不创建,支持当前事务,如果没有也不创建。MANDATORY 强制 如果当前存在事务,则加入事务。如果不存在事务,则抛出异常

上四者比较常用

事务传播途径

5、springMVC

1.MVC概念和模式理解

MVC框架是为了解决传统MVC模式(Jsp + Servlet + JavaBean)的一些问题而出现的框架。

传统MVC模式存在问题:

1.所有的Servlet和Servlet映射都要配置在web.xml中,如果项目太大,web.xml就太庞大,并且不能实现模块化管理。

2.Servlet的主要功能就是接受参数、调用逻辑、跳转页面,比如像其他字符编码、文件上传等功能也要写在Servlet中,不能让Servlet主要功能而需要做处理一下特例。

3、接受参数比较麻烦(String name = request.getParameter(“name”),User user=new User user.setName(name)),不能通过model接收,只能单个接收,接收完成后转换封装model.

4、跳转页面方式比较单一(forword,redirect),并且当我的页面名称发生改变时需要修改Servlet源代码.

MVC模式理解:

MVC (Model-Vew-Controler) 式是一种常见的软性架构模式,用于组织和管理应用程序的代码结构。它分为三个核心组件:模型(Model) 、视图 (View) 和控制器 (Controller) 。

模型(Model)是应用程序的数据层,负责处理数据的存情、检索和操作。它代表着应用程序的业务逻辑和状态,模型不关心展示给用户的方式,独立于界面的实现。

视图(View)是用户界面的表示层,负责展示数据给用户并接收用户的输入。它从模型中获取数据,并将其以合适的方式呈现给用户。视图通常是被动的,只用于显示数据,不处理业务逻辑。

控制器(Controler)是模型和视图之间的协调者,负责处理用户的输入并作出相应的反应,它接收来自视图的用户交互事件,更新模型的状态,并将更新后的数据传递给视图进行展示。控制器充当了模型和视图之间的桥梁。

MVC模式通过将应用程序的不同部分进行解耦和分离,使得每个部分都可以独立地开发、测试和维护。它提供了清晰的代码组织结构,使得不同组件的职责和功能更加明确,提高了可重用性和可扩展性。

总而言之,MVC模式通过将应用程序分解为模型、视图和控制器这三个核心组件,实现了数据、展示和用户交互的分离,使得软件开发更加灵活和可维护。

2.重要组件

基于MVC设计模式的,凡是MVC框架,重点要解决的是控制器的问题,一般来讲,提供两类的控制器。

中央控制器 springmvc提供了前端控制器(DispatcherServlet),由框架提供,一般用servlet来实现,仅有一个。action组件 springmvc提供的handler(处理器),由程序员实现,有n个。

3.springmvc的工作流程

springmvc的工作流程图

1.用户请求旅程的第一站是DispatcherServlet。

2.收到请求后,DispatcherServlet调用HandlerMapping, 获取对应Handler

3.如果有拦截器一并返回

4.拿到Handler后,找到HandlerAdapter,通过它来访问Handler,并执行处理器。

5.执行Handler的逻辑。

6.Handler会返回一个ModelAndView对象给DispatcherServlet。

7.将获得到的ModelAndView对象返回给DispatcherServlet。

8.请求ViewResolver解析视图,根据逻辑视图名解析成真正的View

9.返回View给DispatcherServlet

10.DispatcherServlet对View进行渲染视图

11.DispatcherServlet响应用户。

4.SpringMVC的核心组件

前端控制器(DispatcherServlet):主要负责捕获客户端(浏览器)的请求和调度各个组件,可降低不同组件之间耦合性,是整个SpringMVC的核心模块

本质上是一个Servlet,相当于一个中转站,所有的访问都会走到这个Servlet中,再根据配置进行中转到相应的Handler中进行处理,获取到数据和视图之后,再使用相应做出响应;

处理器映射器(Handlermapping):根据url查找后端控制器handler

本质上就是一段映射关系,将访问路径和相对应的handler存储为映射关系,在需要时供前端控制器查阅

DispatcherServlet是通过HandlerMapping将请求映射到不同的handler

处理器适配器(HandlerAdapter):根据地址调用方法,执行后端控制器(handler),拿到后端控制器返回的结果ModelAndView后将结果返回给前端控制器DispatcherServlet

本质上是一个适配器,可以根据要求找到对应的Handler来运行,前端控制器通过处理器映射器找到对应的Handler信息之后,将请求响应和对应的Handler信息交给处理器适配器处理,处理器适配器找到真正的Handler执行后,将结果即model和view返回给前端控制器

处理器适配器,Handler执行业务方法之前,需要进行一系列的操作包括表单数据的验证、数据类型的转换、将表单数据封装到pojo等,这一系列的操作,都是由handlerAdapter来完成,dispatcherServlet通过HandlerAdapter执行不同的Handler

后端控制器(处理器)(Handler):主要负责处理前端请求,完成业务逻辑,相当于Servlet或Action,生成ModelAndView对象返回给HandlerAdapter

视图解析器(ViewResolver):主要负责将从DispatcherServlet中拿到的ModelAndView对象进行解析,生成View对象返回给DispatcherServlet

本质上也是一种映射关系,可以将视图名称映射到真正的视图地址,前端控制器调用处理器适配器完成后得到model和view,将view信息传给视图解析器给得到真正的view

处理器拦截器(HandlerInterceptor):是一个接口,如果我们需要一些拦截处理,可以实现这个接口

处理器执行链(HandlerExecutionChin):包括两部分,handler和handlerInterceptor(系统会有一个默认的handlerInterceptor,如果需要额外的拦截处理,可以添加拦截器设置)

模型视图(ModelAndView):装载了模型视图和视图信息,作为Handler的处理结果,返回给DispatcherServlet

5.SpringMVC需要配置什么

静态资源映射拦截器全局配置全局异常文件预设键值对绑定到Model中预处理前台请求参数

6.例举动态代理的应用场景

AOP编程:为切点配置包含的类生成代理Bean实例;

@lazy:懒加载,被注解的bean不是不实例化,而是先创建一个代理bean注入;

@Configuration:配置类注解,生成的配置类bean实例是代理,执行@bean的方法之前,先判断单例池中是否已有该对象实例,确保@bean注解的对象单例;

@Async:动态生成实现异步调用的代理类

7.SpringMVC的注解

@RequestMapping:相当于为当前的方法绑定一个URL地址,可以与前端的请求相匹配。包括value和method属性@RequestParam:标注在方法参数之前,用于对传入的参数做一些限制,支持三个属性:value:默认属性,用于指定前端传入的参数名称defaultValue:当参数为非必传参数且前端没有传入参数时,指定一个默认值@RequestHeader:用于接收请求头中的所有信息,会封装到一个Map结构中去@RequestBody:用于接收请求体中的参数,并将其封装到对象中(json转为java对象,一般前后端分离时使用)@ResponseBody:用于将方法的返回值放入响应体(java对象转为json数组)@PathVariable:用户从url路径中获取指定参数,标注在参数前@PathVariable("要获取的参数名")@ControllerAdvice:标注在一个类上,表示该类是一个全局异常处理的类@ExceptionHandler(Exception.class):标注在异常处理类中的方法上,表示该方法可以处理的异常类型@Controller:用于标注控制层组件@Autowired:用于自动装配Bean

8.struct2和SpringMVC的区别

1、springmvc入口是一个Servlet前端控制器(DispatcherServlet),struct2入口是一个filiter过滤器(StructsPrepareAndExecuteFilter)

2、struct2通过action类中定义成员变量接收参数,(属性驱动和模型驱动),它只能使用多例模式管理action。springmvc通过controller方法中定义形参接收参数,springmvc可以使用单例模式管理controller

3、springmvc是基于方法开发的,注解开发中使用requestMapping将url和方法进行映射,如果根据url找到controller类的方法生成一个handler处理器对象(只包括一个method)

1、struct2是基于直接类开发的,每个请求过来创建一个action实例,实例对象中有若干个方法

2、开发中建议使用springmvc,spring更类似service业务方法

4、struct2采用值栈存储请求和相应数据,通过OGNL存储数据;springmvc通过参数绑定将request请求内容解析,并给方法形参赋值

5、struct2和springmvc的速度是相当的,由于struct2的漏洞较多,更多企业使用springmvc

6、springmvc验证支持JSR303,处理起来相对更加灵活方便,而struct2验证比较繁琐,感觉太烦乱

7、设计思想上,struct2更加符合OOP的编程思想,springmvc就比较严谨,在servlet上扩展

8、拦截器实现机制上,struct2有以自己的interceptor机制,springmvc用的是独立的aop方式,这样导致struct2的配置文件还是比springmvc大

9.如何解决get和post乱码问题

解决post请求乱码:

在web.xml里边配置一个CharacterEncodingFilter过滤器,设置为utf-8

解决get请求乱码:

1.修改tomcat配置文件添加编码与工程编码一致;

2.对参数重新编码String userName=new String(Request.getParameter("username").getBytes("ISO8859-1"),"UTF-8");

10.SpringMVC的优点

1、它是基于组件技术的,全部的应用对象,无论控制器和视图,还是业务对象之类的都是java组件,并且和Spring提供的其他基础结构紧密集成

2、不依赖于Servlet API(目标虽是如此,但是在实现的时候确实是依赖于Servlet的

3、可以任意使用各种视图技术,而不仅仅局限于JSP

4、支持各种请求资源的映射策略

5、它应是易于扩展的

11.声明bean的注解

我们一般使用@Autowired注解去自动装配bean,而想要把一个类标识为可以用@Autowired注解自动装配的bean,可以采用以下注解

@Component注解,通用的注解,可标注任意类为Spring组件,如果一个Bean不知道属于哪一层,可以使用@Component注解标注@Respository注解,对应的持久层,即Dao层,主要用于数据库相关操作@Service注解,对应服务层,即Service层,主要涉及一些复杂逻辑,需要用到Dao层(注入)@Controller注解,对应SpringMVC的控制层,即Controller层,主要用于接收用户请求并调用Service层的方法返回数据给前端页面

12.简述ModelAndView、String和void三种返回类型的作用

ModelAndView类型中可以添加Model数据,并指定视图String类型在返回值可以跳转视图,但不能携带数据void类型主要在异步请求中,使用它只返回数据,不会跳转视图

13.拦截器和过滤器的区别

拦截器是基于java的反射机制的,而过滤器是基于函数回调拦截器不依赖于servlet容器,而过滤器依赖于servlet容器拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用拦截器可以访问action上下文、值栈里的对象,而过滤器不能在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

14.为什么SpringMVC中的前端控制是单例,会有什么问题,解决方案是什么?

默认是单例模式

所以在多线程访问的时候有线程安全问题,不需要用同步,会影响性能的,

解决方案是在控制器里面不能写成员变量

为什么设计成单例模式?

(1)性能(不用每次请求都创建对象)

(2)不需要多例(不要在控制器类中定义成员变量)

15.SpringMVC获取参数的方式

通过 @RequestParam 注解获取请求参数通过 @PathVariable 注解获取 URL 路径参数通过 HttpServletRequest 以及 @RequestBody 注解获取请求体参数

16.过滤器链

1、CharacterEncodingFilter: 设置请求和响应的字符编码

2、HiddenHttpMethodFilter: 用于支持使用隐藏字段来传递HTTP方法。

3、FormContentFilter: 用于解析请求的内容以支持PUT和DELETE方法。

4、CorsFilter: 处理跨域资源共享

5、AuthenticationFilter: 用于身份验证

6、SecurityFilterChain: 处理安全相关的过滤器。

17.DDD模式

1.概念

DDD(Domain-Driven Design,领域驱动设计)是一种软件开发方法论,旨在帮助开发人员更好地理解和应对复杂的业务需求。DDD强调将业务领域作为软件开发的核心,并将其建模为一个独立的领域模型。

在DDD中,领域模型是对业务领域的抽象和建模,它包含了业务逻辑、规则和概念。领域模型是通过与领域专家密切合作来开发的,以确保模型与实际业务需求相匹配。

DDD模式提供了一些核心概念和技术,包括聚合根(Aggregate Root)、实体(Entity)、值对象(Value Object)、领域事件(Domain Event)等。这些概念和技术帮助开发人员更好地组织和管理领域模型,使其具有高内聚性和低耦合性。

DDD模式还提供了一些战术模式,例如仓储(Repository)、工厂(Factory)、服务(Service)等,用于实现领域模型的持久化、创建和操作。

通过使用DDD模式,开发人员可以更好地理解和应对复杂的业务需求,减少开发过程中的误解和沟通成本,提高软件系统的可维护性和可扩展性。

2.MVC模式 VS DDD模式

MVC模式图

MVC模式存在的问题

1.新需求的开发会越来越难。

2.代码维护越来越难,一个类代码太多,这怎么看对吧,就是一堆屎山。

3.技术创新越来越难,代码没时间重构,越拖越烂。

4.测试越来越难,没办法单元测试,一个小需求又要回归测试,太累。

使用DDD的意义

单体架构局部业务膨胀可以拆分成微服务,微服务架构局部业务膨胀,又拆成什么呢?DDD就是为了解决这些问题的存在,从一个软件系统的长期价值来看,就需要用DDD,虽然一开始从设计到开发需要成本,但是随着时间的增长,N年以后代码依然很整洁,利于扩展和维护,高度自治,高度内聚,边界领域划分的很清楚。当然了,针对于简单的系统用DDD反而用复杂了,杀鸡焉用宰牛刀!

MVC的开发模式:是数据驱动,自低向上的思想,关注数据。

DDD的开发模式:是领域驱动,自顶向下,关注业务活动。

3.总结

DDD 分层架构中的要素其实和三层架构类似,只是在 DDD 分层架构中,这些要素被重新归类,重新划分了层,确定了层与层之间的交互规则和职责边界。

MVC是一个短暂的快乐但不足以支撑漫长的生活,DDD是一个不要短暂的温存而是一世的陪伴,如果是你来抉择你会选择哪一个?

MVC模式与DDD模式架构图

6、什么是Java Config?Spring Java Config是Spring社区的产品,它提供了配置Spring IOC容器的纯Java方法它有助于避免使用XML配置使用Java Config的优点在于:面向对象的配置由于配置被定义为Java Config中的类,因此用户可以充分利用Java中的面向对象功能,一个配置类可以继承另一个,重写它的@Bean方法等减少或消除XML配置基于依赖注入原则的外化配置的好处已被证明,但是,许多开发人员不希望在XML和Java之间来回切换。JavaConfig为开发人员提供了一种纯Java方法来配置与XML配置概念相似的Spring容器,从技术角度来讲,只使用JavaConfig配置类来配置容器是可行的,但实际上很多人认为将JavaConfig与XML混合匹配是理想的类型安全和重构友好JavaConfig提供了一种类型安全的方法来配置Spring容器,由于Java5.0对泛型的支持,现在可以按类型而不是按名称检索bean,不需要任何强制转换或基于字符串的查找7、Activiti工作流框架

1.概念

工作流:多任务人协同完成的一个复杂的工作流,例如,OA系统使用最多

工作流框架:处理复杂业务流的业务框架,开源使用最多的就是Activiti

2.特点

1、把复杂的业务流进行图形化处理

2、图形化处理业务部署到数据库中(数据库化)

3、流程数据库,共有23张表

4、提供了一套API,就是业务对象(service),框架本身是一个半成品的系统

5、持久层的实现就是mybatis

6、所以,activiti是一个业务框架(系统)

3.常用业务

部署流程定义启动流程实例查找待办事务流程结束 (推进查看流程定义图判断流程实例是否结束删除流程定义

4.Activiti中的API允许执行Activiti流程引擎之外的方式渲染任务表单(外置表单)怎么去操作?

所有需要渲染的表单属性进行装配的服务方法有两种:

StartFormData FormService.getStartFormData(String processDefinitionId)

TaskFormdata FormService.getTaskFormData(String taskId

表单属性提交的两种方式:

ProcessInstance FormService.submitStartFormData(String processDefinitionId, Map<String,String> properties)

void FormService.submitStartFormData(String taskId, Map<String,String> properties)

可以将任何表单模版资源放进要部署的业务文档之中(如果想要按照流程的版本进行存储).将会在部署中作为一种可用的资源

获取部署表单模版的方式有两种:

String ProcessDefinition.getDeploymentId()

InputStream RepositoryService.getResourceAsStream(String deploymentId, String resourceName

4.Shiro安全框架

Shiro安全框架图

1.主要模块

Subject 受验证的主体(应用程序,某个用户)Security Manager 安全管理器 不是直接做认证和授权 Authenticator 认证器 Authorizer 授权器Session Manager 会话管理器Session Dao 管理Session中的数据Cache Manager 管理缓存数据Cryptography 跟密码加密有关,MD5Realm 领域,实现认证和授权的业务逻辑

2.执行流程

配置Sercurity Manager环境Subject.login()提交认证SecurityManager.login()执行认证Authenticator执行认证Realm根据身份获取验证信息

3.常用的安全框架

1.apache shiro

较轻量级,入门简单,不依赖与spring,传统ssm的项目使用较多

2.spring security

较复杂,入门较难,属于spring框架中的模块,多用于springboot+springcloud分布式前后端分离应用中

4.Shiro认证过程

①. 应用程序代码调用 Subject.login 方法,传递创建好的包含终端用户的 Principals(身份)和 Credentials(凭证)的 AuthenticationToken 实例

②. Subject 实例委托应用程序的 SecurityManager 通过调用securityManager.login(token) 开始真正的验证。

Subject 实例(通常为 DelegatingSubject或它的子类)

③. SubjectManager 接收 token,调用内部的 Authenticator 实例调用 authenticator.authenticate(token).Authenticator 通常是一个 ModularRealmAuthenticator 实例, 支持在身份验证中协调一个或多个Realm 实例

④. 如果应用程序中配置了一个以上的 Realm, ModularRealmAuthenticator 实例将利用配置好的AuthenticationStrategy 来启动 Multi-Realm 认证尝试。在Realms 被身份验证调用之前、调用期间、调用之后,AuthenticationStrategy 被调用使其能够对每个Realm 的结果作出反应。(AuthenticationStrategy都会被调用,对每个Realm 的结果作出反应)

⑤. 每个配置的 Realm 用来帮助看它是否支持提交的 AuthenticationToken. 如果支持, 那么支持 Realm 的 getAuthenticationInfo 方法将会伴随着提交的 token 被调用. getAuthenticationInfo 方法有效地代表一个特定 Realm 的单一的身份验证尝试。

5.Shiro授权过程

①. 应用程序或框架代码调用任何 Subject 的hasRole, checkRole, isPermitted,或者checkPermission方法的变体, 传递任何所需的权限

②. Subject 的实例 调用securityManager 的对应的方法.

Subject 实例(通常为 DelegatingSubject或它的子类)

③. SecurityManager 调用 org.apache.shiro.authz.Authorizer 接口的对应方法.默认情况下,authorizer 实例是一个 ModularRealmAuthorizer 实例, 它支持协调任何授权操作过程中的一个或多个Realm 实例

④. 每个配置好的 Realm 被检查是否实现了相同的 Authorizer 接口. 如果是, Realm 各自的 hasRole, checkRole,isPermitted,或 checkPermission 方法将被调用。

6.Shiro和Spring Security的区别

①导入和使用的范围:Shiro 是一个独立的库,并且可以用于任何 Java 应用程序;而 Spring Security 是 Spring 生态的一部分,需要导入与 Spring 框架相同的依赖。如果您的应用程序已经使用了 Spring 框架,可以考虑使用 Spring Security;如果您需要集成 Spring 之外的应用程序,可以选择使用 Shiro。

②开发体验:Shiro 相对来说比 Spring Security 更简单,而且可以更轻松地实现自定义认证和授权需求。Spring Security 基于标准的 Spring 集成方式,使其配置更加灵活和可扩展,但也会增加一些学习成本。

③安全特性:Shiro 支持更多的安全特性,包括单点登录(SSO)、OAuth 等;而 Spring Security 提供了更全面的安全性和比较高的安全级别,例如 CSRF 保护、安全头和 CSRF 攻击防范等。

④社区支持:由于 Spring Security 是 Spring 生态的一部分,拥有更大的社区支持和生态系统;而 Shiro 的生态系统相对来说不那么成熟。

5.SpringBoot

1.对SpringBoot的认识

1.快速开发spring应用的框架

2.内嵌tomcat和jetty容器,不需要单独安装容器,jar包直接发布一个web应用

3.简化maven配置,parent这种方式,一站式引入需要的各种依赖

4.基于注解的零配置思想

5.和各种流行框架,springwebmvc,mybatis,springcloud无缝整合

2.自动装配的原理

1、在Spring Boot应用程序的启动时,Spring Boot加载了classpath下的META-INF/spring.factories,并加载文件中列出的所有自动配置类的定义。

2、根据条件判断,Spring Boot会选择并初始化需要的所有自动配置类。

3、通过可以自动发现的机制,Spring Boot会自动注入所有已知的服务或引入的模块,如Web模块或持久化模块。

4、Spring Boot会使用懒加载机制,只在需要使用的时候才去调用启动自动装配的逻辑。

5、Spring Boot自动装配使用了很多Spring中的高级技术,如基于Java类注释的条件配置、自动装配Bean的生命周期管理等,来保证每个Bean都得到正确的初始化和管理。

3.运行原理

springboot是通过main方法下的SpringApplication.run方法启动的,启动的时候他会调用refshContext方法,先刷新容器,然后根据解析注解或者解析配置文件的形式注册bean,而它是通过启动类的SpringBootApplication注解进行开始解析的,他会根据EnableAutoConfiguration开启自动化配置,里面有个核心方法ImportSelect选择性的导入,根据loadFanctoryNames根据classpash路径以MATA-INF/spring.factorces下面以xxxEnableAutoConfiguration开头的key去加载里面所有对应的自动化配置,他并不是把这一百二十多个自动化配置全部导入,在他每个自动化配置里面都有条件判断注解,先判断是否引入相互的jar包,再判断容器是否有bean再进行注入到bean容器

4.运行方式

1.打包用命令或者放到容器中运行

2.用Maven/Gradle插件运行

3.直接执行main方法运行

5.启动流程

1、加载配置:Spring Boot会读取配置文件(如application.properties或application.yml)中的配置信息,包括端口号、数据库连接等。

2、创建Spring应用上下文:Spring Boot会创建一个Spring应用上下文(ApplicationContext),用于管理整个应用的各种Bean。

3、执行自动配置:Spring Boot会根据classpath中的依赖和配置信息,自动配置各种开箱即用的功能,例如数据库连接、Web服务器等。

4、扫描注解与组件:Spring Boot会扫描并加载带有特定注解(如@Controller、@Service、@Repository)的类,将其实例化为Bean。

5、触发应用事件:Spring Boot会触发一系列的应用事件,如应用上下文创建完成、Web服务器启动等。

6、启动Web服务器:如果应用包含Web组件,则Spring Boot会启动内嵌的Web服务器(如Tomcat、Jetty)。

7、运行应用:Web服务器启动后,Spring Boot会开始监听指定的端口号,接收并处理来自客户端的请求。

5.Spring Boot比Spring做了哪些改进?

1) Spring Boot可以建立独立的Spring应用程序;

2) 内嵌了如Tomcat,Jetty和Undertow这样的容器,也就是说可以直接跑起来,用不着再做部署工作了;

3) 无需再像Spring那样搞一堆繁琐的xml文件的配置;

4) 可以自动配置Spring.SpringBoot将原有的XML配置改为Java配置,将bean注入改为使用注解注入的方式(@Autowire),并将多个xml、properties配置浓缩在一个appliaction.yml 配置文件中。

5) 提供了一些现有的功能,如量度工具,表单数据验证以及一些外部配置这样的一些第三方功能;

6) 整合常用依赖(开发库,例如spring-webmvc、jackson-json、validation-api和tomcat等),提供的POM可以简化Maven的配置。当我们引入核心依赖时,SpringBoot会自引入其他依赖。

(自动配置,简化开发,清除了大量的xml配置,以及大量的依赖导入,在springboot中,springboot的启动直接由注解@SpringBootApplication其中的三个重要注解@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan实现自动装配)

6.SpringBoot监视器是什么东西?

spring boot actuator是spring启动框架中的重要功能之一;spring boot监视器可帮助您访问生产环境中正在运行的应用程序的当前状态,有几个指标必须在生产环境中进行环境和监控,即使一些外部程序应用可能正在使用这些服务来向相关人员触发警报消息;监视器模块公开了一组可直接作为HTTP URL 访问的REST断点来检查状态

7.SpringBoot和SpringMVC的区别有哪些?

SpringMVC是单体框架,SpringBoot是SpringMVC的升级版,可作为单体框架,也可作为前后端分离框架SpringMVC的前端页面是jsp,SpringBoot默认是htmlSpringMVC使用重量级的xml配置文件配置,并且需要程序员手动配置,SpringBoot自动配置了基础的配置,并提供了properties或yml文件让程序员使用个性化配置SpringMVC必须借助外部容器才能启动,SpringBoot内置tomcat,并以main方法启动

8.log4j的日志等级

①ERROR Level:指出虽然发生 错误事件,但不影响系统的继续运行;

②WARN Level:表明出现潜在错误;

③INFO Level:表明粗粒度级别,上强调应用程序的运行程序,比如进入某个业务分支;

④DEBUG Level:指出细粒度信息事件,主要用于调试应用程序;

⑤FATAL Level:指出每个严重的错误事件将会导致应用程序的推出;

注意:Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG.等于或高于日志记录器当前配置级别的日志的将会被打印出来。

9.@ResponseBody和@RequestBody的区别

①@ResponseBody用于将方法的返回值作为响应体返回给客户端,@RequestBody用于将请求体的数据解析为方法参数指定的对象类型;

②@ResponseBody注解在方法上,@RequestBody注解在方法参数上;

③@ResponseBody应用于响应处理,@RequestBody应用于请求处理。

10.@Resource和@Autowired区别

相同点:

都是用于依赖注入的注解,可以在Spring框架中使用。

不同点:

来源:@Resource是J2EE标准的注解,而@Autowired是Spring框架提供的注解。

类型:@Resource默认按照名称进行自动装配,如果找不到与名称匹配的bean,则会尝试按照类型进行匹配。@Autowired默认按照类型进行自动装配,如果存在多个与类型匹配的bean,则会抛出异常

配置方式:@Resource可以通过name属性指定bean的名称,也可以通过type属性指定bean的类型。​ @Autowired可以通过required属性指定依赖是否是必须得,默认为true。

支持范围:@Resource可以注入任意的资源,包括其他的JavaEE组件。​ @Autowired主要用于注入Spring容器中的bean。

总结:@Resource更加灵活,可以注入不同类型的资源,而@Autowired更加专注于注入Spring容器中的bean。在使用时,根据具体需求选择合适的注解。

11.@PostConstruct和实现CommonRunner接口的区别

@PostConstruct 是一个注解,用于在Bean实例化之后,依赖注入完成之后进行初始化操作的方法上进行标记。常见的应用场景包括在初始化完成后执行一些额外的逻辑,例如加载配置文件、建立连接等。通常情况下,@PostConstruct 方法会在构造函数执行完毕后立即执行。

而实现 CommonRunner 接口是一种自定义的做法,这个接口可能是由你自己或者你的团队定义的。通过实现 CommonRunner 接口,你可以在应用程序启动的时候执行一些自定义的逻辑。这个接口通常包含一个 run 方法,用于指定需要在应用程序启动时执行的代码。

总的来说,@PostConstruct 注解是用于在Bean初始化之后执行初始化操作的标记,而实现 CommonRunner 接口是一种自定义的启动初始化操作的方式。具体使用哪种方式取决于你的需求和实际情况。

6.Spring Security

1.什么是Spring Security?核心功能?

Spring Security是一个基于Spring框架的安全框架,提供了完整的安全解决方案,包括认证、授权、攻击防护等功能。

其核心功能包括:

认证:提供了多种认证方式,如表单认证、HTTP Basic认证、OAuth2认证等,可以与多种身份验证机制集成。

授权:提供了多种授权方式,如角色授权、基于表达式的授权等,可以对应用程序中的不同资源进行授权。

攻击防护:提供了多种防护机制,如跨站点请求伪造(CSRF)防护、注入攻击防护等。

会话管理:提供了会话管理机制,如令牌管理、并发控制等。

监视与管理:提供了监视与管理机制,如访问日志记录、审计等。

Spring Security通过配置安全规则和过滤器链来实现以上功能,可以轻松地为Spring应用程序提供安全性和保护机制。

2.Spring Security的原理?

Spring Security是一个基于Spring框架的安全性认证和授权框架,它提供了全面的安全性解决方案,可以保护Web应用程序中的所有关键部分。

Spring Security的核心原理是拦截器(Filter)。Spring Security会在Web应用程序的过滤器链中添加一组自定义的过滤器,这些过滤器可以实现身份验证和授权功能。当用户请求资源时,Spring Security会拦截请求,并使用配置的身份验证机制来验证用户身份。如果身份验证成功,Spring Security会授权用户访问所请求的资源。

Spring Security核心原理图

Spring Security的具体工作原理如下:

1.用户请求Web应用程序的受保护资源。

2.Spring Security拦截请求,并尝试获取用户的身份验证信息。

3.如果用户没有经过身份验证,Spring Security将向用户显示一个登录页面,并要求用户提供有效的凭据(用户名和密码)。

4.一旦用户提供了有效的凭据,Spring Security将验证这些凭据,并创建一个已认证的安全上下文(SecurityContext)对象。

5.安全上下文对象包含已认证的用户信息,包括用户名、角色和授权信息。

6.在接下来的请求中,Spring Security将使用已经认证的安全上下文对象来判断用户是否有权访问受保护的资源。

7.如果用户有权访问资源,Spring Security将允许用户访问资源,否则将返回一个错误信息。

3.有哪些控制请求访问权限的方法?

在Spring Security中,可以使用以下方法来控制请求访问权限:

permitAll():允许所有用户访问该请求,不需要进行任何身份验证。

denyAll():拒绝所有用户访问该请求。

anonymous():允许匿名用户访问该请求。

authenticated():要求用户进行身份验证,但是不要求用户具有任何特定的角色。

hasRole(String role):要求用户具有特定的角色才能访问该请求。

hasAnyRole(String... roles):要求用户具有多个角色中的至少一个角色才能访问该请求。

hasAuthority(String authority):要求用户具有特定的权限才能访问该请求。

hasAnyAuthority(String... authorities):要求用户具有多个权限中的至少一个权限才能访问该请求。

可以将这些方法应用于Spring Security的配置类或者在Spring Security注解中使用。

4.hasRole 和 hasAuthority 有区别吗?

在Spring Security中,hasRole和hasAuthority都可以用来控制用户的访问权限,但它们有一些细微的差别。

hasRole方法是基于角色进行访问控制的。它检查用户是否有指定的角色,并且这些角色以"ROLE_"前缀作为前缀(例如"ROLE_ADMIN")。

hasAuthority方法是基于权限进行访问控制的。它检查用户是否有指定的权限,并且这些权限没有前缀。

因此,使用hasRole方法需要在用户的角色名称前添加"ROLE_"前缀,而使用hasAuthority方法不需要这样做。

例如,假设用户有一个角色为"ADMIN"和一个权限为"VIEW_REPORTS",可以使用以下方式控制用户对页面的访问权限:

 .antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/reports/**").hasAuthority("VIEW_REPORTS")

在这个例子中,只有具有"ROLE_ADMIN"角色的用户才能访问/admin/路径下的页面,而具有"VIEW_REPORTS"权限的用户才能访问/reports/路径下的页面。

5.如何对密码进行加密?

在 Spring Security 中对密码进行加密通常使用的是密码编码器(PasswordEncoder)。PasswordEncoder 的作用是将明文密码加密成密文密码,以便于存储和校验。Spring Security 提供了多种常见的密码编码器,例如 BCryptPasswordEncoder、SCryptPasswordEncoder、StandardPasswordEncoder 等。

以 BCryptPasswordEncoder 为例,使用步骤如下:

1.在 pom.xml 文件中添加 BCryptPasswordEncoder 的依赖:

 <dependency>    <groupId>org.springframework.security</groupId>    <artifactId>spring-security-crypto</artifactId>    <version>5.6.1</version></dependency>

2.在 Spring 配置文件中注入 BCryptPasswordEncoder:

@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter {        @Bean    public PasswordEncoder passwordEncoder() {        return new BCryptPasswordEncoder();    }        // ...}

3.在使用密码的地方调用 passwordEncoder.encode() 方法对密码进行加密,例如注册时对密码进行加密:

@Servicepublic class UserServiceImpl implements UserService {     @Autowired    private PasswordEncoder passwordEncoder;     @Override    public User register(User user) {        String encodedPassword = passwordEncoder.encode(user.getPassword());        user.setPassword(encodedPassword);        // ...        return user;    }     // ...}

以上就是使用 BCryptPasswordEncoder 对密码进行加密的步骤。使用其他密码编码器的步骤类似,只需将 BCryptPasswordEncoder 替换为相应的密码编码器即可。

6.Spring Security基于用户名和密码的认证模式流程?

请求的用户名密码可以通过表单登录,基础认证,数字认证三种方式从HttpServletRequest中获得,用于认证的数据源策略有内存,数据库,ldap,自定义等。

拦截未授权的请求,重定向到登录页面的过程:

当用户访问需要授权的资源时,Spring Security会检查用户是否已经认证(即是否已登录),如果没有登录则会重定向到登录页面。

重定向到登录页面时,用户需要输入用户名和密码进行认证。

表单登录的过程:

用户在登录页面输入用户名和密码,提交表单。

Spring Security的UsernamePasswordAuthenticationFilter拦截表单提交的请求,并将用户名和密码封装成一个Authentication对象。

AuthenticationManager接收到Authentication对象后,会根据用户名和密码查询用户信息,并将用户信息封装成一个UserDetails对象。

如果查询到用户信息,则将UserDetails对象封装成一个已认证的Authentication对象并返回,如果查询不到用户信息,则抛出相应的异常。

认证成功后,用户会被重定向到之前访问的资源。如果之前访问的资源需要特定的角色或权限才能访问,则还需要进行授权的过程。

Spring Security的认证流程大致可以分为两个过程,首先是用户登录认证的过程,然后是用户访问受保护资源时的授权过程。在认证过程中,用户需要提供用户名和密码,Spring Security通过UsernamePasswordAuthenticationFilter将用户名和密码封装成Authentication对象,并交由AuthenticationManager进行认证。如果认证成功,则认证结果会存储在SecurityContextHolder中。在授权过程中,Spring Security会检查用户是否有访问受保护资源的权限,如果没有则会重定向到登录页面进行认证。

拦截未授权的请求,重定向到登录页面

拦截未授权的请求,重定向到登录页面图

表单登录的过程,进行账号密码认证

表单登录的过程,进行账号密码认证图

7.Spring Security 常见的过滤器介绍及项目中使用

Spring Security是一个用于在Java应用程序中实现身份验证和授权的强大框架。它提供了一系列的过滤器,用于处理不同的安全相关功能。以下是一些常见的Spring Security过滤器及其用途:

1、AuthenticationFilter(身份验证过滤器):负责验证用户的身份。它根据用户提供的凭据(如用户名和密码)进行验证,并生成一个认证对象,以便在后续的过滤器中进行授权。

2、UsernamePasswordAuthenticationFilter(用户名密码身份认证过滤器):用于处理基于用户名和密码的身份认证。它从登录表单获取用户输入的用户名和密码,并在身份验证过程中使用。

3、RememberMeAuthenticationFilter(记住我身份认证过滤器):用于处理基于“记住我”的身份认证。它允许用户在一段时间内无需重新输入凭据进行访问。

4、AuthorizationFilter(授权过滤器):用于检查用户是否具有访问特定资源或执行特定操作的权限。它通常根据用户的角色或权限信息进行判断。

5、ExceptionTranslationFilter(异常转换过滤器):负责处理Spring Security中的各种异常。它将异常转换为适当的HTTP状态码或执行特定的行为,如重定向到登录页面或拒绝访问。

在项目中使用Spring Security时,通常需要进行以下配置步骤:

1、引入Spring Security依赖:在项目的构建文件(如pom.xml)中添加Spring Security的依赖。

2、配置安全规则:通过配置类或XML文件定义安全规则,包括哪些URL需要进行身份验证、哪些URL需要特定角色或权限等。

3、自定义过滤器链:根据项目需求,可以自定义过滤器链来添加或修改Spring Security默认提供的过滤器。可以通过扩展WebSecurityConfigurerAdapter类来定义自己的过滤器链。

4、用户认证和授权:实现用户认证和授权的逻辑,可以使用内置的UserDetailsService来进行用户详细信息的加载,或自定义认证提供者(如数据库或LDAP)。

通过以上配置,Spring Security会根据定义的过滤器链和安全规则来对请求进行身份验证和授权。例如,在用户名密码身份认证过滤器验证成功后,可以使用授权过滤器判断用户是否有权限访问特定的资源。

8.SpringSecurity中的MD5算法是对称加密吗?

Spring Security中的MD5算法并不是对称加密算法,而是哈希算法(Hash Algorithm)

哈希算法是一种将任意长度的数据映射为固定长度散列值的算法。MD5哈希算法将输入数据转换为128位散列值。 对称加密算法(Symmetric Encryption Algorithm)是一种使用相同密钥进行加密和解密的算法,例如AES(Advanced Encryption Standard)和DES(Data Encryption Standard)等。

除了MD5算法,还有一些常用的哈希算法和对称加密算法,例如:

SHA-1(Secure Hash Algorithm 1):产生160位的散列值,相对于MD5更安全。SHA-256、SHA-384和SHA-512:SHA(Secure Hash Algorithm)家族的扩展版本,分别产生256位、384位和512位的散列值。 -AES(Advanced Encryption Standard):一种高级加密标准,使用对称密钥进行加密和解密,安全可靠性高。DES(Data Encryption Standard):一种对称加密算法,使用56位密钥对数据进行加密和解密。7.Vue

1.Vue2和Vue3的区别

生命周期函数钩子不同数据双向绑定原理不同定义变量和方法不同指令和插槽的使用不同API类型不同是否支持碎片父子之间传参不同Main.js文件中部分设置不同

2.Vue2和Vue3的生命周期钩子

Vue2

Vue3

说明

BeforeCreate

Setup()

组件创建之前

Created

Setup()

组件创建完成

BeforeMount

onBeforeMount

组件挂载之前

Mounted

onMounted

组件挂载完成

BeforeUpdate

onBeforeUpdate

数据更新,虚拟Dom打补丁之前

Updated

onUpdated

数据更新,虚拟Dom渲染之前

BeforeDestroy

onBeforeUnmount

组件销毁之前

Destroyed

onUnmounted

组件销毁后

activated

onActivated

deactivated

onDeactivated

3.Vue组件传值的方式

在Vue中实现组件传值,有两种方式:

1、一个父组件可以通过props向一个子组件传递数据,而子组件可以通过$emit事件向父组件传递数据

2、通过在子组件标签上绑定事件监听器,接收子组件的数据

具体的实现方式需要根据具体的业务需求进行选择和优化。

4.Vue网关的作用

1、路由管理:Vue网关可以根据配置文件进行动态路由管理,将前端请求路由到不同的后端服务,并对路由进行监控、限流等。

2、API接口管理:Vue网关提供了API接口中心,可以管理和监控所有后端服务的API接口,并支持对接口进行鉴权、授权等操作。

3、请求过滤和处理:Vue网关能够对请求进行预处理,例如请求合并、请求重试、请求缓存等,以减少不必要的前后端交互,提升系统性能。

4、安全性增强:Vue网关可以实现统一的安全认证和鉴权,为API服务提供访问控制和认证。

5.Vue中数据渲染方法

在Vue中,数据渲染是通过数据绑定实现的。当视图中需要展示动态的数据时,我们可以使用{{}}语法来绑定数据,Vue会将绑定的数据实时更新到视图中。

除了使用{{}}语法,Vue还提供了v-bind指令,可以将指定属性与Vue实例中的数据绑定起来。

6.模板引擎和Vue的区别

定位:模板引擎主要用于服务端渲染(SSR),而Vue是一种用于构建客户端应用程序的前端框架

数据绑定:模板引擎通常使用双向数据绑定或模板语法来将数据动态渲染到HTML模板中,而Vue基于响应式数据绑定,通过在模板中使用指令和插值表达式,将数据域DOM元素进行双向绑定。

动态更新:模板引擎需要在服务端进行模板渲染,生成最终的HTML响应,然后再将其发送给客户端。而Vue在客户端通过虚拟DOM和数据的变化,实现了高效的DOM更新和视图重新渲染。

结构复杂度:模板引擎通过适用于相对简单的页面,对于大型复杂的前端应用程序,可能难以维护和扩展。而Vue提供了组件化的开发方式,使得应用程序的结构更加清晰和可维护。

生态系统:Vue提供了完整的生态系统,包括路由、状态管理、构建工具等,可以方便地构建现代化的前端应用。而模板引擎通常只提供了基本的模板渲染功能,其他功能需要自行集成或选择其他库。

总之:模板引擎和Vue适用于不同的场景,如果需要实现高强度交互和可扩展的前端应用程序,推荐使用Vue;而如果只需要简单的动态模板渲染,模板引擎可能是更合适的选择。

7.MVVM

MVVM是一种架构模式,它代表着模型-视图-视图模型(Model-View-ViewModel)

MVVM的关键思想是将应用程序的界面(视图)与应用程序的逻辑和数据(模型)分离,以及通过一个中介层(视图模型)将两者连接起来。MVVM的设计目标是提高代码的可维护性、可测试性和可扩展性

以下是对MVVM的各个组成部分的简要解释:

模型(Model):模型表示应用程序的数据或业务逻辑。它可以是从数据库、网络或其他数据源获取的数据,也可以是应用程序的状态和行为

视图(View):视图是应用程序的用户界面,它负责展示数据并与用户进行交互。在MVVM中,视图通常是声明性的,使用标记语言(如HTML、XML等)来描述其外观和布局。

视图模型(ViewModel)视图模型是视图和模型之间的中介层。它从模型中获取数据,并将其转换成视图可以使用的格式。视图模型还包含了处理用户交互、发送指令到模型和控制视图状态的逻辑。

数据绑定(Data Binding)MVVM通过数据绑定机制实现视图和视图模型之间的数据同步。当模型的数据发生变化时,视图会自动更新;当用户在视图上进行操作时,视图模型可以立即接收到通知并作出相应的反应。

MVVM的主要优势在于它将应用程序的逻辑与界面逻辑分离,使得代码更加清晰和可维护。它还有助于促进团队协作,因为开发人员可以同时开发视图和视图模型,而无需关心彼此的具体实现细节。

总之,MVVM是一种用于构建现代化、可扩展和可测试的应用程序的架构模式,它通过将视图、视图模型和模型分离,实现了良好的代码组织和分离关注点的原则。

标签: #java ee框架技术课后题答案 #轻量级javaee程序设计及实践课后题答案