框架面试题

 

1 spring特性是什么?

1 IOC控制反转

2 aop面向切面编程

2 ioc和aop的原理是什么?

1 ioc

  把创建对象的权利交给spring, 有spring来管理对象,使用对象的时候通过依赖注入来注入对象

autowired, qualifier, resource

2 aop

  一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行

  二是采用静态织入的方式,引入特定的语法创建“切面”,从而使得编译器可以在编译期间织入有关“切面”的代码,属于静态代理

3 aop的注解有哪些?

@Aspect:

作用:把当前类声明为切面类

@Before:

作用:把当前方法看成是前置通知

属性:

value:用于指定切入点表达式,还可以指定切入点表达式的引用。 讲师:陈飞

@AfterReturning

作用:把当前方法看成是后置通知

属性:

value:用于指定切入点表达式,还可以指定切入点表达式的引用。

@AfterThrowing

作用:把当前方法看成是异常通知

属性:

value:用于指定切入点表达式,还可以指定切入点表达式的引用。

@After

作用:把当前方法看成是最终通知

属性:

value:用于指定切入点表达式,还可以指定切入点表达式的引用。

@Around

作用:把当前方法看成是环绕通知

属性:

value:用于指定切入点表达式,还可以指定切入点表达式的引用

@Pointcut

作用:指定切入点表达式

属性:

value:指定表达式的内容

4 springboot自动装配的原理是什么?

1 Spring Boot关于自动配置的源码在spring-boot-autoconfigure-x.x.x.x.jar中

2 @SpringBootApplication是一个复合注解或派生注解,在 @SpringBootApplication中有一个注解 @EnableAutoConfiguration,翻译成人话就是开启自动配置

3 @EnableAutoConfiguration也是一个派生注解,其中的关键功能由 @Import提供

4 @Import导入的AutoConfigurationImportSelector的selectImports()方法通过SpringFactoriesLoader.loadFactoryNames()扫描所有具有META-INF/spring.factories的jar包

spring-boot-autoconfigure-x.x.x.x.jar里就有一个这样的spring.factories文件

  • 1 这个spring.factories文件也是一组一组的key=value的形式
  • 2 其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔
  • 3 这个 @EnableAutoConfiguration 注解通过 @SpringBootApplication被间接的标记在了Spring Boot的启动类上
  • 4 在SpringApplication.run(...)的内部就会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有自动配置类加载到Spring容器中。

5 自动配置生效

1 每一个XxxxAutoConfiguration自动配置类都是在某些条件之下才会生效的
2 这些条件的限制在Spring Boot中以注解的形式体现
3 即使用一些条件注解类

  • @ConditionalOnBean:当容器里有指定的bean的条件下。
  • @ConditionalOnMissingBean:当容器里不存在指定bean的条件下。
  • @ConditionalOnClass:当类路径下有指定类的条件下。
  • @ConditionalOnMissingClass:当类路径下不存在指定类的条件下。
  • @ConditionalOnProperty 指定的属性是否有指定的值,比如 @ConditionalOnProperties(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),代表当xxx.xxx为enable时条件的布尔值为true,如果没有设置的情况下也为true。

6 面试回答可以为

Spring Boot启动的时候会通过 @EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类,

并对其进行加载,而这些自动配置类都是以AutoConfiguration结尾来命名的,

它实际上就是一个JavaConfig形式的Spring容器配置类,

它能通过以Properties结尾命名的类中取得在全局配置文件中配置的属性如:server.port,

而XxxxProperties类是通过 @ConfigurationProperties注解与全局配置文件中对应的属性进行绑定的。

5 springboot配置文件中常用配置有哪些?

  properties, yml, yaml, bootstrap

6 springboot项目如何打包,部署,运行?

1 jar包方式

1 直接在idea中执行打包命令: mvn package
2 打包后进入到jar包目录, 然后进入cmd用命令, java -jar jar名名称

2 war包方式

1 pom.xml中配置打包方式为war包
2 执行打包命令
3 把打成的war包放到tomcat的webapps目录中, 启动tomcat即可

7 spring是如何控制事务的?

  使用aop控制事务, 使用动态代理技术

8 springmvc常用注解及作用?

1 @Controller 定义了一个控制器类
2 @RequestMapping 用来处理请求地址映射的注解
3 @Resource 和 @Autowired 做bean的注入时使用
4 @ModelAttribute 和 @SessionAttributes

  • 1 该Controller的所有方法在调用前,先执行此 @ModelAttribute方法
    • 可用于注解和方法参数中,可以把这个 @ModelAttribute特性,应用在BaseController当中,所有的Controller继承BaseController,即可实现在调用Controller时,先执行 @ModelAttribute方法。
  • 2 @SessionAttributes即将值放到session作用域中,写在class上面
  • 3 传递和保存数据

5 @PathVariable 用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数
6 @requestParam SpringMVC后台控制层获取请求参数
7 @ResponseBody 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区
1 使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
8 @Component 相当于通用的注解,当不知道一些类归到哪个层时使用,但是不建议。
9 @Repository 于注解dao层,在daoImpl类上面注解。
10 @Service
11 @GetMapping, @PostMapping, @PutMapping, @DeleteMapping

9 springmvc的工作流程是什么?

1、 用户发送请求至前端控制器DispatcherServlet
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
4、 DispatcherServlet调用HandlerAdapter处理器适配器
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)
6、 Controller执行完成返回ModelAndView
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、 ViewReslover解析后返回具体View
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)
11、DispatcherServlet响应用户

10 mybatis的工作原理是什么?

1 mybatis底层还是采用原生jdbc来对数据库进行操作的

1 只是通过 SqlSessionFactory,SqlSession Executor,StatementHandler
2 ParameterHandler,ResultHandler和TypeHandler等几个处理器封装了这些过程

2

执行器:Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
参数处理器: ParameterHandler (getParameterObject, setParameters)
结构处理器:ResultSetHandler (handleResultSets, handleOutputParameters)
sql查询处理器:StatementHandler (prepare, parameterize, batch, update, query)

3 Mybatis工作原理:

  MyBatis应用程序根据XML配置文件创建SqlSessionFactory,SqlSessionFactory在根据配置获取一个SqlSession。(配置来源于两个地方,一处是配置文件,一处是Java代码的注解)
  SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句,完成对数据的增删改查和事务提交等,
用完之后关闭SqlSession
  SqlSessionFactory,SqlSession是对jdbc的封装, 底层还是调用的jdbc对数据库进行操作

11 mybatis的缓存的理解?

mybatis提供查询缓存,用于减轻数据压力,提高数据库性能
Mybatis内部存储缓存使用的是一个HashMap对象
key为 hashCode + sqlId + sql 语句
而value值就是从查询出来映射生成的java对象

1 一级缓存

  一级缓存是SqlSession级别的缓存

  我们都知道在操作数据库时需要构造 sqlSession对象,而在sqlSession对象中有一个数据结构(HashMap)用于存储缓存数据,比如查询id为1的用户信息, 会先从sqlSession的缓存中查找, 如果有结果, 就不用再查数据库了,如果缓存中没有, 才去查询数据库

  不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的,即一级缓存的不同sqlSession之间数据不共享

  一级缓存默认启用, 想要关闭一级缓存可以再select标签上配置flushCache = “true”

  一级缓存存在于Sqlsession 的声明周期中,在同一个SqlSeesion中查询时,Mybatis会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个Map对象中,如果同一个SqlSession中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当Map缓存对象中已经存在该键时,则会返回缓存中的对象

  任何的insert,update,delete操作都会清空一级缓存,是为了保证缓存里面的数据肯定是准确数据避免脏读

2 二级缓存

  二级缓存以namespace为单位进行缓存

  二级缓存默认开启,但是必须利用<cache></cache>标签才能开启单个namespace二级缓存,相同namespace的mapper查询数据放在同一个区域,多个SqlSession去操作同一个Mapper的sql语句, 多个SqlSession可以共用二级缓存, 二级缓存是可以横跨跨SqlSession的

  二级缓存有时会出现脏读情况,是因为不同的namespace中相同的查询所致,每当进行update,delete,insert操作时,会以namespace为单位清空缓存

12 mybatis中#{} 和{} 的区别?

${}字符串替换

1 其中间的变量就是直接替换成值的
2 $ 的作用实际上是字符串拼接,所以要特别小心sql注入问题

#{}预编译处理

1 会根据变量的类型来进行替换
2 # 把参数部分用一个占位符 ? 代替, 这样可以有效的防止sql注入
3 具体执行时,# 都是用到了prepareStement,这样对效率也有一定的提升
4 #方式一般用于传入插入/更新的值或查询/删除的where条件

能同时用#和$的时候最好用#

13 springboot的异常处理?

一 自定义错误页面

  只需要在resources/templates/目录下新建一个名为error的视图页面即可。
  当出现异常时,SpringBoot 会像/error 的 url 发送请求。在 springBoot 中提供了一个叫 BasicExceptionController 来处理/error 请求,然后跳转到默认显示异常的页面来展示异常信息。
  缺点:拦截所有错误,不灵活。

二 使用注解 @ExceptionHandler处理

  在controller类中添加错误处理的方法,返回ModelandView,并使用 @ExceptionHandler(value={})注解,value中标注错误类型,当发生错误时会自动跳转到你设置的错误页面中
  缺点:只能在一个controller中使用,不能跨controller使用

三 使用注解 @ControllerAdvice处理

  定义一个类用来装所有的错误类型,并且使用 @controllerAdvice注解
  其中可以定义处理错误的方法, 方法上使用 @ExceptionHandler(value={})注解
  缺点:如果有多个错误还是要写多个方法,代码重复严重

四 使用 @Configuration注解处理

  新建类,在类中使用 @Configuration注解,在类中定义方法,方法使用 @Bean注解,并且返回值为:SimpleMappingExceptionResolver
  将所有的错误都定义到一个方法中,发生错误时,会根据判断自动跳转到指定错误页面
  缺点:不能将错误信息传递到页面中

五 自定义 HandlerExceptionResolver 类处理异常

  新建类,使用Configuration注解并且实现HandlerExceptionResolver接口,实现方法

推荐使用第五种方法,既可以将错误定义到一个方法中,又可以传递错误信息到错误页面中

14 spring中如何配置拦截器, 过滤器?

1 拦截器: interceptor(拦截器)

1 创建拦截器类实现HandlerInterceptor接口
2 实现接口中的三个方法

  • 1 boolean preHandle(request, response, Object handler){ }: 该方法在控制器方法执行之前执行
  • 2 void postHandle(request, response, handler, modelAndView){ }: 该方法在控制器方法执行之后, 视图对象返回之前执行
  • 3 void afterCompletion(request, response, handler, Exception e){ }: 该方法在流程都执行完毕后执行, 即服务器处理完成一次请求

3 方法执行顺序

  • 1 一个拦截器: preHandle -> 控制器方法 -> postHandle -> afterCompletion
  • 2 两个拦截器: 拦截器1(配置在前, 先执行), 拦截器2
    • preHandle(1) -> preHandle(2) -> 控制器方法 -> postHandle(2) -> postHandle(1) -> afterCompletion(2) -> afterCompletion(1)

4 spring配置文件中需要配置拦截器以及拦截路径

2 过滤器

1 方法一(spring):

  • 1 过滤器不是spring的, 而是web的是基于servlet的过滤器
  • 2 自定义类实现Filter接口
    • 重写方法doFilter()
  • 3 在web.xml中配置过滤器, 使用 filter 标签和 filter-mapping 标签

2 方法二(springboot):

  • 1 自定义类实现Filter接口, 类上添加注解 @WebFilter
  • 2 springboot启动类上添加包扫描注解: @ServletComponentScan(basePackages = "自定义filter全限定类名")

15 spring管理的bean是否会存在并发?

1 存在
2 Spring默认的单例模式的bean

1 因为是单例的,所以会避免不断的创建新的实例从而导致并发量很大时垃圾回收效率低的问题。
2 也有缺点,就是状态不好管理,也就是说bean里面的全局变量不好管理,因为这样很容易会导致多线程问题。

3 一般来说我们用Spring管理的类一般是各种Service类,无需设计成有状态的bean,而状态最好不要在bean里面保存,因为集群环境下bean管理的状态会有问题。可以考虑使用缓存或者数据库来管理状态。
如果一个对象是单例的, 而这个对象中又有全局变量时, 在多线程中就会产生线程安全问题

16 springsession的原理是什么?

1 session只能在单台服务器上使用, 而在分布式或集群中, 用户访问一台服务器产生的session, 在访问另一台服务器时无法被识别
2 springsession就是在分布式或集群中使用的, 可以代替session
3 原理

1 方式一: 利用redis来实现session同步

  • 1 既当客户端访问服务器端的时候,将服务器端生成的session信息保存在redis中
  • 2 然后访问的时候通过redis获取session信息
  • 3 springsession使用该方式, 支持数据库,redis等存储方式;

2 方式二: 使用token 替代 session 即 auth2认证方案,一般用于移动端的开发

17 spring的类加载器是什么?

AppClassLoader: 应用程序类加载器

其他

1、 启动类加载器(Bootstrap ClassLoader):
  这个类加载器负责将存放在<JAVA_HOME>\lib目录中,或者被-XbootClasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。
  启动类加载器无法直接被java程序引用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那直接使用null代替即可。
2、 扩展类加载器(Extension ClassLoader):
  这个加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中,或者被java.ext.dirs系统变量所指定的路径中的类库,开发者可以直接使用扩展类加载器。
3、 应用程序类加载器(Application ClassLoader):
  这个类加载器由sun.misc.Launcher$AppClassLoader实现。
  由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器,它负责加载用户类路径(classpath)上指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中的默认类加载器

18 springcloud的组件有哪些? 作用分别是什么?

1 eureka: 治理组件

  • 1 服务注册中心,特性有失效剔除、服务保护。
  • 2 还有consul, nacos作用和eureka类似

2 ribbon: 客户端负载均衡组件

  •  客户端负载均衡,特性有区域亲和、重试机制

3 hystrix: 服务容错保护组件

  •  客户端容错保护,特性有服务降级、服务熔断、请求缓存、请求合并、依赖隔离。

4 feign: 声明式服务调用组件

  • 声明式服务调用,本质上就是Ribbon+Hystrix

5 zuul: API网关治理组件

  • 1 API服务网关,功能有路由分发和过滤。
  • 2 类似的还有gateway

6 config: 分布式配置中心组件

  •  分布式配置中心,支持本地仓库、SVN、Git、Jar包内配置等模式

7 bus: 消息总线组件

  •  消息总线,配合Config仓库修改的一种Stream实现

8 stream: 消息驱动组件

  •  消息驱动,有Sink、Source、Processor三种通道,特性有订阅发布、消费组、消息分区。

9 sleuth: 分布式跟踪组件

  •  分布式服务追踪,需要搞清楚TraceID和SpanID以及抽样,如何与ELK整合。

10 Dashboard,Hystrix仪表盘,

  •  监控集群模式和单点模式,其中集群模式需要收集器Turbine配合。

19 dubbo和springcloud的区别和优缺点?

1 dubbo

1 dubbo由于是二进制的传输,占用带宽会更少
2 dubbo的开发难度较大,原因是dubbo的jar包依赖问题很多大型工程无法解决
3 dubbo的注册中心可以选择zookeeper,redis等多种

2 springcloud

1 springCloud是http协议传输,带宽会比较多,同时使用http协议一般会使用JSON报文,消耗会更大
2 springcloud的接口协议约定比较自由且松散,需要有强有力的行政措施来限制接口无序升级
3 springcloud的注册中心能用eureka, consul, nacos

3 spring cloud整机,dubbo需要自己组装;整机的性能有保证,组装的机子更自由

4 区别

1 dubbo是rpc框架, spirngcloud是微服务框架
2 Dubbo基于RPC;SpringCloud基于HTTP的Rest风格
3 dubbo只是实现了服务治理, 但springcloud中包含了微服务架构下的各个方面的组件, 更加全面

20 gateway的动态路由如何实现?

  动态路由: uri: lb://GATEWAY-PROVIDER

  注意: "//"后面的为在服务注册中心中的服务名称

21 鉴权框架的了解和使用?

1 鉴权的使用

1 单体应用下的常用方案

  • 1 传统的单体应用,一般会写一个固定的认证和鉴权的包,里面包含很多的认证和鉴权的类
  • 2 当用户请求时可以利用session的方式,把用户存入session并生成一个sessionid,之后返回客户端
  • 3 客户端可以存在cookie里,从而在后续的请求中顺利通过验证。
  • 4 常用框架:shiro 、自定义注解、Filter拦截等

2 微服务下的SSO单点登陆方案

  • 1 单点登录(Single Sign On),简称为 SSO, 是目前比较流行的企业业务 整合的解决方案之一
  • 2 SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统
  • 3 但是针对微服务(服务之间调用):每个 服务都进行每个用户端 的sso动作,那么每个服务里都会做用户的认证和鉴权,可能保存每个用户的信息或者每个用户都会和鉴权服务打交道,这些情况都会带来非常大的网路开销和性能消耗,也有可能会造成数据的不一致,所以不建议用这种方案。

3 分布式Session与网关结合方案

  • 1 步骤
    • 1 用户在网关进行sso登陆 ,进行用户认证,检查用户是否存在和有效
    • 2 如果用户通过,则将用户信息存储在第三方中间件中,如mysql、redis
    • 3 后端可以从共享存储拿到用户的数据
  • 2 很多 场景下,这种方案是推荐的,因为方便扩展,也 可以保证高可用的方案
  • 3 但是这种方案的缺点是依赖于第三方中间件,且这些部件需要 做高可用,并且增加安全的控制,所有对于实现有一定的复杂度

4 客户端Token与 网关结合方案

  • 1 实现步骤
    • 1 客户端持有一个token,通常可用jwt或者其它加密的算法实现自己的一种Token,然后通过token保存用户的信息
    • 2 发起用户请求并携带token,token传到网关层后,网关 层进行认证和校验
    • 3 校验通过,携带token到后端服务中
    • 4 如果涉及到用户的大量信息存放,token就有可能不太合适(或者用中间件来存放)
  • 2 这种方案也是业界很常用的方案,但是对于 token来说,他的注销有一定的麻烦,需要在网关层进行Token的注销

5 浏览器Cookie与网关结合方案

  • 1 实现: 把用户的信息存放在cookie里,然后通过网关来解析cookie,从而 获取用户的相关信息
  • 2 这种方式在一些老系统做改造时遇到的比较多,适合做为老系统改造时采取的方案,因为很多系统需要继承,这时cookie在别的系统中也是同样的适用。

6 网关Token和 服务间鉴权结合

  • 实现步骤
      1 在gateway网关层做认证,通过用户校验后,传递用户信息到header中,后台做服务在收到header后进行解析,解析完后查看是否有调用此服务或者某个url的权限,然后完成鉴权。
            2 从服务内部发出的请求,在出去时进行拦截,把用户信息保存在header里,然后传出去,被调用方取到header后进行解析和鉴权

2 Spring Security 权限框架

  Spring Security是Spring全家桶中的处理身份和权限问题的一员。Spring Security可以根据使用者的需要定制相关的角色身份和身份所具有的权限,完成黑名单操作、拦截无权限的操作等等。

配置文件中配置相关配置

            ublic class UserService implements UserDetailsService {
                public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                    用户名密码判断
                    授予权限
                }
            }
            controller方法添加注解
                @PreAuthorize("hasAuthority('add')")
                @PreAuthorize("hasRole('ROLE_ADMIN')")

3 Shiro 权限框架

   Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。

认证流程:
  构造SecurityManager → Subject()提交认证 → SecurityManager.login()执行认证 → Authenticator执行认证 → Realm根据身份获取验证信息

1、 创建token令牌,token中有用户提交的认证信息即账号和密码

2、 执行subject.login(token),最终由securityManager通过Authenticator进行认证

3、 Authenticator的实现ModularRealmAuthenticator调用realm从ini配置文件取用户真实的账号和密码,这里使用的是IniRealm(shiro自带)

4、 IniRealm先根据token中的账号去ini中找该账号,如果找不到则给ModularRealmAuthenticator返回null,如果找到则匹配密码,匹配密码成功则认证通过。

授权方式

Shiro 支持三种方式的授权:

编程式:通过写if/else 授权代码块完成:

Subject subject = SecurityUtils.getSubject();

if(subject.hasRole(“admin”)) {

//有权限

} else {

//无权限

}

注解式:通过在执行的Java方法上放置相应的注解完成:

@RequiresRoles("admin")

public void hello() {

//有权限

}

JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成:

<shiro:hasRole name="admin">

<!— 有权限—>

</shiro:hasRole>

 

4 SpringSecurity和Shiro都是基于RBAC的

1 RBAC是Role Based Access Control的英文缩写,意思是基于角色访问控制。
2 在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限

  • 1 这就极大地简化了权限的管理。
  • 2 这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,
  • 3 这样的权限设计很清楚,管理起来很方便。

5 spring security和shiro的异同

相同点:

  1、认证功能;2、授权功能;3、加密功能;4、会话管理;5、缓存支持;6、rememberMe功能;

不同点:

  1、Spring Security 基于Spring 开发,项目若使用 Spring 作为基础,配合 Spring Security 做权限更加方便,而 Shiro 需要和 Spring 进行整合开发;
  2、Spring Security 功能比 Shiro 更加丰富些,例如安全维护方面;
  3、Spring Security 社区资源相对比 Shiro 更加丰富;
  4、Spring Security对Oauth、OpenID也有支持,Shiro则需要自己手动实现。而且Spring Security的权限细粒度更高
  5、spring security 接口 RequestMatcher 用于匹配路径,对路径做特殊的请求,类似于shiro的抽象类 PathMatchingFilter,但是RequestMatcher 作用粒度更细
  6、Shiro 的配置和使用比较简单,Spring Security 上手复杂些;
  7、Shiro 依赖性低,不需要任何框架和容器,可以独立运行.Spring Security 依赖Spring容器;
  8、shiro 不仅仅可以使用在web中,还支持非web项目它可以工作在任何应用环境中。在集群会话时Shiro最重要的一个好处或许就是它的会话是独立于容器的。


  使用apache shiro的优点在于,简单,易用,功能也强大,spring官网就是用的shiro,可见shiro的强大

22 mybatis同时操作通一条数据该怎么解决并发问题?

1 发现并发问题

1 可以给表增加一个版本号字段, 新的时候给版本号字段加上 1
2 更新执行后, 会返回一个更新结果的行数,
3 如果更新执行返回的数量是 0 表示产生并发修改了, 需要重新获得最新的数据后再进行更新操作

2 Hibernate、JPA 等 ORM 框架或者实现,是使用版本号

判断 UPDATE 后返回的数值, 如果这个值小于 1 时则抛出乐观锁并发修改异常。

3 使用版本号的方式属于乐观锁

23 mybatis中传递参数有哪些方式?

1.第一种方式 匿名参数 顺序传递参数, (param1, param2,...), (arg0, arg1,...)

1 mapper: List<Employee> selectByGenderAndAge(Short gender,String age );
2 xml:

<select id="selectByGenderAndAge" resultMap="BaseResultMap" >
  select * from employee where gender = #{param1} and age = #{param2}
</select>
或在#{}中使用 arg0, arg1

3 这种传参方式的缺点是不够灵活,必须严格按照参数顺序来引用

2.第二种方式 使用 @Param注解

1 mapper: List<Employee> selectByGenderAndAge( @Param("gender") Short gender,@Param("age") String age );
  使用 @Param注解显示的告诉mybatis参数的名字,这样在xml中就可以按照参数名去引用了
2 xml:

<select id="selectByGenderAndAge" resultMap="BaseResultMap" >
  select * from employee where gender = #{gender} and age = #{age}
</select>

 

3.使用Map传递参数

1 mapper: List<Employee> selectByMapParams(Map params);
  所有要传递的参数都被封装到map中了
2 xml:

<select id="selectByMapParams" resultMap="BaseResultMap" parameterType="map">
  select * from employee where gender = #{gender} and age = #{age}
</select>
#{}中使用的值就是map值的key值

 

4.用过java bean传递多个参数

1 mapper: List <Employee> selectByBeans(Employee employee);
  数据被封装到一个javaBean中
2 xml:

<select id="selectByBeans" resultMap="BaseResultMap" parameterType="com.wg.demo.po.Employee">
  select * from employee where gender = #{gender} and age = #{age}
</select>
#{}中填写的为javabean中的属性的名称

 

5.直接使用JSON传递参数

1 mapper: List <Employee> findByJSONObject(JSONObject params);
  controller的方法中接收参数是就是用 @RequestBody JSONObject params 来接收json数据
2 xml

<select id="findByJSONObject" resultMap="BaseResultMap" parameterType="com.alibaba.fastjson.JSONObject">
  select * from employee where gender = #{gender} and age = #{age}
</select>
#{}中填写的为json中的key值

 

6.传递集合类型参数List、Set、Array, 需要使用<foreach>标签遍历

1 mapper: List <Employee> findByList(List list);
2 xml:

<select id="findByList" resultMap="BaseResultMap" >
  SELECT * from employee where age in
  <foreach collection="list" open="(" separator="," close=")" item="age">
  #{age}
  </foreach>
</select>
  这里foreach表示循环操作, 遍历取出集合中的数据

 

7.参数类型为对象+集合

1 该类参数与java Bean参数形式类似, 但是在对象的属性中不仅有基本类型的变量, 还有集合类型的变量,集合中存储的是对象数据

2 mapper: List <Employee> findByDepartment(@Param("department")Department department);
3 xml:

<select id="findByDepartment" resultMap="BaseResultMap" parameterType="com.wg.demo.po.Department">
      SELECT * from employee where dept_id =#{department.id} and age in
     <foreach collection="department.employees" open="(" separator="," close=")" item="employee">
      #{employee.age}
     </foreach>
</select>

 

24 spring中bean的生命周期? 作用域有哪些?

1 spring中bean的生命周期

1 单例bean对象

  • 1 对象创建: 当应用加载, 创建spring容器时, 对象就被创建了
  • 2 对象存活: 只要容器存在, 对象一直存活
  • 3 对象销毁: 当应用卸载, 销毁容器时, 对象被销毁

2 多例bean对象

  • 1 对象创建: 当使用对象时, 创建新的对象实例
  • 2 对象存活: 只要对象在使用中, 对象一直存活
  • 3 对象销毁: 当对象长时间不用时, 被java的垃圾回收器回收

2 作用域有哪些

1 singleton: 单例的(默认值), bean.xml文件加载后立即创建其中的对象
2 prototype: 多例的, 对象在使用时才会被创建
3 request: 作用与web应用的请求范围, web项目中, 将创建的对象存入request域中
4 session: 作用于web应用的会话范围, web项目中, 将创建的对象存入session域中
5 global-session: 作用于集群环境的会话范围(全局会话范围)

25 怎么实现mybatis批量插入?

1 xml配置

1 方式一: 写一个insert标签, java代码重复多次调用

2 方式二: insert标签中使用foreach标签遍历要插入的数据, 并拼接到sql语句上

2 注解方式

26 junit如何使用?

1 spring

1 导入junitjar包:
2 测试类添加注解

  • 1 @Runwith(SpringJunit4ClassRunner.class)
  • 2 @ContextConfiguration(classes={配置类的路径})
    •  value属性指定配置文件路径: value="classpath:文件路径"

2 springboot

1 坐标: org.springframework.boot spring-boot-starter-test
2 测试类添加注解

  • 1 @Runwith(SpringRunner.class)
  • 2 @SpringBootTest(classes = 引导类名.class)
    •  如果测试类所在包名和引导类所在包名相同时, 可以不写classea参数

3 junit注解

1 @Test: 测试方法
2 @Before: 在测试方法执行之前执行
3 @After: 在测试方法执行之后执行
4 @Ignore: 忽略方法, 即不对该方法进行测试
5 @BeforeClass: 在测试类执行之前执行
6 @AfterClass: 在测试类执行之后执行

27 spring的工厂模式如何使用?

  工厂模式由一个接口类加一个对应的工厂类实现的,接口类提供所有要创建出来的实体所需要的方法,工厂类只负责一件事:创建实现类的对象的方法。
  Spring 框架有Spring 容器,Spring 容器在启动的时候已经创建了,所有被@Component注解标注的实体类都会被扫描到放入容器中,下次使用是直接从容器中取出对象,不会再new新的对象。
  把实现类放入spring容器中,使用AnnotationConfigApplicationContext可以实现基于Java的配置类加载Spring的应用上下文,让工厂类能够使用实现类的方法,并把创建的对象放到容器中。

28 springboot是如何对线程进行封装的?

1 你直接new出来的对象是没法使用的

1 就算你能new成功,但是bean里面依赖的其他组件比如Dao,
2 是没法初始化的,因为你饶过了spring,
3 默认的spring初始化一个类时,其相关依赖的组件都会被初始化,
4 但是自己new出来的类,是不具备这种功能的

2 需要通过spring来获取我们自己的线程类

3 springboot对多线程的封装

1 Spring是通过任务执行器(TaskExecutor)来实现多线程和并发编程
2 使用ThreadPoolTaskExecutor来创建一个基于线城池的TaskExecutor
1 在使用线程池的大多数情况下都是异步非阻塞的
3 注解 @EnableAsync: 来开启Springboot对于异步任务的支持
4 然后在实际执行的方法上配置注解 @Async上声明是异步任务

4 线程池的配置方式

1 方式一: 创建一个配置类, 并实现AsyncConfigurer接口

  • 1 类上添加注解
    • 1 @Configuration

    • 2 @EnableAsync // 开启Springboot对于异步任务的支持

  • 2 类中重写接口中的方法
    •     public Executor getAsyncExecutor() {
              ThreadPoolTaskExecutor executor = new 
              executor.setCorePoolSize(5);
              executor.setMaxPoolSize(15);
              executor.setQueueCapacity(25);
              executor.initialize();
              return executor;
          }
          public AsyncUncaughtExceptionHandler 
              return null;
          }

2 方式二: 创建一个配置类

  • 1 类上添加注解
    • 1 @Configuration
    • 2 @EnableAsync // 开启Springboot对于异步任务的支持
  • 2 类中添加方法: public Executor getAsyncExecutor() { }
    • 1 方法中内容和上面的相同
    • 2 方法上添加注解: @Bean

3 使用上述两种方式之一后, 使用时只需要在对应的方法上添加 @Async 注解即可

  • 1 如在service的一个方法上添加 @Async 注解, 表明该方法是异步方法
  • 2 如果Async注解在类上,那表明这个类里面的所有方法都是异步的
  • 3 在调用该方法时, 框架中会自动把该方法用一个新的线程来执行

29 springboot中starter种类有哪些?如何写一个springboot的starter组件?

1 常用starter

spring-boot-starter-web

spring-boot-starter-thymeleaf

1 依赖作用: 模板配置
2 分析:

  • 1 在springboot中使用 @RestController时候不需要模板技术
  • 2 但是如果使用 @Controller不加入模板技术的话, 启动服务器不会报错, 但是无法网页访问项目
  • 3 且如果设置了html网页, 则建议使用 @Controller, 且添加该模板坐标

spring-boot-starter-data-redis

spring-boot-starter-data-jpa

1 用于操作mysql的数据库用的, 用于表的基本CRUD
2 复杂的查询操作则使用mybatis

spring-boot-starter-data-elasticsearch

1 elasticSearch 其实也算是一种nosql数据库
2 如果是用spring-boot-starter-data-elasticsearch的话在增删方面用起来和JPA几乎没什么两样

spring-boot-starter-data-mongodb

spring-boot-starter-test

spring-boot-starter-jdbc

spring-boot-starter-aop

spring-boot-starter-security

spring-boot-starter-actuator

spring-boot-starter-tomcat

2 如何写一个springboot的starter组件

1 创建starter项目,spring应用
2 pom文件添加一个SpringBoot坐标, 以及其他相关依赖
3 创建xxxAutoConfiguration类

加上注解

1 @Configuration(表明这是一个配置类)
2 @EnableConfigurationProperties(RedisProperty.class)(从名称上可以看出开启自动配置,后面跟上属性的property)
3 @ConditionalOnClass(Redisson.class)(当其他项目引用这个组件的时候会根据对应的条件选择注入bean)

4 RedisProperty类(ConfigurationProperties) 就是我们的属性设置

添加 @ConfigurationProperties(prefix="前缀")

5 配置文件: 在resource文件夹下创建META_INF文件夹,spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxxAutoConfiguration全限定类名

6 添加配置文件

1 additional-spring-configuration-metadata.json, 

    • 在META_INF文件夹中添加该文件
    • 文件内容
              {
                "properties": [
                  {
                    "name": "***.redisson.host",
                    "type": "java.lang.String",
                    "description": "redis服务器地址",
                    "defaultValue": "localhost"
                  },{
                    "name": "***.redisson.port",
                    "type": "java.lang.Integer",
                    "description": "redis服务器的端口",
                    "defaultValue": 6379
                  }
                ]
              }

2 作用: 为了在yml文件中配置属性时有提示

30 设计一个开放接口, 如何保证接口安全性?

1 数据加密

1 数据在传输过程中是很容易被抓包

  • 1 如果直接传输比如通过http协议, 那么用户传输的数据可以被任何人获取, 所以必须对数据加密
  • 2 常见的做法对关键字段加密比如用户密码直接通过md5加密
  • 3 现在主流的做法是使用https协议
    • 在http和tcp之间添加一层加密层(SSL层),这一层负责数据的加密和解密;

2 注意: 加密的部分其实只是在外网

  • 1 数据进入服务器后就会被解析为正常的数据,
  • 2 而在服务器内部(内网)可能需要经过很多服务跳转,

2 数据加签

1 数据加签就是由发送者产生一段无法伪造的一段数字串,来保证数据在传输过程中不被篡改
2 数据加签可以防止内网中数据被篡改

3 时间戳机制

在每次请求中加入当前的时间,服务器端会拿到当前时间和消息中的时间相减
  1 看看是否在一个固定的时间范围内比如5分钟内
  2 这样恶意请求的数据包是无法更改里面时间的,所以5分钟后就视为非法请求了;

4 AppId机制

   相当于用户名和密码的验证机制, 这里使用的是appid+秘钥

5 限流机制

1 本来就是真实的用户,并且开通了appid,但是出现频繁调用接口的情况
2 这种情况需要给相关appid限流处理

6 黑名单机制

1 如果此appid进行过很多非法操作
2 或者说专门有一个中黑系统,经过分析之后直接将此appid列入黑名单,所有请求直接返回错误码

7 数据合法性校验

  1 这个可以说是每个系统都会有的处理机制,只有在数据是合法的情况下才会进行数据处理;每个系统都有自己的验证规则,当然也可能有一些常规性的规则,比如身份证长度和组成,电话号码长度和组成等等
  2 各个系统都有自己的处理数据的格式

 

Spring Boot启动的时候会通过 @EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类,并对其进行加载,而这些自动配置类都是以AutoConfiguration结尾来命名的,它实际上就是一个JavaConfig形式的Spring容器配置类,它能通过以Properties结尾命名的类中取得在全局配置文件中配置的属性如:server.port,而XxxxProperties类是通过 @ConfigurationProperties注解与全局配置文件中对应的属性进行绑定的。

posted @ 2021-07-20 10:34  mini9264  阅读(161)  评论(0编辑  收藏  举报