作者:Aristochi
更新时间: 2020/01/11 12:43
参考书目:Java EE框架整合开发入门到实战——Spring+Spring MVC+MyBatis
部分内容引自https://www.w3cschool.cn/wkspring/dcu91icn.html
一个图书电商的SSM项目地址https://github.com/Aristochi/Bookstore
图片没有上传成功,可以查看下方链接
文章完整链接有道云笔记·Javaweb SSM框架知识点整理
复习提纲
第一部分 Spring
第1章 Spring入门
Spring核心容器中有哪些模块?P3
① Spring-core
spring-core模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。
② Spring-beans
spring-beans 模块提供 BeanFactory,工厂模式的经典实现,Spring将管理对象称为Bean
③ Spring-context
建立在core和 beans 模块的基础上,提供一个框架式的对象访问方式,是访问定义和配置的任何对象的媒介。ApplicationContext接口是Context模块的焦点
④ Spring-context-support
spring-context-support支持整合第三方库到Spring应用程序上下文,比如缓存(EhCache, Guava, JCache)、任务调度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。
⑤ Spring-expression
spring-expression模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是JSP2.1规范中定义的统一表达式语言的扩展,支持set和get属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从Spring IoC容器检索对象,还支持列表的投影、选择以及聚合等。
完整依赖关系如下图:
第二章 SpringIOC
2.1 SpringIOC的基本概念
1. Spring框架中,什么是控制反转?什么是依赖注入?有何区别?
1)控制反转:当某个对象(调用者)需要另外一个对象(被调用者)时,传统的编程模式下,调用者通常会new一个被调用者对象。在Spring中,对象不再由调用者创建,而是由Spring容器来创建。Spring负责控制程序之间的依赖关系,而不是由调用者控制,这样,控制权由调用者转移到Spring容器,控制权发生的反转,这就是Spring的控制反转。
2)依赖注入:从应用程序角度来看,调用者依赖Spring容器创建并注入它所需要的被调用者对象,这就是依赖注入。
3)区别:依赖反转和依赖注入其实是对同一件事情在不同角度的不同表述,依赖注入是从应用程序的角度在描述,而控制反转是从容器的角度在描述。
2.2 Spring IoC容器
1.Spring IoC容器的设计主要是基于BeanFactory和ApplicationContext两个接口
2. 创建ApplicationContext接口实例通常有三种方法:
1) 通过ClassPathXmlApplicationContext创建
2) 通过FileSystemXmlApplicationContext创建
3) 通过web服务器实例化ApplicationContext容器
2.3 依赖注入的类型
依赖注入的类型包括:使用构造方法注入,使用属性的setter方法注入
第3章Spring Bean
3.2 Bean的实例化:构造方法实例化,静态工厂实例化,实例工厂实例化
1. Spring如何创建对象,对象是如何存储的,用户是如何获取对象的?
1) Spring容器启动时,首先会加载Spring的核心配置文件,Spring器逐行进行解析xml配置文件
2) 当解析到bean标签时开始创建对象,根据class属性中的数据通过反射机制创建对象。
3) 将创建好的对象存入Spring所维护的Map中,key就是bean中的ID,value就是生成的对象。
4) 用户传入key,通过key来获取Map中的value(对象)
3.3 Bean的作用域
singleton(默认)、prototype、request、session、application
3.5 Bean的装配方式:
基于XML的装配;基于注解的装配; 基于Java的装配
Spring框架常用的注解 P34-35
① @Component(类注解)
该注解是一个泛化的概念,仅仅表示一个组件对象(Bean),可以作用在任何层次上。
② @Repository(DAO层)
该注解将数据访问层(DAO)的类标识为Bean,即注解数据访问层Bean,其功能与@Component相同
③ @Service(Service层)
该注解用于标注一个业务逻辑组件类(Service层),其功能与@Component相同
④ @Controller(Controller层)
该注解用于标识一个控制器组件类(Spring MVC的controller),其功能与@Component相同
⑤ @Autowired
该注解可以对类成员变量、方法及构造方法进行标注,完成自动装配的工作。通过使用@Autowired来消除setter和getter方法。默认按照Bean的类型进行装配
⑥@Resource
该注解与@Autowired的功能一样,区别在于该注解默认是按照名称来装配注入的,只有当找不到与名称匹配的Bean才会按照类型来装配注入。
Spring注解中@Autowired和@Resource的区别
1)@Autowired默认按类型装配依赖对象,默认情况下要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如果想按名称装配,可以结合@Qualifier注解一起使用。
2) @Resource注解有两个属性:name和type。name属性指定Bean实例名称,则按照名称来装配注入;type属性指定Bean类型,则按照Bean的类型进行装配。
第四章 Spring AOP
一、Spring AOP的基本概念,理解AOP的术语(P41)理解
(补充说明)切面(Aspect)是指封装横切到系统功能(如事务处理)的类。
连接点(Joint Point)和切入点(Point cut)是什么? 4
1)连接点是程序执行的一个点。例如,一个方法的执行或者一个异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法执行。
2)切入点(Pointcut):匹配连接点的断言或者表达式。通知和一个切入点表达式关联,并在满足这个切入点表达式的连接点上运行。
二、动态代理:JDK动态代理(默认)、Cglib动态代理
比较JDK动态代理和Cglib动态代理
答:在AOP的源码中用到了两种动态代理来实现拦截切入功能:JDK动态代理和Cglib动态代理。两种方法同时存在,各有优劣。
1) JDK动态代理是由java内部的反射机制来实现,反射机制在生成类的过程中比较高效;而Cglib动态代理是通过继承来实现的,Cglib在生成类之后的相关执行过程中比较高效。
2) 如果目标对象有接口则采用JDK动态代理,如果目标对象没有接口采用Cglib动态代理,Cglib动态代理是备用方案。
3) 对接口创建代理优于对类创建代理,因为更加松耦合,所以Spring默认是使用JDK动态代理。
三、基于代理类的AOP实现
通知类型P48
(来自百度的解释)
前置通知在一个方法执行之前,执行通知。
后置通知在一个方法执行之后,不考虑其结果,执行通知。
返回后通知在一个方法执行之后,只有在方法成功完成时,才能执行通知。
抛出异常后通知在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
环绕通知在建议方法调用之前和之后,执行通知。
(课本内容)
>>org.aopalliance.intercept.MethodInterceptor(环绕通知):
在目标方法执行前后实施增强,可以应用于日志记录、事务管理等功能。
>>org.springframework.aop.MethodBeforeAdvice(前置通知):
在目标方法执行前实施增强,可以应用于权限管理等功能。
>>org.springframework.aop.AfterReturningAdvice(后置返回通知):
在目标方法执行成功后实施增强,可以应用于关闭流、上传文件、删除临时文件等功能。
>>org.springframework.aop.AfterAdvice(后置(最终)通知)
在目标方法执行后实施增强,与后置返回通知不同的是,不管是否发生异常都要执行该类通知,该类通知,可应用于释放资源
>>org.springframework.aop.ThrowsAdvice (异常通知):
在方法抛出异常后实施增强,可以应用于处理异常、记录日志等功能
>>org.springframework.aop.IntroductionInterceptor(引介通知):
在目标类添加一些新的方法和属性,可以应用修目标类(增强类)。
AspectJ实现SpringAOP的两种方式:基于AspectJ的XML配置和基于注解开发AspectJ
基于XML配置开发AspectJ是指通过XML配置文件定义切面、切入点及通知,所有这些定义都必须在<aop:config>元素内。
切点表达式(理解第8周 PPT课件中的切点表达式例子)
切面表达式主要由:designators(指示器,匹配java方法),wildcards(通配符),operators(操作运算符)三部分组成
基于XML配置开发AspectJ的例子
1.导入AspectJ框架相关的JAR包
2.创建切面类
在src目录下,创建aspectj.xml包,在该包中创建切面类MyAspect,并在类中编写各种类型通知。
3.创建配置文件,并编写相关配置
在aspectj.xml包中,创建配置文件applicationContext.xml,并为<aop:config>元素及其子元素编写相关配置。
4.创建测试类
在aspectj.xml包中,创建测试类XMLAspectJTest,在主方法中使用Spring容器获取代理对象,并执行目标方法。
5.在dynamic.jdk.TestDaoImpl类中save方法中添加异常代码。
//例如
@Override
public void save() {
int n = 100/0;
System.out.println("保存");
}
基于注解开发AspectJ
1.创建切面类,并进行注解
在ch4应用的src目录下,创建aspectj.annotation包,在该包中创建切面类MyAspect。在该类中,首先使用@Aspect注解定义一个切面类,由于该类在Spring中是作为组件使用的,所以还需要使用@Component注解。然后,使用@Pointcut注解切入点表达式,并通过定义方法来表示切入点名称。最后在每个通知方法上添加相应的注解,并将切入点名称作为参数传递给需要执行增强的通知方法。
2.注解目标类
使用注解@Repository将目标类dynamic.jdk.TestDaoImpl注解为目标对象,注解代码如下:@Repository("testDao")
3.创建配置文件
在aspectj.annotation包中,创建配置文件applicationContext.xml,并在配置文件中指定需要扫描的包,使注解生效。同时,需要启动基于注解的AspectJ支持.
4.创建测试类
第5章 Spring的事务处理
5.1 Spring的数据库编程
1. JDBC 连接数据库时需要配置数据库,配置数据源时需要的 4 个基本属性
MySQL数据库驱动、连接数据库的URL、连接数据库的用户名、连接数据库的密码
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- MySQL数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!-- 连接数据库的URL -->
<property name="url" value="jdbc:mysql://localhost:3306/springtest?characterEncoding=utf8"/>
<!-- 连接数据库的用户名 -->
<property name="username" value="root"/>
<!-- 连接数据库的密码 -->
<property name="password" value="12345678"/>
</bean>
<!-- 配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
5.3 声明式事务处理
1. 在Spring配置文件中为JDBC配置事务时需要做哪四步工作,注意它们的正确顺序(XML 的方式)
1) 配置数据源
2) 配置事务管理器
3) 配置事务通知
4) 配置事务切面
2. Spring 的声明式事务管理可以通过两种方式来实现
一种是基于 XML 的方式,另一种是基于 @Transactional的注解方式
3. @Transactional 注解一般标注在 Service层上,主要是针对数据的增加、修改、删除进行事务管理。
第二部分 MyBatis
第6章 MyBatis开发入门
1. 在MyBatis核心配置文件中mybatis-config.xml必须配置SQL映射文件。
<mappers>
<!-- 映射文件的位置 -->
<mapper resource="com/mybatis/mapper/UserMapper.xml"/>
</mappers>
2. SQL映射文件的mapper配置标签中使用namespace来指定对应映射接口
例如UserMapper.xml中的配置:
<mapper namespace="com.dao.UserDao">
第7章 映射器
1. SQL映射文件的常用配置元素P99
➣ cache :配置给定命名空间的缓存
➣ cache-ref :从其他命名空间引用缓存配置
➣ resultMap:提供映射规则(用来描述数据库结果集和对象的对应关系)
➣ sql:可以重用的 SQL 块,也可以被其他语句引用
➣ insert:映射插入语句
➣ update:映射更新语句
➣ delete:映射删除语句
➣ select:映射查询语句
2. SQL映射文件的常用配置元素的使用
<select>
在SQL映射文件中<select>元素用于映射SQL的select语句,其示例代码如下:
<!-- 根据uid查询一个用户信息 -->
<select id="selectUserById" parameterType="Integer"
resultType="com.po.MyUser">
select * from user where uid = #{uid}
</select>
上述示例代码中,id的值是唯一标识符,它接收一个Integer类型的参数,返回一个MyUser类型的对象,结果集自动映射到MyUser属性。
<insert>
<insert>元素用于映射插入语句,MyBatis执行完一条插入语句后,将返回一个整数表示其影响的行数。它的属性与<select>元素的属性大部分相同,在本节讲解它的几个特有属性。具体如下:
keyProperty:该属性的作用是将插入或更新操作时的返回值赋值给PO类的某个属性,通常会设置为主键对应的属性。如果是联合主键,可以在多个值之间用逗号隔开。
keyColumn:该属性用于设置第几列是主键,当主键列不是表中的第一列时需要设置。如果是联合主键时,可以在多个值之间用逗号隔开。
useGeneratedKeys:该属性将使MyBatis使用JDBC的getGeneratedKeys()方法获取由数据库内部生产的主键,如MySQL、SQL Server等自动递增的字段,其默认值为false。
1.主键(自动递增)回填
MySQL、SQL Server等数据库的表格可以采用自动递增的字段作为主键。有时可能需要使用这个刚刚产生的主键,用以关联其他业务。
<!-- 添加一个用户,成功后将主键值回填给uid(po类的属性)-->
<insert id="addUser" parameterType="com.po.MyUser"
keyProperty="uid" useGeneratedKeys="true">
insert into user (uname,usex) values(#{uname},#{usex})
</insert>
2.自定义主键
如果实际工程中使用的数据库不支持主键自动递增(如Oracle),或者取消了主键自动递增的规则时,可以使用MyBatis的<selectKey>元素来自定义生成主键。
<insert id="insertUser" parameterType="com.po.MyUser">
<!-- 先使用selectKey元素定义主键,然后再定义SQL语句 -->
<selectKey keyProperty="uid" resultType="Integer" order="BEFORE">
select if(max(uid) is null, 1 , max(uid)+1) as newUid from user
</selectKey>
insert into user (uid,uname,usex) values(#{uid},#{uname},#{usex})
</insert>
<update>和<delete>
<update>和<delete>元素比较简单,它们的属性和<insert>元素、<select>元素的属性差不多,执行后也返回一个整数,表示影响了数据库的记录行数。
<!-- 修改一个用户 -->
<update id="updateUser" parameterType="com.po.MyUser">
update user set uname = #{uname},usex = #{usex} where uid = #{uid}
</update>
<!-- 删除一个用户 -->
<delete id="deleteUser" parameterType="Integer">
delete from user where uid = #{uid}
</delete>
<resultMap>元素(提纲内无)
使用Map存储结果集
使用POJO存出结果集
<resultMap type="" id="">
<constructor><!-- 类在实例化时,用来注入结果到构造方法 -->
<idArg/><!-- ID参数,结果为ID -->
<arg/><!-- 注入到构造方法的一个普通结果 -->
</constructor>
<id/><!-- 用于表示哪个列是主键 -->
<result/><!-- 注入到字段或JavaBean属性的普通结果 -->
<association property=""/><!-- 用于一对一关联 -->
<collection property=""/><!-- 用于一对多、多对多关联 -->
<discriminator javaType=""><!-- 使用结果值来决定使用哪个结果映射 -->
<case value=""/> <!-- 基于某些值的结果映射 -->
</discriminator>
</resultMap>
<resultMap>元素表示结果映射集,是MyBatis中最重要也是最强大的元素。主要用来定义映射规则、级联的更新以及定义类型转化器等。
<resultMap>元素的type属性表示需要的POJO,id属性是resultMap的唯一标识。
子元素<constructor>用于配置构造方法(当POJO未定义无参数的构造方法时使用)。
子元素<id>用于表示哪个列是主键。
子元素<result>用于表示POJO和数据表普通列的映射关系。
子元素<association> 、<collection> 和<discriminator>是用在级联的情况下。
3. SQL映射文件中的配置元素中的id属性必须唯一
4. Mybatis进行一对一和一对多关联查询时使用的标签分别是?
MyBatis如何处理一对一级联查询呢?
在MyBatis中,通过<resultMap>元素的子元素<association>处理这种一对一级联关系。在<association>元素中,通常使用以下属性。
property:指定映射到实体类的对象属性。
column:指定表中对应的字段(即查询返回的列名)。
javaType:指定映射到实体对象属性的类型。
select:指定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询。
一对多关联查询可用三种方式实现:
可参考实例
链接:http://note.youdao.com/noteshare?id=4b17fafdaad543166f32f4c808c639e6
单步查询,利用collection标签为级联属性赋值;
分步查询:
利用association标签进行分步查询;
和使用collection标签的方式相同
利用collection标签进行分步查询:
指定collection标签的 property 属性;
通过select属性指定下一步查询使用的 statement id;
通过column属性向下一步查询传递参数
(以下为补充内容)
resultMap总结
resultType:
作用:
将查询结果按照sql列名pojo属性名一致性映射到pojo中。
场合:
常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。
resultMap:
使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
association:
作用:
将关联查询信息映射到一个pojo对象中。
场合:
为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。
使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。
collection:
作用:
将关联查询信息映射到一个list集合中。
场合:
为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。
如果使用resultType无法将查询结果映射到list集合中。
第8章 动态SQL
1. 常用的动态SQL元素有哪些?理解它们的使用
if、choose (when, otherwise)、trim (where, set)、foreach
if
1.添加SQL映射语句
<!--在com.mybatis包的UserMapper.xml文件中,添加如下SQL映射语句:-->
<!-- 使用if元素,根据条件动态查询用户信息 -->
<select id="selectUserByIf" resultType="com.po.MyUser" parameterType="com.po.MyUser">
select * from user where 1=1
<if test="uname !=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if>
<if test="usex !=null and usex!=''">
and usex = #{usex}
</if>
</select>
2.添加数据操作接口方法
//在com.dao包的UserDao接口中,添加如下数据操作接口方法:
public List<MyUser> selectUserByIf(MyUser user);
3.调用数据操作接口方法
//在com.controller包的UserController类中,添加如下程序,调用数据操作接口方法。
//使用if元素查询用户信息
MyUser ifmu = new MyUser();
ifmu.setUname("张");
ifmu.setUsex("女");
List<MyUser> listByif = userDao.selectUserByIf(ifmu);
System.out.println("if元素================");
for (MyUser myUser : listByif) {
System.out.println(myUser);
}
4.测试动态SQL语句
//运行com.controller包中TestController主类,测试动态SQL语句。
select * from user where 1=1 and uname like concat('%',?,'%') and usex = ?
choose (when, otherwise)
//有些时候,不想用到所有的条件语句,而只想从中择其一二。
//针对这种情况,MyBatis 提供了choose元素,它有点像Java中的 switch 语句。
<!-- 使用choose、when、otherwise元素,根据条件动态查询用户信息 -->
<select id="selectUserByChoose" resultType="com.po.MyUser" parameterType="com.po.MyUser">
select * from user where 1=1
<choose>
<when test="uname !=null and uname!=''">
and uname like concat('%',#{uname},'%')
</when>
<when test="usex !=null and usex!=''">
and usex = #{usex}
</when>
<otherwise>
and uid > 10
</otherwise>
</choose>
</select>
//使用choose、when、otherwise元素,根据条件动态查询用户信息
MyUser chooseMu = new MyUser();
chooseMu.setUname("陈");
// chooseMu.setUsex("女");
List<MyUser> listChoose = userDao.selectUserByIf(chooseMu);
System.out.println("choose元素================");
for (MyUser myUser : listChoose) {
System.out.println(myUser);
}
trim (where, set)
<trim>元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部的某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为元素有这样的功能,所以也可以非常简单地利用来代替元素的功能。
<!-- 使用trim元素,根据条件动态查询用户信息 -->
<!--UserMapper.xml-->
<select id="selectUserByTrim" resultType="com.po.MyUser" parameterType="com.po.MyUser">
select * from user
<trim prefix="where" prefixOverrides="and |or">
<if test="uname !=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if>
<if test="usex !=null and usex!=''">
and usex = #{usex}
</if>
</trim>
</select>
//在com.dao包下的UserDao接口中添加数据操作方法
public List<MyUser> selectUserByTrim(MyUser user);
// 使用trim元素,根据条件动态查询用户信息
//UserController
MyUser trimMu = new MyUser();
trimMu.setUname("张");
trimMu.setUsex("女");
List<MyUser> listtrim = userDao.selectUserByTrim(trimMu);
System.out.println("trim元素================");
for (MyUser myUser : listtrim) {
System.out.println(myUser);
}
<where>元素
<where>元素的作用是会在写入元素的地方输出一个where语句,另外一个好处是不需要考虑元素里面的条件输出是什么样子的,MyBatis将智能处理。如果所有的条件都不满足,那么MyBatis就会查出所有的记录,如果输出后是and 开头的,MyBatis会把第一个and忽略,当然如果是or开头的,MyBatis也会把它忽略;此外,在元素中不需要考虑空格的问题,MyBatis将智能加上。
<!-- 使用where元素,根据条件动态查询用户信息 -->
<!--UserMapper.xml-->
<select id="selectUserByWhere" resultType="com.po.MyUser" parameterType="com.po.MyUser">
select * from user
<where>
<if test="uname !=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if>
<if test="usex !=null and usex!=''">
and usex = #{usex}
</if>
</where>
</select>
//在com.dao包下的UserDao接口中添加数据操作方法
public List<MyUser> selectUserByWhere(MyUser user);
// 使用where元素,根据条件动态查询用户信息
//UserController
MyUser whereMu = new MyUser();
whereMu.setUname("张");
whereMu.setUsex("女");
List<MyUser> listWhere = userDao.selectUserByWhere(whereMu);
System.out.println("where元素================");
for (MyUser myUser : listWhere) {
System.out.println(myUser);
}
<set>元素
在动态update语句中,可以使用<set>元素动态更新列。
<!-- 使用set元素,动态修改一个用户 -->
<!--UserMapper.xml-->
<update id="updateUserBySet" parameterType="com.po.MyUser">
update user
<set>
<if test="uname != null">uname=#{uname},</if>
<if test="usex != null">usex=#{usex}</if>
</set>
where uid = #{uid}
</update
//UserDao
//使用set元素,动态修改一个用户
public int updateUserBySet(MyUser user);
//使用set元素,动态修改一个用户
//UserController
System.out.println("set元素================");
MyUser setMu = new MyUser();
setMu.setUid(31);
setMu.setUname("张久");
int setup=userDao.updateUserBySet(setMu);
System.out.println("set元素修改了"+setup+"条记录");
System.out.println("================");
foreach
元素主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔符,close表示以什么结束。在使用时,最关键的也是最容易出错的是collection属性,该属性是必选的,但在不同情况下,该属性的值是不一样的,主要有以下3种情况:
如果传入的是单参数且参数类型是一个List的时候,collection属性值为list。
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array。
如果传入的参数是多个时,需要把它们封装成一个Map,当然单参数也可以封装成Map。Map的key是参数名,collection属性值是传入的List或array对象在自己封装的Map中的key。
<!--UserMapper.xml-->
<!-- 使用foreach元素,查询用户信息 -->
<select id="selectUserByForeach" resultType="com.po.MyUser" parameterType="List">
select * from user where uid in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
//UserDao接口
public List<MyUser> selectUserByForeach(List<Integer>listId);
// 使用foreach元素,根据条件动态查询用户信息
//UserController
List<Integer> listIds = new ArrayList<Integer>();
listIds.add(31);
listIds.add(32);
List<MyUser> listForeach = userDao.selectUserByForeach(listIds);
System.out.println("Foreach元素================");
for (MyUser myUser : listForeach) {
System.out.println(myUser);
}
2. 给出动态SQL语句,根据输入写出正确的SQL语句
3. MyBatis 中#{}与${}绑定参数有什么区别?
①#{ }将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #{id},如果传入的值是111,那么解析成sql时的值为order by“111”, 如果传入的值是id,则解析成的sql为order by“id”。
②${ }将传入的数据直接显示生成在sql中。如:order by ${id},如果传入的值是111,那么解析成sql时的值为order by 111, 如果传入的值是id,则解析成的sql为order by id。
③#{ }方式能够很大程度防止sql注入,${}方式无法防止Sql注入。
④${ }方式一般用于传入数据库对象,例如传入表名。
⑤ 一般能用#{}的就别用${}。
第9章 Spring MVC入门
1. SpringMVC 的工作流程P133
工作流程如下:
1) 客户端请求提交到DispatcherServlet;
2) 由DispatcherServlet控制器寻找一个或多个HandlerMapping,找到处理请求的Controller;
3) DispatcherServlet将请求提交到Controller,Controller调用业务逻辑处理后返回ModelAndView;
4) DispatcherServlet寻找一个或多个ViewResolver视图解析器,找到ModelAndView指定的视图;
5) 视图负责将结果显示到客户端。
2. 在开发Spring MVC应用时,需要在web.xml中部署配置前端控制器DispatcherServlet
第10章 Spring MVC的Controller
10.1控制器注解
@Controller
@Controller注解表明了某类是作为控制器的角色而存在的。
(使用org.springframework.stereotype.Controller注解类型声明某类的实例是一个控制器。)。
在SpringMVC中使用扫描机制找到应用中所有基于注解的控制器类,为了让控制器类被Spring MVC框架扫描到,需要在配置文件中声明spring-context,并使用<context:component-scan/>元素指定控制器类的基本包(请确保所有控制器类都在基本包及其子包下)。
示例代码:
package controller;
import org.springframework.stereotype.Controller;
/** “@Controller”表示IndexController的实例是一个控制器
* @Controller相当于@Controller("indexController")
* 或@Controller(value = "indexController")
*/
@Controller
public class IndexController {
//处理请求的方法
}
@RequestMapping
@RequestMapping 将请求的url与处理方法一一对应起来
1.方法级别注解
@Controller
public class IndexController {
@RequestMapping(value = "/index/login")
public String login() {
/**login代表逻辑视图名称,需要根据Spring MVC配置
* 文件中internalResourceViewResolver的前缀和后缀找到对应的物理视图 */
return "login";
}
@RequestMapping(value = "/index/register")
public String register() {
return "register";
}
}
2.类级别注解
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/register")
public String register() {
return "register";
}
}
10.2 Controller接收请求参数的常用方式(6种方式)
通过实体bean接收请求参数
通过处理方法的形参接收请求参数
通过HttpServletRequest接收请求参数
通过@PathVariable接收URL中的请求参数
通过@RequestParam接收请求参数
通过@ModelAttribute接收请求参数
10.3 重定向和转发
1.转发到一个请求方法(同一个控制器类里,可省略/index/)
return "forward: /index/login";
2.重定向到一个请求方法
return "redirect:/index/isRegister";
3.转发到一个视图
return "register"; //加上前缀和后缀 /WEB-INF/jsp/register.jsp
第12章 数据绑定和表单标签库
认识 JSON的两种数据结构(对象结构、数组结构)
JSON(JavaScript Object Notation,JS对象标记)是一种轻量级的数据交换格式。
与XML一样,JSON也是基于纯文本的数据格式。它有两种数据结构。
1.对象结构
对象结构以“{”开始,以“}”结束。中间部分由0个或多个以英文“,”分隔的key/value对构成,key和value之间以英文“:”分隔。对象结构的语法结构如下:
{
key1:value1,
key2:value2,
…
}
其中,key必须为String类型,value可以是String、Number、Object、Array等数据类型。
2.数组结构
数组结构以“[”开始,以“]”结束。中间部分由0个或多个以英文“,”分隔的值的列表组成。数组结构的语法结构如下:
[
value1,
value2,
…
]
第13章 拦截器
1. 拦截器的定义,实现HandlerInterceptor接口,实现接口的哪三个方法。分别在什么时候执行?
1) preHandle()方法:该方法在控制器的处理请求方法之前执行,其返回值表示是否中断后续操作。返回true表示继续向下执行,返回false表示中断后续操作。
2) postHandle()方法:该方法在控制器的处理请求方法调用之后,解析视图之前执行。可以通过此方法对请求域中的模型和视图做进一步的修改。
3) afterCompletion()方法:该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。
2. 拦截器的配置,path的值
1) /**的意思是所有文件夹及里面的子文件夹
2) /*是所有文件夹,不含子文件夹
3) /是web项目的根目录
第17章 文件的上传和下载
1. 文件上传,表单的enctype属性值必须设置为multipart/form-data
2. 文件上传是通过MultipartResolver 对象实现的,
defaultEncoding="UTF-8"
maxUploadSize="5400000"
uploadTempDir="fileUpload/temp"
defaultEncoding="UTF-8" //是请求的编码格式,默认为iso-8859-1
maxUploadSize="5400000"//是允许上传文件的最大值,单位为字节
uploadTempDir="fileUpload/temp" //为上传文件的临时路径
第19章 SSM框架整合
分别 写出各个配置文件的配置步骤
1. web.xml
2. applicationContext.xml
3. springmvc-servlet.xml
4. mybatis-config.xml
1. 写出SSM框架整合,配置文件web.xml的基本配置步骤
① 实例化applicationContext容器
② 配置前端控制器
③ 定义过滤器解决post提交乱码问题
2. 写出SSM框架整合,配置文件 applicationContext.xml的基本配置步骤。
答:
1) 开启包扫描 Service
2) 配置数据源(driverClassName、url、username、password)
3) 配置事务管理器
4) 基于XML声明式事务处理(配置事务通知、配置事务切面); 基于注解的声明式事务处理(开启事务注解)
5) 配置MyBatis工厂(属性dataSource:加载数据源,属性configLocation:指定mybatis核心配置文件的路径)
6) 配置Mapper代理开发,使用Spring自动扫描MyBatis的接口并装配,Spring将指定包中所有被@Mapper注解的接口自动装配为MyBatis的映射接口。
3. 写出SSM框架整合, 配置文件springmvc-servlet.xml的基本配置步骤。
① 开启包扫描,扫描控制器类
② 开启mvc注解,允许静态资源可见
③ 配置视图解析器(prefix:配置前缀,suffix:配置后缀)
4. MyBatis核心配置文件的配置
<mappers>
<!-- 映射器,告诉 MyBatis到哪里去找映射文件-->
<mapper resource="com/mybatis/UserMapper.xml"/>
<mapper resource="com/mybatis/ProdMapper.xml"/>
</mappers>
参考试题 Spring试题
https://wenku.baidu.com/view/0c81274586c24028915f804d2b160b4e767f81d5.html