Java经典面试题最全汇总208道(四)

Java
261
0
0
2023-07-23
标签   Java面试
目录
  • 前言 
  • 126、Spring 框架中的单例 Beans 是线程安全的么?
  • 127、请解释 Spring Bean 的自动装配?
  • 129、什么是 Spring Batch?
  • 130、spring mvc 和 struts 的区别是什么?
  • 131、请举例解释@Required 注解?
  • 132、Spring常用注解
  • 133、项目中是如何实现权限验证的,权限验证需要几张表
  • 134、谈谈controller,接口调用的路径问题
  • 135、如何防止表单重复提交
  • 136、Spring中都应用了哪些设计模式
  • 137、请举例说明如何在 Spring 中注入一个 Java Collection?
  • 138、mybatis 中 #{}和 ${}的区别是什么?
  • 139、mybatis 是否支持延迟加载?延迟加载的原理是什么?
  • 140、说一下 mybatis 的一级缓存和二级缓存?
  • 141、mybatis 有哪些执行器(Executor)?
  • 142、mybatis 和 hibernate 的区别有哪些?
  • 143、myBatis查询多个id、myBatis常用属性
  • 144、mybatis一级缓存、二级缓存
  • 145、mybatis如何防止sql注入
  • 146、为什么要使用 hibernate?
  • 146、hibernate 中如何在控制台查看打印的 sql 语句?
  • 148、hibernate 实体类可以被定义为 final 吗?
  • 149、在 hibernate 中使用 Integer 和 int 做映射有什么区别?
  • 150、什么是 Spring Boot?Spring Boot 有哪些优点?
  • 151、Spring Boot 中的监视器是什么?

前言 

短时间提升自己最快的手段就是背面试题,最近总结了Java常用的面试题,分享给大家,希望大家都能圆梦大厂,加油,我命由我不由天。

126、Spring 框架中的单例 Beans 是线程安全的么?

Spring框架并没有对单例bean进行任何多线程的封装处理。

关于单例bean的线程安全和并发问题需要开发者自行去搞定。

但实际上,大部分的Spring bean并没有可变的状态,所以在某种程度上说Spring的单例bean时线程安全的。

如果你的bean有多种状态的话,比如view model,就需要自行保证线程安全啦。

最浅显的解决办法就是将多态bean的作用域由singleton变更为prototype。

127、请解释 Spring Bean 的自动装配?

Spring支持IOC,自动装配不用类实例化,直接从bean容器中取。

1、配置在xml中

<bean id="employeeDAO" class="com.guor.EmployeeDAOImpl" autowire="byName" />

2、@Autowired自动装配

128、如何开启基于注解的自动装配?

要使用 @Autowired,需要注册 AutowiredAnnotationBeanPostProcessor,可以有以下两种方式来实现:

引入配置文件中的<bean>下引入 <context:annotation-config>

<beans>
    <context:annotation-config />
</beans>

在bean配置文件中直接引入AutowiredAnnotationBeanPostProcessor

<beans>
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>

129、什么是 Spring Batch?

1、什么是spring batch?

spring batch是一个轻量级的、完善的批处理框架,它主要的目的在于帮助企业建立健壮、高效的批处理应用。

spring batch是Spring的一个子项目,它使用java语言并基于spring框架作为基础开发,使得已经使用Spring框架的开发者或者是企业可以更加容易访问和利用企业服务。

spring batch提供了大量可重用的组件,包括了日志、追踪、事务、任务作业统计、任务重启、跳过、重复、资源管理。

对大数据量和高性能的批处理任务,spring batch同样提供了高级功能和特性来支持。

例如:分区功能、远程功能。

总的来说,spring batch可以支持简单的、复杂的和大数据量的批处理作业。

2、spring batch业务场景

周期性的提交批处理

把一个任务并行处理

消息驱动应用分级处理

大规模并行批处理

手工或调度使任务失败之后重新启动

有依赖步骤的顺序执行(使用工作流驱动扩展)

处理时跳过部分记录

成批事务:为小批量的或有的存储过程/脚本的场景使用

130、spring mvc 和 struts 的区别是什么?

1、拦截机制的不同

Struts2是类级别的拦截,每次请求就会创建一个Action,和Spring整合时Struts2的ActionBean注入作用域是原型模式prototype,然后通过setter,getter吧request数据注入到属性。

Struts2中,一个Action对应一个request,response上下文,在接收参数时,可以通过属性接收,这说明属性参数是让多个方法共享的。

Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了,只能设计为多例。

SpringMVC是方法级别的拦截,一个方法对应一个Request上下文,所以方法直接基本上是独立的,独享request,response数据。

而每个方法同时又何一个url对应,参数的传递是直接注入到方法中的,是方法所独有的。

处理结果通过ModeMap返回给框架。在Spring整合时,SpringMVC的Controller Bean默认单例模式Singleton,所以默认对所有的请求,只会创建一个Controller,有应为没有共享的属性,所以是线程安全的,如果要改变默认的作用域,需要添加@Scope注解修改。

Struts2有自己的拦截Interceptor机制,SpringMVC这是用的是独立的Aop方式,这样导致Struts2的配置文件量还是比SpringMVC大。

2、底层框架的不同

Struts2采用Filter(StrutsPrepareAndExecuteFilter)实现,SpringMVC(DispatcherServlet)则采用Servlet实现。Filter在容器启动之后即初始化;服务停止以后坠毁,晚于Servlet。Servlet在是在调用时初始化,先于Filter调用,服务停止后销毁。

3、性能方面

Struts2是类级别的拦截,每次请求对应实例一个新的Action,需要加载所有的属性值注入,SpringMVC实现了零配置,由于SpringMVC基于方法的拦截,有加载一次单例模式bean注入。

所以,SpringMVC开发效率和性能高于Struts2。

4、配置方面

spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高。

131、请举例解释@Required 注解?

@Required注解应用于bean属性的setter方法,它表明影响的bean属性在配置时必须放在XML配置文件中。

请举例说明@Qualifier 注解?

如果在xml中定义了一种类型的多个bean,同时在java注解中又想把其中一个bean对象作为属性,那么此时可以使用@Qualifier加@Autowired来达到这一目的

若不加@Qualifier这个注解,在运行时会出现“ No qualifying bean of type [com.tutorialspoint.Student] is defined: expected single matching bean but found 2: student1,student2”这个异常。

132、Spring常用注解

Spring常用注解(绝对经典)

133、项目中是如何实现权限验证的,权限验证需要几张表

通过了解,现在最普遍的权限管理模型就是RBAC(Role-Based Access Control)。

1、权限控制分类

菜单功能

url控制(控制访问不同的控制器)

2、RBAC的优缺点

(1)优点

简化了用户和权限的关系

易扩展、易维护

(2)缺点

RBAC模型没有提供操作顺序的控制机制,这一缺陷使得RBAC模型很难适应哪些对操作次序有严格要求的系统。

3、RBAC支持的安全原则

(1)最小权限原则

RBAC可以将角色配置成其完成任务所需的最小权限集合。

(2)责任分离原则

可以通过调用相互独立互斥的角色来共同完成敏感的任务,例如要求一个记账员和财务管理员共同参与统一过账操作。

(3)数据抽象原则

可以通过权限的抽象来体现,例如财务操作用借款、存款等抽象权限,而不是使用典型的读写权限。

4、远古时代的权限控制

当时还没有RBAC,也没有这个概念,就是一堆程序员在那鼓捣,觉得登录这块该做点什么。

1、新建一个用户,对这个用户进行赋予权限。
2、但是一旦用户多了,权限复杂了,这工作量也是蛮大的。

5、RBAC

RBAC 1.0

直接上图,一目了然,当程序不是很复杂的时候,RBAC就是这样设计的,我们公司的权限验证模块就是这样设计的。

简简单单,五张表,解

RBAC 2.0

基于RBAC 1.0模型的基础上,进行了角色的访问控制

RBAC2中的一个基本限制是互斥角色的限制,互斥角色是指各自权限可以互相制约的两个角色。

对于这类角色一个用户在某一次活动中只能被分配其中的一个角色,不能同时获得两个角色的使用权。

该模型有以下几种约束

  • 互斥角色 :同一用户只能分配到一组互斥角色集合中至多一个角色,支持责任分离的原则。

互斥角色是指各自权限互相制约的两个角色。

对于这类角色一个用户在某一次活动中只能被分配其中的一个角色,不能同时获得两个角色的使用权。

常举的例子:在审计活动中,一个角色不能同时被指派给会计角色和审计员角色。

  • 基数约束 :一个角色被分配的用户数量受限;一个用户可拥有的角色数目受限;同样一个角色对应的访问权限数目也应受限,以控制高级权限在系统中的分配。
  • 先决条件角色 :可以分配角色给用户仅当该用户已经是另一角色的成员;对应的可以分配访问权限给角色,仅当该角色已经拥有另一种访问权限。

指要想获得较高的权限,要首先拥有低一级的权限。

  • 运行时互斥 :例如,允许一个用户具有两个角色的成员资格,但在运行中不可同时激活这两个角色。

6、rbac的实现理论分析

进入登录页面;

拿到通过post传过来的用户名和密码;

使用orm进行过滤查找;

如果能找到值,则说明登录成功:登录成功后调用rbac初始化函数,初始化函数的主要功能是获取用户的权限和菜单保存到session中,并跳转客户列表页面;

如果失败,页面进行友好提示;

7、url权限控制关键代码

134、谈谈controller,接口调用的路径问题

1、Spring MVC如何匹配请求路径

@RequestMapping是用来映射请求的,比如get请求、post请求、或者REST风格与非REST风格的。

该注解可以用在类上或方法上,如果用在类上,表示是该类中所有方法的父路径。

@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
    @RequestMapping("/testRequestMapping")
    public String testRequestMapping(){
        System.out.println("testRequestMapping");
        return SUCCESS;
    }
}

在类上还添加了一个@Controller注解,该注解在SpringMVC中负责处理由DispatcherServlet分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个model,然后再把该model返回给对应的view进行展示。

我们可以通过“springmvc/testRequestMapping”这个路径来定位到testRequestMapping这个方法,然后执行方法内的方法体。

RequestMapping可以实现模糊匹配路径,比如:

  1. ?表示一个字符;
  2. *表示任意字符;
  3. **匹配多层路径;

/springmvc/**/testRequestMapping 就可以匹配/springmvc/stu/getStudentInfo/testRequestMapping 这样的路径了。

2、SpringMVC如何获取请求的参数

(1)@PathVariable

该注解用来映射请求URL中绑定的占位符。通过@PathVariable可以将URL中占位符的参数绑定到controller处理方法的入参中。

@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable(value="id") Integer id){
    System.out.println("testPathVariable:" + id);
    return SUCCESS;
}

在index.jsp中我们添加一条连接,用来触发一个请求:

<a href="springmvc/testPathVariable/" rel="external nofollow" >testPathVariable</a>

(2) @RequestParam

该注解也是用来获取请求参数的,那么该注解和@PathVariable有什么不同呢?

@RequestMapping(value="/testRequestParam")
public String testRequestParam(@RequestParam(value="username") String username, @RequestParam(value="age", required=false, defaultValue="") int age){
    System.out.println("testRequestParam" + " username:" + username + " age:" +age);
    return SUCCESS;
}

在index.jsp添加超链接标签

<a href="springmvc/testRequestParam?username=jackie&age=" rel="external nofollow" >testRequestParam</a>

3、REST风格的请求

在SpringMVC中业务最多的应该是CRUD了

@RequestMapping(value="/testRest/{id}", method=RequestMethod.PUT)
public String testRestPut(@PathVariable(value="id") Integer id){
    System.out.println("test put:" + id);
    return SUCCESS;
}
     
@RequestMapping(value="/testRest/{id}", method=RequestMethod.DELETE)
public String testRestDelete(@PathVariable(value="id") Integer id){
    System.out.println("test delete:" + id);
    return SUCCESS;
}
     
@RequestMapping(value="/testRest", method=RequestMethod.POST)
public String testRest(){
    System.out.println("test post");
    return SUCCESS;
}
     
@RequestMapping(value="/testRest/{id}", method=RequestMethod.GET)
public String testRest(@PathVariable(value="id") Integer id){
    System.out.println("test get:" + id);
    return SUCCESS;
}

135、如何防止表单重复提交

1、通过JavaScript屏蔽提交按钮(不推荐)

2、给数据库增加唯一键约束(简单粗暴)

3、利用Session防止表单重复提交(推荐)

4、使用AOP自定义切入实现

136、Spring中都应用了哪些设计模式

1、简单工厂模式

简单工厂模式的本质就是一个工厂类根据传入的参数,动态的决定实例化哪个类。

Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得bean对象。

2、工厂方法模式

应用程序将对象的创建及初始化职责交给工厂对象,工厂Bean。

定义工厂方法,然后通过config.xml配置文件,将其纳入Spring容器来管理,需要通过factory-method指定静态方法名称。

3、单例模式

Spring用的是双重判断加锁的单例模式,通过getSingleton方法从singletonObjects中获取bean。

 /**
 * Return the (raw) singleton object registered under the given name.
 * <p>Checks already instantiated singletons and also allows for an early
 * reference to a currently created singleton (resolving a circular reference).
 * @param beanName the name of the bean to look for
 * @param allowEarlyReference whether early references should be created or not
 * @return the registered singleton object, or {@code null} if none found
 */
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

4、代理模式

Spring的AOP中,使用的Advice(通知)来增强被代理类的功能。

Spring实现AOP功能的原理就是代理模式(① JDK动态代理,② CGLIB字节码生成技术代理。)对类进行方法级别的切面增强。

5、装饰器模式

装饰器模式:动态的给一个对象添加一些额外的功能。

Spring的ApplicationContext中配置所有的DataSource。

这些DataSource可能是不同的数据库,然后SessionFactory根据用户的每次请求,将DataSource设置成不同的数据源,以达到切换数据源的目的。

在Spring中有两种表现:

一种是类名中含有Wrapper,另一种是类名中含有Decorator。

6、观察者模式

定义对象间的一对多的关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

Spring中观察者模式一般用在listener的实现。

7、策略模式

策略模式是行为性模式,调用不同的方法,适应行为的变化 ,强调父类的调用子类的特性 。

getHandler是HandlerMapping接口中的唯一方法,用于根据请求找到匹配的处理器。

8、模板方法模式

Spring JdbcTemplate的query方法总体结构是一个模板方法+回调函数,query方法中调用的execute()是一个模板方法,而预期的回调doInStatement(Statement state)方法也是一个模板方法。

137、请举例说明如何在 Spring 中注入一个 Java Collection?

Spring注入有四种方式,

  1. set注入;
  2. 构造器注入;
  3. 基于注解的注入;
  4. xml配置文件注入;

想要注入java collection,就是注入集合类:

  1. listsetmapprops:该标签支持注入键和值都是字符串类型的键值对。
  2. list和set都使用value标签;
  3. map使用entry标签;
  4. props使用prop标签;

138、mybatis 中 #{}和 ${}的区别是什么?

  1. #{}带引号,${}不带引号;
  2. #{}可以防止SQL注入;
  3. ${}常用于数据库表名、order by子句;
  4. 一般能用#{}就不要使用${};

139、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(),这就是延迟加载的原理。

140、说一下 mybatis 的一级缓存和二级缓存?

一级缓存是session级别的缓存,默认开启,当查询一次数据库时,对查询结果进行缓存,如果之后的查询在一级缓存中存在,则无需再访问数据库;

二级缓存是sessionFactory级别的缓存,需要配置才会开启。当进行sql语句查询时,先查看一级缓存,如果不存在,访问二级缓存,降低数据库访问压力。

141、mybatis 有哪些执行器(Executor)?

1、mybatis有三种基本的Executor执行器:

(1)、SimpleExecutor

每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

(2)、PauseExecutor

执行update或select,以sql做为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而且放置于Map内,供下一次使用。

简言之,就是重复使用Statement对象。

(3)、BatchExecutor

执行update,将所有sql通过addBatch()都添加到批处理中,等待统一执行executeBatch(),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。

与JDBC批处理相同。

2、作用范围:

Executor的这些特点,都严格限制在SqlSession生命周期范围内。

3、Mybatis中如何指定使用哪一种Executor执行器?

在mybatis的配置文件中,可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数。

142、mybatis 和 hibernate 的区别有哪些?

1、两者最大的区别

针对简单逻辑,都有对应的代码生成工具,可以生成简单基本的dao层方法;

针对高级查询,mybatis要手动编写sql语句和resultMap,而hibernate有良好的映射机制;

2、开发难度对比

hibernate > mybatis 

3、日志统计

hibernate有自己的日志统计功能,而mybatis需要借助log4j来记录日志。

4、数据库扩展比较

hibernate > mybatis 

5、缓存机制比较

因为hibernate对查询对象有良好的管理机制,用户无需关心sql,所以使用二级缓存如果出现脏数据,系统会报错。

而mybatis,如果不能获取最新数据,应该避免缓存的使用,脏数据的出现会给系统的正常运行带来很大的隐患。

6、如何选择

  • mybatis需要编写sql和映射规则,工作量大于hibernate;
  • mybatis支持的工具也有限,不能像hibernate那样有许多插件可以帮助生成映射代码和关联关系;
  • 对于性能要求不太苛刻的系统,比如管理系统、ERP等推荐hibernate;
  • 对于性能要求高、响应快、灵活的系统,比如电商系统,推荐使用mybatis;

143、myBatis查询多个id、myBatis常用属性

myBatis查询多个id(我居然回答用对象来传递...)

Page<UserPoJo> getUserListByIds(@Param("ids") List<Integer> ids);
<!--根据id列表批量查询user-->
<select id="getUserListByIds" resultType="com.guor.UserPoJo">
    select * from student
    where id in
    <foreach collection="ids" item="userid" open="(" close=")" separator=",">
        #{userid}
    </foreach>
</select>

144、mybatis一级缓存、二级缓存

1、一级缓存:指的是mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入sqlSession中,再次查询的时候,先去sqlSession中查询,有的话直接拿出,当sqlSession消失时,mybatis的一级缓存也就消失了,当调用sqlSession的修改、添加、删除、commit()、close()等方法时,会清空一级缓存。

2、二级缓存:指的是mybatis中的sqlSessionFactory对象的缓存,由同一个sqlSessionFactory对象创建的sqlSession共享其缓存,但是其中缓存的是数据而不是对象。

当命中二级缓存时,通过存储的数据构造成对象返回。查询数据的时候,查询的流程是二级缓存 > 一级缓存 > 数据库。

3、如果开启了二级缓存,sqlSession进行close()后,才会把sqlSession一级缓存中的数据添加到二级缓存中,为了将缓存数据取出执行反序列化,还需要将要缓存的pojo实现Serializable接口,因为二级缓存数据存储介质多种多样,不一定只存在内存中,也可能存在硬盘中。

4、mybatis框架主要是围绕sqlSessionFactory进行的,具体的步骤:

定义一个configuration对象,其中包含数据源、事务、mapper文件资源以及影响数据库行为属性设置settings。

  1. 通过配置对象,则可以创建一个sqlSessionFactoryBuilder对象。
  2. 通过sqlSessionFactoryBuilder获得sqlSessionFactory实例。
  3. 通过sqlSessionFactory实例创建qlSession实例,通过sqlSession对数据库进行操作。

5、代码实例

mybatis-config.xml

<?xml version=".0" encoding="UTF-8"?>  
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config.0//EN"  
"http://mybatis.org/dtd/mybatis--config.dtd">  
 
<configuration>   
    <!-- 加载类路径下的属性文件 -->  
    <properties resource="db.properties"/>  
 
    <!-- 设置类型别名 -->  
    <typeAliases>  
        <typeAlias type="cn.itcast.javaee.mybatis.app.Student" alias="student"/>  
    </typeAliases>  
 
    <!-- 设置一个默认的连接环境信息 -->  
    <environments default="mysql_developer">  
 
        <!-- 连接环境信息,取一个任意唯一的名字 -->  
        <environment id="mysql_developer">  
            <!-- mybatis使用jdbc事务管理方式 -->  
            <transactionManager type="jdbc"/>  
            <!-- mybatis使用连接池方式来获取连接 -->  
            <dataSource type="pooled">  
                <!-- 配置与数据库交互的个必要属性 -->  
                <property name="driver" value="${mysql.driver}"/>  
                <property name="url" value="${mysql.url}"/>  
                <property name="username" value="${mysql.username}"/>  
                <property name="password" value="${mysql.password}"/>  
            </dataSource>  
        </environment>  
 
        <!-- 连接环境信息,取一个任意唯一的名字 -->  
        <environment id="oracle_developer">  
            <!-- mybatis使用jdbc事务管理方式 -->  
            <transactionManager type="jdbc"/>  
            <!-- mybatis使用连接池方式来获取连接 -->  
            <dataSource type="pooled">  
                <!-- 配置与数据库交互的个必要属性 -->  
                <property name="driver" value="${oracle.driver}"/>  
                <property name="url" value="${oracle.url}"/>  
                <property name="username" value="${oracle.username}"/>  
                <property name="password" value="${oracle.password}"/>  
            </dataSource>  
        </environment>  
    </environments>  
 
    <!-- 加载映射文件-->  
    <mappers>  
        <mapper resource="cn/itcast/javaee/mybatis/app/StudentMapper.xml"/>  
    </mappers>  
 
</configuration>  
public class MyBatisTest {
 
    public static void main(String[] args) {
        try {
            //读取mybatis-config.xml文件
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
            //初始化mybatis,创建SqlSessionFactory类的实例
            SqlSessionFactory sqlSessionFactory =  new SqlSessionFactoryBuilder().build(resourceAsStream);
            //创建session实例
            SqlSession session = sqlSessionFactory.openSession();
            /*
             * 接下来在这里做很多事情,到目前为止,目的已经达到得到了SqlSession对象.通过调用SqlSession里面的方法,
             * 可以测试MyBatis和Dao层接口方法之间的正确性,当然也可以做别的很多事情,在这里就不列举了
             */
            //插入数据
            User user = new User();
            user.setC_password("");
            user.setC_username("");
            user.setC_salt("");
            //第一个参数为方法的完全限定名:位置信息+映射文件当中的id
            session.insert("com.cn.dao.UserMapping.insertUserInformation", user);
            //提交事务
            session.commit();
            //关闭session
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

145、mybatis如何防止sql注入

注意:但凡是sql注入漏洞的程序,都是因为程序要接受来自客户端用户输入的变量或URL传递的参数,并且这个变量或参数是组成sql语句的一部分,对于用户输入的内容或传递的参数,我们应该要时刻保持警惕,这是安全领域里的【外部数据不可信任】的原则,纵观web安全领域的各种攻击方式,大多数都是因为开发者违反了这个原则而导致的,所以自然能想到,就是变量的检测、过滤、验证下手,确保变量是开发者所预想的。

1、检查变量数据类型和格式

数据类型检查,sql执行前,要进行数据类型检查,如果是邮箱,参数就必须是邮箱的格式,如果是日期,就必须是日期格式;

只要是有固定格式的变量,在SQL语句执行前,应该严格按照固定格式去检查,确保变量是我们预想的格式,这样很大程度上可以避免SQL注入攻击。

如果上述例子中id是int型的,效果会怎样呢?无法注入,因为输入注入参数会失败。

比如上述中的name字段,我们应该在用户注册的时候,就确定一个用户名规则

比如5-20个字符,只能由大小写字母、数字以及汉字组成,不包含特殊字符。

此时我们应该有一个函数来完成统一的用户名检查。

不过,仍然有很多场景并不能用到这个方法,比如写博客,评论系统,弹幕系统,必须允许用户可以提交任意形式的字符才行,否则用户体验感太差了。

2、过滤特殊符号

3、绑定变量,使用预编译语句

146、为什么要使用 hibernate?

  1. hibernate对jdbc进行了封装,简化了JDBC的重复性代码;
  2. hibernate对dao有一个封装类hibernateTemplate,可以继承它,实现简单的CRUD接口。
  3. hibernate使用注解和配置文件,可以对实体类和映射文件进行映射;
  4. hibernate有事务管理机制,保证了数据的安全性;
  5. hibernate有一级缓存和二级缓存;

146、hibernate 中如何在控制台查看打印的 sql 语句?

public class MyBatisTest {
 
    public static void main(String[] args) {
        try {
            //读取mybatis-config.xml文件
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
            //初始化mybatis,创建SqlSessionFactory类的实例
            SqlSessionFactory sqlSessionFactory =  new SqlSessionFactoryBuilder().build(resourceAsStream);
            //创建session实例
            SqlSession session = sqlSessionFactory.openSession();
            /*
             * 接下来在这里做很多事情,到目前为止,目的已经达到得到了SqlSession对象.通过调用SqlSession里面的方法,
             * 可以测试MyBatis和Dao层接口方法之间的正确性,当然也可以做别的很多事情,在这里就不列举了
             */
            //插入数据
            User user = new User();
            user.setC_password("");
            user.setC_username("");
            user.setC_salt("");
            //第一个参数为方法的完全限定名:位置信息+映射文件当中的id
            session.insert("com.cn.dao.UserMapping.insertUserInformation", user);
            //提交事务
            session.commit();
            //关闭session
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

147、hibernate 有几种查询方式?

1、导航对象图查询:根据已加载的对象,导航到其他对象。

例如,对于已经加载的Customer对象,调用它的getOrders().iterator()方法就可以导航到所有关联的Order对象,假如在关联级别使用了延迟加载检索策略

那么首次执行此方法时,hibernate会从数据库中加载关联的Order对象,否则就从缓存中获得Order对象。

2、OID方式:按照对象的OID来检索对象

Session的get()和load()方法提供了这种功能,如果在应用程序中先知道了OID,就可以使用这种方式检索对象。

get()和load()的用法完全一样,都需要两个参数,一个是持久化对象类名class,一个是行号OID,返回固定的某一行的数据,但是需要注意的是,当输入的OID不存在时,get()会返回一个空对象,load()则直接报错。

3、HQL检索方式:(hibernate query language)

使用面向对象的HQL查询语言,session的find()方法用于执行HQL查询语句。

此外,hibernate还提供了query接口,它是hibernate提供的专门的HQL查询接口,能够执行各种复杂的HQL查询语句。

它具备以下功能:

  1. 在查询语句中设定各种查询条件;
  2. 支持投影查询,即仅检索出对象的部分属性;
  3. 支持分页查询;
  4. 支持连接查询;
  5. 支持分组查询;
  6. 提供内置函数;
  7. 能够调用用户自定义的SQL函数;
  8. 支持子查询;
  9. 支持动态绑定参数;

例如:

Query query = session.createQuery(“from UserPo”);

获得一个query对象,注意参数字符串中不是一个SQL语句,from后面的是持久化对象名称;

List list = query.list();

就可以获取数据库中对应表的数据集合。

4、QBC检索方式:Query By Criteria的API来检索对象

这种API封装了基于字符串形式的查询语句,提供了更加面向对象的接口。

例:Criteria criteria = session.createCriteria(UserPo.class);

创建一个Criteria对象,参数是所关联的持久化对象,criteria.add(Restrictions.ge("id",2));将查询条件加入对象中,后面的操作就和Query对象一样了。

5、本地SQL

使用本地数据库的SQL查询语句,hibernate会负责把检索到的JDBC ResultSet结果映射为持久化对象图。

148、hibernate 实体类可以被定义为 final 吗?

可以将hibernate的实体类定义为final,但这种做法不好。

因为hibernate会使用代理模式在延迟关联的情况下提高性能,如果你把实体类定义成final类之后,因为Java不允许对final类进行扩展

所以hibernate就无法再使用代理了,如此一来就限制了使用可以提升性能的手段。

不过,如果你的持久化类实现了一个接口,而且在该接口中声明了所有定义于实体类中的所有public的方法的话,就能避免出现前面所说的不利后果。

149、在 hibernate 中使用 Integer 和 int 做映射有什么区别?

hibernate是面向对象的ORM,所以一般定义成封装类型,要看数据库中的定义,如果数据库中有对应字段存在null值,就要定义Integer。

也可以定义基本类型,在配置文件中写清楚即可。

150、什么是 Spring Boot?Spring Boot 有哪些优点?

1、Spring Boot简介

基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化spring应用的整个搭建和开发过程。

另外SpringBoot通过集成大量的框架使得依赖包的版本冲突、引用的不稳定性得到了解决。

2、Spring Boot 有哪些优点?

  1. 快速构建项目,可以选一些必要的组件;
  2. 对主流框架的无配置集成;
  3. 内嵌Tomcat容器,项目可独立运行;
  4. 删除了繁琐的xml配置文件;
  5. 极大地提高了开发和部署效率;
  6. 提供starter,简化maven配置;

3、SpringBoot有哪些缺点?

版本迭代速度快,一些模块改动很大;由于无须配置,报错时很难定位;

151、Spring Boot 中的监视器是什么?

监听器也叫listener,是servlet的监听器,可以用于监听web应用程序中某些对象的创建、销毁、增加、修改、删除等动作的发生,然后做出相应的响应处理。

当范围对象的状态发生变化时,服务器自动调用监听器对象中的方法,常用于系统加载时进行信息初始化,统计在线人数和在线用户,统计网站的访问量。

配置监听器的方法:

  1. 通过@Component把监听器加入Spring容器中管理;
  2. 在application.properties中添加context.listener.classes配置;
  3. 在方法上加@EventListener注解;

系列文章:

Java经典面试题最全汇总208道(一)

Java经典面试题最全汇总208道(二)

Java经典面试题最全汇总208道(三)

Java经典面试题最全汇总208道(四)

Java经典面试题最全汇总208道(五)

Java经典面试题最全汇总208道(六)