- 一、什么是SpringMVC
- 二、SpringMVC的工作原理
- 三、SpringMVC 常用的注解有哪些?
- 四、Controller和RestController的区别?
- 五、Mybaties中的#和{}的区别
- 六、当实体类中的属性名和表中的字段名不一样,怎么办
- 七、模糊查询like语句应该怎么写
- 八、MyBatis实现一对一有几种方式?具体怎么操作的?
- 九、MyBatis实现一对多有几种方式,怎么操作的?
- 十、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么
- 十一、什么是MyBatis的接口绑定?有哪些实现方式?
- 十二、使用MyBatis的mapper接口调用时有哪些要求?
- 十三、Mybaties中的一级缓存和二级缓存?
- 十三、SQL注入问题
一、什么是SpringMVC
SpringMVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model、View、Controller分离,将Web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
二、SpringMVC的工作原理
- 用户发送请求至前端控制器DispatcherServlet;
- DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handler;
- 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
- DispatcherServlet 调用 HandlerAdapter处理器适配器;
- HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
- Handler执行完成返回ModelAndView;
- HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
- DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
- ViewResolver解析后返回具体View;
- DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
- DispatcherServlet响应用户。
三、SpringMVC 常用的注解有哪些?
- RequestMapping:用于处理请求url映射的注解,可用于类或方法上;用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
- RequestBody:注解实现接受http请求的json数据,将json转换为java对象。
- ResponseBody:注解实现将controller方法返回对象转换为json对象响应给客户。
四、Controller和RestController的区别?
都是用来表示Spring某个类是否可以接受HTTP请求RestController注解相当于RequestBody+Controller合一起的作用。
- 如果只是使用RestController注解Controller类,则Controller类中过的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是return里的内容。
- 如果要返回指定页面,则需要使用Controller配合视图解析器 InternalResourceViewResolver才行;如果需要返回JSON、XML内容到页面,则需要在对应的方法上加上ResponseBody注解。
五、Mybaties中的#和{}的区别
Mybatis的SQL xml映射文件中,有关参数传递的方法有两种,分别是#{}和${},这两种方式之间存在一定的差异。
动态SQL是Mybatis的请打特性之一,也是它由于其他ORM框架的一个重要原因。Mybatis在对sql语句进行预编译之前,会对sql进行动态解析,解析为一个BoundSql对象,也是在此处对动态SQL进行处理的。在动态SQ解析阶段,#{}和${}会有不同的表现。
BoundSql更像一个中转站,mybatis在执行一次CRUD操作过程中产生的中间数据的集中点。
#{}在动态解析的时候,会解析成一个参数标记符。
${}在动态解析的时候,会将我们传入的参数当做String字符串填充到我们的语句中。
所以,${}变量的替换阶段在动态SQL解析阶段,而#{}变量的替换的替换是在DBMS中。
#{}变量的替换的替换是在DBMS,会导致Mybatis创建PreparedStatement参数并安全地设置参数,这样就避免了sql注入的问题。
- #{}方式能够很大程度上防止sql注入。${}方式无法防止Sql注入。
- ${}方式一般用于传入数据库对象,例如传入表名。
SQL注入其实就是恶意用户通过在表单中填写包含SQL关键字的数据来使数据库执行非常规代码的过程。
六、当实体类中的属性名和表中的字段名不一样,怎么办
- 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
- 通过来映射字段名和实体类属性名的一一对应的关系。
七、模糊查询like语句应该怎么写
- 在Java代码中添加sql通配符。
- 在sql语句中拼接通配符,会引起sql注入。
八、MyBatis实现一对一有几种方式?具体怎么操作的?
- 有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
- 嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。
九、MyBatis实现一对多有几种方式,怎么操作的?
有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成;嵌套查询是先查一个表,根据这个表里面的 结果的外键id,去再另外一个表里面查询数据,也是通过配置collection,但另外一个表的查询通过select节点配置。
十、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,支持延迟加载的原理都是一样的。
十一、什么是MyBatis的接口绑定?有哪些实现方式?
接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。
接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多。
十二、使用MyBatis的mapper接口调用时有哪些要求?
① Mapper接口方法名和mapper.xml中定义的每个sql的id相同;
② Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;
③ Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;
④ Mapper.xml文件中的namespace即是mapper接口的类路径。
十三、Mybaties中的一级缓存和二级缓存?
缓存:是指将程序或系统经常调用的对象(临时数据)存在内存中,一遍其使用时可以快速调用,不必在去创建新的重复的实例。
- 一级缓存
SqlSession是Mybatis最重要的构建之一,可以简单的认为Mybatis一系列的配置的目的是生成类似JDBC生成的Connection对象的SqlSession,这样才能与数据库开启“沟通”,通过SqlSession可以实现增删改查。
它指的是Mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入到SqlSession为我们提供的一块区域中,该区域的结构是一个Map,在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库中进行查询,并写到缓存中。当执行SQL查询中间发生了增删改的操作,Mybatis会把SqlSession的缓存清空。
一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION,不想使用一级缓存,可以吧以及缓存的范围指定为STATEMENT。
一级缓存实际上就是使用PerpetualCache维护的,那么PerpetualCache是怎样实现的呢?
PerpetualCache实现原理其实很简单,其内部就是通过一个简单的HashMap<k,v> 来实现的,没有其他的任何限制。
- 二级缓存
它指的是Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessionFactory对象创建的SqlSession共享其内存,但是其中缓存的是数据而不是对象,所以从二级缓存再次查询出得结果的对象与第一次存入的对象是不一样。
总结
一级缓存:SqlSession级别的缓存,缓存的是对象,当发生修改、更新等操作一级缓存会清空。
二级缓存:SqlSessionFactory级别的缓存,缓存的是数据,同一个SqlSessionFactory产生的SqlSession都共享一个二级缓存,当命中二级缓存时,通过存户的数据构造对象返回。
==查询数据的流程:二级缓存>一级缓存>数据库
十三、SQL注入问题
SQL注入指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击所要的操作,其主要原因是程序没有细致的过滤用户输入的数据,致使非法数据侵入系统。
- 数字型注入
假设存在一条 URL 为:HTTP://www.aaa.com/test.php?id=1
可以对后台的 SQL 语句猜测为:
SELECT * FROM table WHERE id=1
- 字符型注入
当输入参数为字符串时,则可能存在字符型注入漏洞。数字型与字符型注入最大的区别在于:数字型不需要单引号闭合,而字符型一般需要使用单引号来闭合。
字符型注入最关键的是如何闭合 SQL 语句以及注释多余的代码。
假设后台的 SQL 语句如下:
SELECT * FROM table WHERE username = ‘admin’
- 其他类型
其实我觉得 SQL 注入只有两种类型:数字型与字符型。很多人可能会说还有如:Cookie 注入、POST 注入、延时注入等。
的确如此,但这些类型的注入归根结底也是数字型和字符型注入的不同展现形式或者注入的位置不同罢了。
以下是一些常见的注入叫法:
- POST注入:注入字段在 POST 数据中
- Cookie注入:注入字段在 Cookie 数据中
- 延时注入:使用数据库延时特性注入
- 搜索注入:注入处为搜索的地方
- base64注入:注入字符串需要经过 base64 加密