SSM框架的知识初步了解

此文参考书籍为ACCP软件工程师——使用SSM框架开发企业级应用 8.0版

MyBatis(Dao层部分)

MyBatis传入参数的时候都会将参数放在一个Map中,返回值也是无论你设置的是resultTpye还是resultMap,其实他都会返回一个Map

一、知识了解

(1)核心接口和类

e
①sqlSessionFactoryBuilder(书P21):用过即丢,作用于方法体内,接收mybatis-config.xml形成的流或类,创建sqlSessionFactory。
②sqlSessionFactory:作用域是整个应用,是创建sqlSession实例的工厂
③sqlSession:最佳作用域是request作用域或者方法体作用域内,类似于connection。用来直接运行已经映射的SQL语句(P24下和P25下)

(2)MyBatis核心配置文件(mybatis-config.xml)

(3)SQL映射文件(mapper.xml)

(4)mybatis缓存

参考链接:mybatis 缓存的使用, 看这篇就够了
SSM框架搭建](https://blog.csdn.net/weixin_43773038/article/details/105372591)
MyBatis提供了一级缓存和二级缓存,书上写了解即可(只是说MyBatis的缓存容器了解即可,但是缓存机制得明白),缓存用OSCache、Memcached等缓存服务器更为合理。

二、详细配置

1.mybatis-config.xml

(1)配置properties:有两种写法,直接在这个xml文件中写,或者新建一个配置文件database.properties(是个file类型的文件)
参考链接:java的properties文件怎么创建?
(2)typeAliases元素(书P29):
作用是配置类型别名,就是把mapper的resultType的很长的名字,在mybatis-config.xml中配置用简单名字进行代替(例如:Pojo.User如果结构更深的话,就更复杂)。这里应该那个mapper.xml文件的namespace中的路径也可以用这个来进行简化 这里只能对javaBean进行设置别名。
三种方式:
①<typeAlias alias=“User” type=“Pojo.User” />
②<package name=“Pojo” />
这里用package的name属性标记包名,MyBatis会自动扫描包下的JavaBean,并默认设置一个别名,默认为JavaBean的非限定类名
③在User.java中直接用@Alias(value=“User”)
参考链接:MyBatis中关于别名typeAliases的设置

2.PojoMapper.xml

(1)通过配置resultMap实现高级结果映射
(2)使用@Param注解实现多参数入参

有时候只需要向PojoMapper.xml文件传入两个简单参数(一般超过四个参数最好封装成对象),没有必要传入整个例如Pojo的类,而xml中的resultType还不能实现两个参数,所以就需要在PojoMapper.java 文件中设定方法时使用@Param注解实现多参数传入。
此种方式可读性高。
例如:
在UserMapper.xml文件中

	<update id="setPasswordById">
		UPDATE user
		SET password=#{password}
		WHERE id=#{id}
	</update>

在UserMapper.java中

public int setPasswordById(@Param("id")int user_id,@Param("password")String password);	//通过用户id修改用户密码
(3)动态SQL——if、where、set、trim实现动态查询,更新

用动态SQL语言来解决JDBC时,将条件字符串连接成SQL字符串的空格和大堆的if-else问题
这里的例子只是为了说明标签的作用,实际上修改用户,有时候会需要将某一项请空的需求,可以在修改页面进入时就用POST请求给所有的标签默认值,并且不用防止null传入

①if

举例:
函数功能如果传入的参数username不为空那么就使第一个if标签中语句有效,第二个标签同理,但是如果第一个标签无效第二个标签有效就会导致SQL语句出错(因为WHERE后面紧接着AND),所以引入where标签

<!-- 函数功能如果传入的参数username不为空那么就使第一个if标签中语句有效,第二个标签同理 -->
<!-- 但是如果第一个标签无效第二个标签有效就会导致SQL语句出错(因为WHERE后面紧接着AND),所以引入where标签 -->
<select id="getUserList" resultType="User">
	SELECT * FROM user WHERE
		<if test="username != null and username != ''">
			username LIKE CONCAT ('%',#{username},'%')
		</if>
		<if test="favorite_id != null and favorite_id != ''">
			AND favorite_id = #{favorite_id}
		</if>
</select>
②where

where元素主要用来简化SQL语句中的where条件判断,并能智能地处理and和or,不必担心多于关键字导致的语法错误。

	<!--where元素主要用来简化SQL语句中的where条件判断,并能智能地处理and和or,不必担心多于关键字导致的语法错误。 -->
	<!-- 这里如果第一个if标签无效第二个if标签有效,那么where标签会自动的消除第二个if标签SQL语句的AND -->
	<select id="getUserList" resultType="User">
		SELECT * FROM user WHERE
		<where>
			<if test="username != null and username != ''">
				username LIKE CONCAT ('%',#{username},'%')
			</if>
			<if test="favorite_id != null and favorite_id != ''">
				ANDfavorite_id = #{favorite_id}
			</if>
		</where>		
	</select> 
③set

即例如更新用户数据表时,若某个参数传入值为null时,不需要set该字段
而且注意每句话后面都需要有”,“来保证SQL语言的正确性,但是如果设定最后一个if标签中没有”,“的话,当此标签失效的时候还是会在末尾出现错误,而set可以将末尾的逗号忽略掉,而且if标签中语句保持一致方便以后的修改增加

	<select id="modify" resultType="User">
			UPDATE user 
				<set>
					<if test="username != null and username != ''"> username=#{usernaem}, </if>
					<if test="telephone != null and telephone != ''"> telephone=#{telephone}, </if>
					<if test="email != null and email != ''"> email=#{email}, </if>
					<if test="introduce != null and introduce != ''"> introduce=#{introduce}, </if>
				</set>
	</select>
④trim

tirm元素会自动识别标签内是否有换回之,如果有就会在内容前面加上某些前缀(prefix)或者后缀(suffix),也可以把包含内容的首部或者尾部的内容覆盖掉,举例如下

	<!-- 这里是和起到和②中一样的作用 -->
	<select id="getUserList" resultType="User">
		SELECT * FROM user WHERE
		<trim prefix="WHERE" prefixOverrides="and | or"> 	<!-- 如果标签内的任何一个if标签有效,即标签内有返回值,则个标签中内容填上一个前缀(prefix)——WHERE,并且会自动消除与prefix中内容紧靠的prefixOverrides中的元素 -->
			<if test="username != null and username != ''">
				username like CONCAT ('%',#{username},'%')
			</if>
			<if test="favorite_id != null and favorite_id != ''">
				and favorite_id = #{favorite_id}
			</if>		
		</trim>				
	</select>
(4)使用foreach完成复杂查询

可以接收入参为数组、list或者Map类型的(数组和list不同点就是collection的参数类型不同)
其中元素
item:表示集合中每个元素进行迭代时的别名,此处为roleIds
open:表示语句以什么开始(in语句就是in (value1,value2),所以是"(“为开始的,以”,"为间隔符的)
separator:表示每次迭代之间以什么符号为分隔符(而且能只能处理分隔符不会出现多余的分隔符)
close:表示语句以什么为结束
collection:指定参数格式
   如果参数为单参数且参数是一个List的时候,其属性为list
   如果参数为单参数且参数是一个数组的话,其属性为array(此处就是array)
   如果参数是多参数,就需要把他们封装成一个Map进行处理

传入数组和list的时候

	<!-- 方法功能是传入一个roleid构成的数组,查询用户属性roleId在这个数组中的用户信息 -->
	<select id="getUserByRoleId_foreach_array" resultMap="userMapByRole">
		SELECT * FROM user WHERE userRole in
			<foreach collection="array" item="roleIds" open="(" separator="," close=")">
				#{roleIds}
			</foreach>
	</select>
	<resultMap type="User" id="userMapByRole">
		<id property="id" column="id"/>
		<result property="userCode" column="userCode"/>
		<result property="userName" column="userName"/>
	</resultMap>

传入Map的时候
测试类中

Map<String,Object> conditionMap = new HashMap<String,Object>();
List<Integer> rolelist = new ArrayList<Integer>();
roleList.add(2);
roleList.add(3);
conditionMap.put("gender","男");
conditionMap.put("roleIds",roleList);
List<User> users = new ArrayList<User>();
users = sqlSession.getMapper(UserMapper.class).getUserByConditionMap_foreach_map(conditionMap);

PojoMapper.java中

public List<User> getUserByConditionMap_foreach_map(Map<String,Object> conditionMap);

PojoMapper.xml文件

	<select id="getUserByConditionMap_foreach_map" resultMap="userMapByRole">
		SELECT * FROM user WHERE gender=#{gender} AND userRole in
			<foreach collection="roleIds" item="roleMap" open="(" separator="," close=")">	
			<!-- 这里的collection属性值是传入的变量的名字 -->
				#{roleMap}
			</foreach>
	</select>
	<resultMap type="User" id="userMapByRole">
		<id property="id" column="id"/>
		<result property="userCode" column="userCode"/>
		<result property="userName" column="userName"/>
	</resultMap>

(5)choose(when、otherwise)——多个参数选其一使用完成查询

元素
when:当其test中条件满足的时候就会输出when元素中的内容。并且当when中一旦有条件满足的时候,就会跳出choose,及所有的when和otherwise条件中,只有一个条件会输出。
otherwise:当when中的所有条件都不满足的时候,就会自动输出otherwise元素中的内容。
UserMapper.xml文件

	<!-- 方法功能当username、introduce和userrole以从上到下的顺序,第一个有效的when标签生效,即跳出choose标签,如果都没有生效则otherwise标签生效 -->
	<select id="getUserList_choose" resultType="User">
		SELECT * FROM user WHERE 1=1
			<choose>
				<when test="username != null and username != ''">
					AND username LIKE CONCAT ('%',#{username},'%')
				</when>
				<when test="introduce != null and introduce != ''">
					AND introduce LIKE CONCAT ('%',#{introduce},'%')
				</when>
				<when test="userrole != null">
					AND userrole=#{userrole}
				</when>
				<otherwise>
					AND registTime = #{registTime}
				</otherwise>
			</choose>
	</select>

UserMapper.java文件

	public List<User> getUserList_choose(@Param("username")String username,@Param("introduce")String introduce,@Param("userrole")String userrole,@Param("registTime")Date registTime);
(5)标签中的各个参数

公共参数:

<insert>中:
keyproperty:

	<!-- 使用 keyProperty="id" useGeneratedKeys="true"可以在使用addUser时,自动返回id-->
	<insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
		INSERT INTO user (username,password,gender,email,telephone,introduce,activeCode,role,registTime) 
		VALUES(#{username},#{password},#{gender},#{email},#{telephone},#{introduce},#{activeCode},#{role},#{registTime})
	</insert>

3.MyBatisUtils.java

(1)如果使用inset、update或者delete等会对数据库数据进行修改的语句,需要保持数据的一致性

所以需要在此处开启Session的时候,设置为手动提交事务,并在调用的时候用commit()进行提交并在失败出错时用rollback()进行回滚,保持数据的一致性。
举例如下:

	//MyBatisUtil.java中设置事务手动提交
	public static SqlSession createSqlSession() {
		return factory.openSession(false);	//true为自动提交事务
	}
	//调用时需要做的顺序
	try {
		sqlSession = MyBatisUtil.createSqlSession();
		count = sqlSession.getMapper(UserMapper.class).addUser(user);
		sqlSession.commit();	
		//如果没有异常的话就提交修改,否则用roolback回滚,因为在MyBatisUtils中设置的是
		//return factory.openSession(false);	//true为自动提交事务,这样就可以判断是否出现异常而来决定是否提交
	} catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
		sqlSession.rollback();	//如果出现异常,进行回滚保持数据一致性
		count = 0;
	}finally {
		MyBatisUtil.closeSqlSession(sqlSession);
	}
(2)

三、log4j

1.知识了解

也见2.

2.详细配置

参考链接:Log4j配置详解这个链接中的二、是详细配置,注意其中的红色字体是配置格式
     实现保存日志路径为相对路径 尝试方法三,最后部署在服务器上的时候试一试服务器环境变量,但是这样好像增加耦合了
     log4j配置和Java中调用getlogger()中填写的name的关系这里暂时理解为如果没有额外的名字的话,调用的时候直接用“rootCategory”来填写为name,就可以

3.使用

//这里的debug和info是作为日志记录的级别,也就是优先级,这里的东西如果高于properties中的级别,在哪里输出依赖于配置文件中的appendername是否设置含有那几个class name 例如:consleAppender(控制台输出)
	logger.debug(" User's aname:" + user.getUsername());		//这个是指定此信息为debug级别,这里的debug级别呗屏蔽,不进行输出和记录
	logger.info(" User's bname:" + user.getUsername());			//这个是指定此信息为info级别,这里的info级别信息,会正常被处理不会被屏蔽

参考配置:用logger在控制台打印信息

Spring(Service部分)

一、知识了解

1.主要特性

有简单性、可测试性和松耦性,是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。

2.优点:

  (1)面向接口编程,而不是针对类,而Spring用容器来实现接口的实现和管理来将接口的复杂度降到零。
  (2)代码更易于测试。因为具有插拔性,可以根据测试来另外实现,方便测试。
  (3)JavaBean提供了应用程序配置的最好方法。?????????
  (4)在Java中,已检查异常(Checked exception)被过度使用。框架不应该迫使你捕获不能恢复的异常。??????????????

3.关于增强类

(具体实现在下面二、2.)
(1)前置增强:在方法运行前进行插入运行
(2)后置增强:在方法运行结束进行运行
(3)异常抛出增强:特点是在目标方法抛出异常时织入增强处理,使异常抛出增强
(4)最终增强:特点是无论方法抛出异常还是正常退出,该增强都会得到执行,类似于异常处理机制中finally的作用,一般用于释放资源。
(5)环绕增强:在目标的方法的前后都可以织入增强处理。是最强大的增强处理,它有对目标方法的控制权。(可以修改目标方法的参数、返回值,也可以进行异常处理,也可以决定方法是否被执行)

二、详细配置

1.applicationContext.xml

其中关键字:

(1)<bean>
	<!-- 对相关组件机型声明,注意最好不要和PojoMapper.xml中的bean重名 -->
	<!-- 这里就能体现出来控制反转的思想,接口类的实现被Spring管理 -->
	<bean id="userService" class="service.UserServiceImpl"></bean>
	<bean id="theLogger" class="service.UserServiceLogger"></bean>
	
	<!-- 如果实现类需要调用另一个bean的话,写法如下,UserServiceImpl代码见下 -->
	<bean id="dao" class="dao.Impl.UserDaoImpl"></bean>
	<bean id="userService" class="service.Impl.UserServiceImpl">
		<property name="dao" ref="dao"></property>
	</bean>
public class UserServiceImpl implements UserService {
	private UserDao dao;
	......
}
(2)<aop>

参考书P141

<aop:config>
		<!-- 定义切入点表达式 ,命名为pointcut -->
		<aop:pointcut id="pointcut" expression="execution(public int addUser(Pojo.User))"/>
		<!-- <aop:pointcut id="pointcut" expression="execution(* service.UserService.addUser())"/> -->
		<!-- 引用包含增强方法的Bean -->
		<aop:aspect ref="theLogger">
			<!-- 这里的before和afterReturning是在增强类中编写的,代码见下 -->
			<!-- 将before()方法定义为前置增强并引用pointcut切入点 -->
			<aop:before method="before" pointcut-ref="pointcut"/>
			<!-- 将afterReturning()方法定义为后置增强并引用pointcut切入点 -->
			<!-- 通过returning属性指定名为result的参数注入返回值 -->
			<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
		</aop:aspect>
	</aop:config>

这里的execution是切入点指示符,括号中是一个切入点表达式,支持模糊匹配,例如;
①public * addNewUser(entity.User); "*"表示匹配所有类型的返回值
②public void * (entity.User); 表示匹配所有参数为User类的方法。
③public void addNewUser(…); 表示匹配所有参数个数和类型的addNewUser方法
④* com.service.*.*(…); 表示匹配com.service包下所有类的所有方法
⑤* com.service…*.*(…); 表示匹配com.service包及其子包下所有类的所有方法

增强类:

package service;
import java.util.Arrays;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;

public class UserServiceLogger {
	private static final Logger logger = Logger.getLogger("rootCategory");	
	//代表前置增强方法
	public void before(JoinPoint jp) {
		logger.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法入参:" + Arrays.toString(jp.getArgs()));
	}
	//代表后置增强方法
	public void afterReturning(JoinPoint jp,Object result) {
		logger.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法返回值:" + result);
	}
}

2.关于增强类的实现

(1)前置增强、后置增强(注释实现):

需要配置applicationContext.xml文件:

	<!-- 这里是用注释来实现增强的时候用的 -->
	<bean class="aop.UserServiceLogger_annotation"></bean>
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
package aop;

import java.util.Arrays;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class UserServiceLogger_annotation {
	private static final Logger logger = Logger.getLogger("rootCategory");
	
	//代表前置增强方法
	@Before("execution(public int addUser(Pojo.User))")
	public void before(JoinPoint jp) {
		logger.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法入参:" + Arrays.toString(jp.getArgs()));
	}
	//代表后置增强方法
	@AfterReturning(pointcut = "execution(public int addUser(Pojo.User))",returning = "result")
	public void afterReturning(JoinPoint jp,Object result) {
		logger.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法返回值:" + result);
	}
}
(2)前置增强、后置增强(xml配置文件实现):
package aop;

import java.util.Arrays;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;

public class UserServiceLogger {
	private static final Logger logger = Logger.getLogger("rootCategory");
	
	//代表前置增强方法
	public void before(JoinPoint jp) {
		logger.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法入参:" + Arrays.toString(jp.getArgs()));
	}
	//代表后置增强方法
	public void afterReturning(JoinPoint jp,Object result) {
		logger.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法返回值:" + result);
	}
}

	<!-- 暂时理解为: 和书上不一样是因为我实现Dao层中接口是用UserMapper.xml实现的,所以不用再次在这里进行设置 -->
	<bean id="userMapper" class="dao.UserMapper"></bean>
	<bean id="userService" class="service.UserServiceImpl"></bean>
	<bean id="theLogger" class="aop.UserServiceLogger"></bean>
	<aop:config>
		定义切入点表达式 ,命名为pointcut
		<aop:pointcut id="pointcut" expression="execution(public int addUser(Pojo.User))"/>
		<aop:pointcut id="pointcut" expression="execution(* service.UserService.addUser())"/>
		引用包含增强方法的Bean
		<aop:aspect ref="theLogger">
			将before()方法定义为前置增强并引用pointcut切入点
			<aop:before method="before" pointcut-ref="pointcut"/>
			将afterReturning()方法定义为后置增强并引用pointcut切入点
			通过returning属性指定名为result的参数注入返回值
			<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
		</aop:aspect>
	</aop:config>
(3)异常抛出增强:

一般放入资源释放类,因为不管完没有完成都会执行
切入点什么的和(2)的前后增强类似,不再赘述。
xml中关键代码:

	<bean id="theLogger" class="aop.ErrorLogger"></bean>
	<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
package aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;

public class ErrorLogger {
	private static final Logger logger = Logger.getLogger(ErrorLogger.class);
	public void afterThrowing(JoinPoint jp,RuntimeException e) {
		logger.error(jp.getSignature().getName() + "方法异常:" + e);
	}
	
}
(4)最终增强:

xml中配置:

<aop:after method="afterLogger" point-cut-ref="pointcut"/>
package aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;

public class AfterLogger {
	private static final Logger logger = Logger.getLogger(AfterLogger.class);
	public void afterLogger(JoinPoint jp) {
		logger.info(jp.getSignature().getName() + "方法异常:");
	}
	
}
(5)环绕增强:

3.注解实现IoC的配置

也就是定义Bean,然后Bean组件配装(将实体化的时候会用到的参数和参数类,进行注解表明其结构)

(1)引入命名空间,且规定注释可能出现的范围

base-package属性制定了需要扫描的基准包(多个逗号隔开)

xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context
					http://www.springframework.org/schema/context/spring-context-3.2.xsd"

	<!-- 规定包中注解标注的类 -->
	<context:component-scan base-package="service,dao">
(2)注释出Bean

这种注释方法进一步减少了配置文件的代码量
@compone("")可以注释所有类别bean
@Respository:用于标注DAO类。
@Service:用于标注业务类。
@Controller:用于标注控制器类。
下面三种特定的注释推荐使用
示例代码见(3)实现组装的例子

(3)用注释实现组装(即构造时会用到另外的Bean,需要注释)

@Autowired:Spring对此注释进行注入时,会采用按类型匹配,而不是按照方法或者bean的名字进行匹配,所以可能出现多个匹配项,所以引出下面的注释
@Qualifier(”“):可以指定所需的Bean的名称,使用时仍需要引入@Autowired

@Service("userService")		//用注释来实现定义Bean
public class UserServiceImpl implements UserService{
	
	@Autowired
	private UserMapper userMapper;	//这里书上例子是用的UserDao,我这里没有对UserMapper进行测试,但是道理是一样的
		
	//这里Spring管理的时候需要用set方法进行实例化
	public void setUserMapper(UserMapper userMapper) {
		this.userMapper = userMapper;
	}

	/**
	*当指定Bean的名字的时候
	*/
	@Autowired
	@Qualifier("userMapper")			//这里的userMapper是用(2)中注释出来的Bean名称
	private UserMapper userMapper;

MyBatis与Spring的整合

一、知识了解

首先明白以下几个部分,其详细配置往下看

①SqlSessionFactoryBean

是用来代替SqlSessionFactoryBean
这里封装了使用SqlSessionFactoryBean创建SqlSessionFactroy的过程,即以配置文件形式配置SqlSessionFactroyBean来获得SqlSessionFactory实例。

②SqlSessionTemplate

(需要在PojoMapperImpl中调用进行使用)
此部分代替MyBatis中原有的SqlSession,提供数据库访问操作
自动管理会话的生命周期、关闭、提交和回滚操作。

③SqlSessionDaoSupport

(仍需要编写PojoMapperImpl类,只是不用声明SqlFactoryTempplate类,继承SqlSessionDaoSupport就行)
此部分简化了SqlSessionTemplate的配置和获取,具体过程如下:
提供了setSqlSessionFactory()来注入SqlSessionFactory实例,并创建SqlSessionTemplate实例,同时提供getSession()方法,来返回创建好的SqlSessionTemplate实例

以下是根据指定的映射器和映射文件直接生成实现类(不必写PojoMapperImpl),同时不用显示注入SqlSessionFactory了,所以②③没用了

④MapperFactoryBean

此部分以配置的方式生成映射器,并注入给业务组件(ServiceImpl中可以调用Dao层中PojoMapper接口)
自动实现PojoMapper的实现类(包括②③干的活)
缺点:如果映射器多,配置项也会多
SQL映射文件须遵循以下命名规则:
映射的命名空间和映射器接口的名称相同。映射元素的id和映射器接口的方法相同。

⑤MapperScannerConfiguer

可以扫描指定包中的接口,并将它们直接注册为MapperFactoryBean,而且会自动注入SqlSessionFactory。
【注意】映射器被注册到Spring的容器时,Spring会根据其接口名称为其命名,默认规则是首字母小写的非完全限定类名

如果使用@Autowired或者@Resource配合@Service(“pojoService”)实现对业务组件的依赖注入,可以更加简化配置文件。

在这里插入图片描述

二、详细配置

(建立在具有Pojo、PojoMapper、PojoMapper.xml和mybatis-config.xml还有PojoMapperImpl的基础上进行如下配置)

1.导入整合资源包

导入MyBatis-Spring 整合资源包
下载:MyBatis-Spring资源整合包中mybatis-spring-1.2.0.zip
导入:mybatis-spring-1.2.0.jar(整合)
   spring-jdbc-3.2.13.RELEASE.jar (Spring的数据源支持)
   spring-tx-3.2.13.RELEASE.jar (事务支持)


以下配置文件暂时放在applicationContext-mybatis.xml文件中

2.配置数据源

(1)这里使用dbcp作为数据库连接池
导入commons-dbcp-1.4.jar 和 commons-pool-1.6.jar
(2)建立applicationContext-mybatis.xml文件

	<!-- 配置DataSource 以获得与数据库的连接-->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url">
			<!-- 这里的![CDATA[]]是用来限制字符串中出现的&等特殊字符,二义性 -->
			<value><![CDATA[jdbc:mysql://localhost:3306/test_blog?characterEncoding=UTF-8]]></value>
		</property>
		<property name="username" value="root"/>
		<property name="password" value="chiying21"/>
	</bean>

3.配置SqlSessionFactoryBean

在MyBatis中,SqlSessionFactory需要用SqlSessionFactoryBuilder创建,这里可以用SqlSessionFactoryBean进行代替,它封装了SqlSessionFactoryBuilder创建SqlSessionFactory的过程,即可以通过SqlSessionFactoryBean配置获得SqlSessionFactory实例。

	<!-- 配置SqlSessionFactoryBean -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 引用数据源组件 -->
		<property name="dataSource" ref="dataSource"/>
		<!-- 引用MyBatis配置文件中的配置 -->
		<property name="configLocation" value="classpath:mybatis-config.xml"/>
		<!-- 配置SQL映射文件信息 -->
		<property name="mapperLocations">
			<list>
				<!-- 这里是指定表示扫描dao包及其任意层级子包中,任意名称的xml文件,来加载SQL映射文件 -->
				<value>classpath:dao/**/*.xml</value>
			</list>
		</property>
	</bean>

4.使用SqlSessionTemplate实现数据库操作

SqlSessionTemplate类实现了MyBatis中的SqlSession接口,可以替换原有的SqlSession实现类提供数据库访问操作。可以自动管理会话的生命周期,包括关闭、提交和回滚操作。
也就是说它主要的任务是在PojoMapperImpl中完成对数据库的连接访问传输SQL语句的功能。
而且,SqlSessionTemplate是线程安全的。!!!!!!!!!!!!!!!!!!!!
(1)配置文件:

	<!-- 省略前文DataSource和sqlSessionFactory的配置 -->
	<!-- 配置SqlSessionTemplate -->
	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg name="sqlSessionFactroy" ref="sqlSessionFactory"/>
	</bean>
	<!-- 配置DAP组件并注入SqlSessionTemplate实例 -->
	<bean id="userMapper" class="dao.UserMapperImpl">
		<property name="sqlSession" ref="sqlSessionTemplate"></property>
	</bean>

(2)使用举例:

package dao;
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import Pojo.User;

public class UserMapperImpl implements UserMapper{
	private SqlSessionTemplate sqlsession;	//它主要的任务是在PojoMapperImpl中完成对数据库的连接访问传输SQL语句的功能。

	//引入set和get方法是因为创建SqlSessionTemplate实例时,需要通过其构造方法注入SqlSessionFactroy实例,这里引用的是前面配置过的id为sqlSessionFactory的Bean
	public SqlSessionTemplate getSqlsession() {
		return sqlsession;
	}
	public void setSqlsession(SqlSessionTemplate sqlsession) {
		this.sqlsession = sqlsession;
	}

	@Override
	public int count() {
		return sqlsession.selectOne("dao.user.UserMapper.count");
	}
}

5.完成业务逻辑代码

这里是写UserService和UserServiceImp的部分,基本不用改变,只是UserServiceImpl中的PojoMapper需要增加get和set方法,供构造的时候使用,并注意userMapper 需要注入

	<bean id="userService" class="service.UserServiceImpl">
		<property name="userMapper" ref="userMapper"></property>
	</bean>

6.测试类编写实例

	/*
	*这里只需要嗲用AppliactionContext类对象,从此对象实例化的类中用getBean方法获得已经初始化的Bean,这个ServiceBean已经获取了与数据库的链接
	*/
	@Test
	public void testUserService() {
		//在这里就已经在配置文件完成MyBatis的一系列创建,创建出来的SqlSessionTemplate可以提供给多个Dao对象使用。
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-mybatis.xml");
		UserService userService = (UserService) ctx.getBean("userService");
		
		int result = 0;
		User user = new User();
		
		user.setUsername("test_addUser");
		user.setActiveCode("测试用户");		
		user.setEmail("example@qq.com");
		user.setGender("男");
		user.setIntroduce("测试用户的个人签名_一直很快乐");
		user.setPassword("1");
		user.setTelephone("15724594969");
		
		result = userService.addUser(user);
	}

7.用SqlSessionDapSupport类来简化SqlSessionTemplate的配置和获取。

SqlSessionDapSupport提供了setSqlSessionFactory()方法用来注入SqlSessionFactory实例并创建SqlSessionTemplate实例,同时提供了getSqlSession()方法来返回创建好的SqlSessionTemplate。
使用SqlSessionDapSupport简化了,配置文件中的SqlSessionTemplate部分,在PojoMapperImpl中也不需要定义SqlSessionTemplate和其setter方法
(1)使用方法

//在PojoMapperImpl中也不需要定义SqlSessionTemplate和其setter方法
package dao;
import java.util.List;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import Pojo.User;
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
	@Override
	public int count() {
		return this.getSqlSession().selectOne("dao.user.UserMapper.count");
	}
}

(2)配置文件
删除上部分SqlSessionTemplate

	<!-- 省略数据源配置 -->
	<!-- 配置SqlSessionFactoryBean -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 省略一些配置 -->
	</bean>
	<!-- 配置DAO -->
	<bean id="userMapper" class="dao.UserMapperImpl">
		<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
	</bean>

这里也有显而易见的缺点,就是每一个pojoMapper需要手动注入sqlSessionFactory。

8.使用MapperFactoryBean注入映射器

能够以配置的方式生成映射器并注入给业务组件,就可以不用手动配置SqlSessionTemplate和SqlSessionDaoSupport来实现Dao类(可以删除PojoMapperImpl了)

配置文件

	<!-- 省略数据源配置 -->
	<!-- 配置SqlSessionFactoryBean -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 引用数据源组件 -->
		<property name="dataSource" ref="dataSource"/>
		<!-- 引用MyBatis配置文件中的配置 -->
		<property name="configLocation" value="classpath:mybatis-config.xml"/>
	</bean>
	
	<!-- 配置DAO -->
	<!-- 这里注意calss中的属性是MapperFactoryBean -->
	<bean id="userMapper" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="mapperInterface" ref="dao.UserMapper"></property>
		<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
	</bean>

9.使用MapperScannerConfigurer注入映射器

是为了简化MapperFactoryBean中配置项项(PojoMapper)很多,
MapperScannerConfigurer可以扫描指定包中的接口并将他们直接注册为MapperFactoryBean,也就是简化了上面配置DAO的部分
MapperScannerConfigurer创建所有的映射器实现都会自动被注入SqlSessionFactory实例,所以无需显示注入。(这里能够批量生成映射器实现,但是如果还使用配置文件进行一个一个的组件,还是太麻烦———就是组建userService等service需要pojomapper组件)

配置文件

	<!-- 省略数据源配置 -->
	<!-- 配置SqlSessionFactoryBean -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 引用数据源组件 -->
		<property name="dataSource" ref="dataSource"/>
		<!-- 引用MyBatis配置文件中的配置 -->
		<property name="configLocation" value="classpath:mybatis-config.xml"/>
	</bean>
	
	<!-- 配置DAO -->
	<!-- 指定扫描范围 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" ref="dao"></property>
	</bean>

①basePackage属性中可以包含多个包,用逗号分开就行
②映射器呗注册到Spring的容器时,Spring会根据其接口名称为其命名,默认规则是首字母小写的非完全限定类名。

10.使用@AutoWired或者@Resource注解实现对业务组件的依赖注入

(1)配置文件

	<!-- 省略数据源配置 -->
	<!-- 省略SqlSessionFactoryBean配置 -->
	<!-- 配置DAO -->
	<!-- 指定扫描范围 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" ref="dao"></property>
	</bean>
	<!-- 配置扫描注解定义的业务Bean base-package属性中执行要扫描的路径(来支持@AutoWired或者@Resource等)-->
	<context:component-scan base-package="service"></context:component-scan>

(2)应用举例

@Service("userService")		//用注释来实现定义Bean
public class UserServiceImpl implements UserService{
	Logger logger = Logger.getLogger("rootCategory");	//获得log4j中logger的实体
	@Resource	//这里指定其装配参数(配合@Service("userService"))
	private UserMapper userMapper;
	
	//这里Spring管理的时候需要用set方法进行实例化
	public void setUserMapper(UserMapper userMapper) {
		this.userMapper = userMapper;
	}	
	public UserMapper getUserMapper() {
		return userMapper;
	}
	
	....
	}

11.配置声明式事务(为业务层添加声明式事务)

Spring提供的声明式事务处理机制,基于AOP实现。使事务控制和事务代码与业务代码完全分离,配置即可用。
使用举例:(添加用户功能为例)

①UserMapper和User Mapper.xml文件不变(如果此方法是新增的话,因为使用MapperScannerConfigurer动态创建映射器实现,没有自定义的接口实现类,所以不需要修改相关代码)
②UserService和UserServiceImpl也不需要修改
③在配置文件中增加命名空间(都放在了applicationContext-mybatis.xml)
	<?xml version="1.0" encoding="UTF-8"?>
	<beans 
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
	</beans>
④配置事务管理器组件——DataSourceTransactionManager

这里要注入数据源组件

	<!-- 省略数据源、SqlSessionFactoryBean、DAP及其业务Bean的配置 -->
	<!-- 定义事务管理器 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 注入数据源组件 -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>
⑤通过<tx:advice >标签配置事务增强,为不同业务方法指定具体的事务规则。

标签中有以下几个属性:propagation、isolation、timeout、read-only、rollback-for、no-rollback-for
参考链接:tx:method 的属性详解
     @Transactional(rollbackFor=Exception.class)的使用(这里暂时不做深入研究)

	<!-- 通过<tx:advice>标签为指定的事务管理器设置事务属性,可以看出这里可以设置不同的事务管理器,而且也可以有多个<tx:advice >供下面切面使用 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<!-- 定义属性,声明事务规则 -->
		<tx:attributes >
			<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
			<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception.class"/>
			<tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception.class"/>
			<tx:method name="*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
⑥定义切面,设置上面<tx:advice >作用点
	<!-- 可以看出可以针对不同的切入点,使用不同的事务增强方案 -->
	<aop:config>
		<!-- 定义切入点 -->
		<aop:pointcut id="serviceMethod" expression="execution(* service..*.*(..))"/>
		<!-- 将事务增强与切入点组合 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
	</aop:config>

12.使用注解实现声明式事务处理(为业务层添加声明式事务)

即先定义事务处理,然后以注释的方式,定义事务生效的地方,而不是跟切点结合,但是暂时认为可以一起使用

(1)配置文件
	<!-- 之前定义过的事务管理器 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 配置用注释的方式配置声明事务,即定义txManager在何处生效,可以对某一方法进行额外注解设置 -->
	<tx:annotation-driven transaction-manager="txManager"/>
(2)使用示例

在PojoServiceImpl.java中进行注释

@Transactional
@Service("userService")		//用注释来实现定义Bean
public class UserServiceImpl implements UserService{
	Logger logger = Logger.getLogger("rootCategory");	//获得log4j中logger的实体
	@Resource	//这里指定其装配参数(配合@Service("userService")
	private UserMapper userMapper;
	
	......
	
	@Override
	@Transactional(rollbackFor=Exception.class)		//这里表示检测到异常就进行回滚
	//新增用户(注册) 
	public int addUser(User user) {}

13.最终的配置文件(暂时都放到applicationContext-mybatis.xml中)

支持12中的注解配置事务,这里用其对特定事务进行补充

<?xml version="1.0" encoding="UTF-8"?>
<beans 	xmlns="http://www.springframework.org/schema/beans" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.2.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
	
	<!-- 配置DataSource 以获得与数据库的连接-->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url">
			<value><![CDATA[jdbc:mysql://localhost:3306/test_blog?characterEncoding=UTF-8]]></value>
		</property>
		<property name="username" value="root"/>
		<property name="password" value="chiying21"/>
	</bean>

	<!-- 配置SqlSessionFactoryBean -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 引用数据源组件 -->
		<property name="dataSource" ref="dataSource"/>
		<!-- 引用MyBatis配置文件中的配置 -->
		<property name="configLocation" value="classpath:mybatis-config.xml"/>
	</bean>
	
	<!-- 配置DAO -->
	<!-- 这里使用MapperScannerConfigurer就不用显示注入SqlSessionFactory -->
	<!-- 映射器被注册到Spring容器时,会根据其接口名字为其命名,默认规则是首字母小写的非完全限定类名 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="dao"></property>
	</bean>
	
	<!-- 配置扫描注解定义的业务Bean base-package属性中执行要扫描的路径(来支持@AutoWired或者@Resource等)-->
	<context:component-scan base-package="service"></context:component-scan>
	
	<!-- 下面属于事务管理部分 -->
	<!-- 定义事务管理器 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 通过<tx:advice>标签为指定的事务管理器设置事务属性 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<!-- 定义属性,声明事务规则 -->
		<tx:attributes >
			<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
			<tx:method name="add*" propagation="REQUIRED"/>
			<tx:method name="modify*" propagation="REQUIRED"/>
			<tx:method name="*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
	
	<aop:config>
		<!-- 定义切入点 -->
		<aop:pointcut id="serviceMethod" expression="execution(* service..*.*(..))"/>
		<!-- 将事务增强与切入点组合 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
	</aop:config>
	
</beans>	

加入SpringMVC

这里的详细优化过程,参考SSM框架的知识初步了解——MyBatis与Spring的整合,下面只写出最终配置,及其注解。

一、知识了解

要明白以下几个部分

二、详细配置

1.导入jar包

SpringMVC的包在三、spring-framewok-3.2.13.RELEASE-dist.zip中:
   spring-web-3.2.13.RELEASE.jar
   spring-webmvc-3.2.13.RELEASE.jar
并需要进行buildPath!!!!!!!!!!!!!!!!!!!!!

2.在web.xml中配置Servlet

web.xml在WEB-INF目录下进行新建

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 id="WebApp_ID" version="2.5">
  
  <!-- 配置SpringMVC的核心控制器DispatcherServlet -->
  <servlet>
    <servlet-name>springMvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>	
    <!-- 初始化同参数 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc-servlet.xml</param-value>	<!-- 配置文件的路径 -->
    </init-param>
    <!-- 这里是配置标记在程序运行时就加载此DispatcherServlet -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- 配置DispatcherServlet -->
  <servlet-mapping>
    <servlet-name>springMvc</servlet-name>	<!-- 将名为springMvc的DispatcherServlet映射到*.action,也就是会截获到jsp中名字为*.action的方法 -->
    <url-pattern>/</url-pattern>	<!-- 这里暂时截获并处理所有的URL请求 -->
  </servlet-mapping>
  
  <!-- 应该是设置过滤器,暂时没用到 -->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

3.创建SpringMVC的配置文件(springmvc-servlet.xml)

放在ersources目录下

(1)配置处理器映射(HandlerMapping)

作用就是把一个URL请求指定给一个Controller处理。
Spring提供了多种处理器映射(HandlerMapping)的支持,如:
org.springframework.web.servlert.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlert.handler.SimpleUrlHandlerMapping
org.springframework.web.servlert.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlert.mvc.method.annotation.RequestMappingHandlerMapping
这里我们使用BeanNameUrlHandlerMapping(如果没有进行显示声明,Spring默认使用BeanNameUrlHandlerMapping),如:
使用配置来匹配

<!-- 声明处理器映射(HandlerMapping),如果没有声明就是默认是BeanNameUrlHandlerMapping -->
    <bean name="/index.html" class="controller.IndexController"></bean>		<!-- 这里用配置文件方式实现url用指定controller处理 -->

使用注释来实现(采用此方法)

	<!--扫描带Controller注解的类 -->
	<context:component-scan base-package="controller" />
	<!-- 加载注解驱动 -->
	<mvc:annotation-driven/>
(2)配置视图解析器

作用是确定指定的请求要使用哪个视图进行请求结果的输出,将控制器返回的逻辑视图名称转换成实际视图。
也有多种视图解析器,如:
org.springframework.web.servlert.view.InternalResourceViewResolver
org.springframework.web.servlert.view.ContentNegotiatingViewResolve
这里使用InternalResourceViewResolver,通过前缀后缀,最后将视图逻辑名解析成前缀/<viewName>/后缀形式的实际路径

    <!-- 配置视图解析器 	 作用:在controller中指定页面路径的时候就不用写页面的完整路径名称了,可以直接写页面去掉扩展名的名称 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 真正的页面路径 =  前缀 + 去掉后缀名的页面名称 + 后缀 ,中间填的是返回的VIEW名-->
		<!-- 前缀 -->
		<property name="prefix" value="/WEB-INF/jsp/"></property>
		<!-- 后缀 -->
		<property name="suffix" value=".jsp"></property>
	</bean>

4.创建Controller(代替原来三层架构的Servlet)

在src目录下新建controller文件夹,然后这里新建indexController.java举例,

(1)第一种方法:

需要继承org.springframework.web.servlet.mvc.AbstractControlle,并实现handleRequest Internal方法
配置文件

 <!-- 声明处理器映射(HandlerMapping),如果没有声明就是默认是BeanNameUrlHandlerMapping -->
    <bean name="/index.html" class="controller.IndexController"></bean>		<!-- 这里用配置文件方式实现url用指定controller处理 -->

Controller的JavaBean

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class IndexController extends  AbstractController{

	@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
		System.out.println("~~~~~~~~~~IndexController~~~~~~~~~~~~");
		return new ModelAndView("index");	//这里就对应上面3.(2)中说的逻辑视图名(viewName),也就是说在这里去访问index.jsp文件
	}

}

(2)第二种方法:

使用@Controller对Controller类进行标注,使其成为一个可处理HTTP请求的控制器,再使用@RequestMapping对Controller中的方法进行标注,确定方法对应的URL。(注意@Request Mapping可以嵌套,见书P234示例8)
配置文件

	<!--扫描带Controller注解的类 -->
	<context:component-scan base-package="controller" />
	<!-- 加载注解驱动 -->
	<mvc:annotation-driven/>

Controller的JavaBean

package controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

@Controller	//
public class IndexController{

	private Logger logger = Logger.getLogger("rootCategory");	//获得log4j中logger的实体
	
	@RequestMapping("/index")//
	public String index() {
		System.out.println("~~~~~~~~~~~~@RequestMapping(\"index\")~~~~~~~~~~~~~~~");
		logger.info("~~~~~~~~~~~~@RequestMapping(\"index\")~~~~~~~~~~~~~~~");
		return "index";
	}
}
最终spring-servlet.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
<!-- 	 扫描带Controller注解的类 -->
<!-- 	<context:component-scan base-package="controller" /> -->
<!-- 	加载注解驱动 -->
<!-- 	<mvc:annotation-driven/> --> 

    <!-- 声明处理器映射(HandlerMapping),如果没有声明就是默认是BeanNameUrlHandlerMapping -->
    <bean name="/index.html" class="controller.IndexController"></bean>		<!-- 这里用配置文件方式实现url用指定controller处理 -->
    
    <!-- 配置视图解析器 	 作用:在controller中指定页面路径的时候就不用写页面的完整路径名称了,可以直接写页面去掉扩展名的名称 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 真正的页面路径 =  前缀 + 去掉后缀名的页面名称 + 后缀 ,中间填的是返回的VIEW名-->
		<!-- 前缀 -->
		<property name="prefix" value="/WEB-INF/jsp/"></property>
		<!-- 后缀 -->
		<property name="suffix" value=".jsp"></property>
	</bean>
		
</beans>

5.创建View(这里是jsp文件)

6.参数传递部分(书P232

View to Controller
(1)@RequestMapping来传递参数

但是这个有弊端,是如果在方法中已经定义一个参数了,但是实际并没有传过来的话就会报400错误,同样url传的参数名和这里定义接受的参数名不一样的话,也会同样找不到,然后报400错误。
在Controller中写

	//此函数
	@RequestMapping(value="/test",method = RequestMethod.GET,params = "username")
	public String test(@RequestParam String username) {
		System.out.println("~~~~~~~~~~~~@RequestMapping(\"/test\")~~~~~~~~~~~~~~~");
		logger.info("~~~~~~~~~~~~@RequestMapping(\"/test\")~~~~~~~~~~~~~~~");
		logger.info("test,username:" + username);
		return "test";
	}

测试方法: http://localhost:8080/test_ssm_Spring_MyBatis_Spring_SpringMVC/test?username=ddz

(2)@RequestParam来注解指定参数

解决上面的参数问题,会设定参数是否必要,使用@RequestParam来注释实现

	@RequestMapping("/test2")
	public String test2(@RequestParam(value = "username",required = false) String username) {
		System.out.println("~~~~~~~~~~~~@RequestMapping(\"/test2\")~~~~~~~~~~~~~~~");
		logger.info("~~~~~~~~~~~~@RequestMapping(\"/test2\")~~~~~~~~~~~~~~~");
		logger.info("test2,username:" + username);
		return "test";
	}
Controller to View
(1)ModelAndView

①添加模型数据:
ModelAndView addObject(String attributeName,Object attributeValue):该方法的第一个参数为key值,第二参数为key对应的value。key需要保证在该Model的作用域内唯一即可。
ModelAndView addAllObjects(Map<String,?> modelMap):可以添加Map对象到Model中。
②设置视图:
void setView(View view):指定一个具体的视图(也就是说相对应于根目录的路径)
void setViewName(String viewName):指定一个逻辑视图,通过视图解析器,得到路径

	@RequestMapping("/test_ModelAndView")
	public ModelAndView test_ModelAndView(@RequestParam(value = "username",required = false) String username,@RequestParam(value = "password",required = false) String password) {
		System.out.println("~~~~~~~~~~~~@RequestMapping(\"/test_ModelAndView\")~~~~~~~~~~~~~~~");
		logger.info("~~~~~~~~~~~~@RequestMapping(\"/test_ModelAndView\")~~~~~~~~~~~~~~~");
		ModelAndView mView = new ModelAndView();
		logger.info("test_ModelAndView,username:" + username);
		logger.info("test_ModelAndView,username:" + password);
		mView.addObject("username2",username);		//这里第一个参数是key,第二个参数是value。即在mView中添加一对KV
		mView.addObject("password2",password);
		mView.setViewName("test");					//这里给mView指定一个逻辑视图名,在return后通过视图解析器,能够去访问test.jsp文件(带着上面两个参数)
		return mView;
	}
(2)Model

这里比较ModelAndView而言好像没什么优势,addAttribute和上面的addObject一样,还能放入javaBean(如Pojo.user),jsp中用下面代码来接收。

	<div>user.username:&emsp; ${user.username}</div>
	@RequestMapping("/test_Model")
	//在参数中添加Model,用addAttribute方法添加KV,就可以了,SpringMVC负责将Model传动给前端
	public String  test_Model(@RequestParam(value = "username",required = false) String username,@RequestParam(value = "password",required = false) String password,Model model) {
		System.out.println("~~~~~~~~~~~~@RequestMapping(\"/test_Model\")~~~~~~~~~~~~~~~");
		logger.info("~~~~~~~~~~~~@RequestMapping(\"/test_Model\")~~~~~~~~~~~~~~~");
		logger.info("test_Model,username:" + username);
		logger.info("test_Model,password:" + password); 
		User user = new User();
		user.setUsername("user.username");
//		user = userService.getUserByUsernameAndPassword(username, password);
		model.addAttribute("username2",username);		//这里第一个参数是key,第二个参数是value。即在mView中添加一对KV
		model.addAttribute("password2",password);
		model.addAttribute("user",user);
		return "test";
	}
(3)Map

和上面Model一样,因为它本身就是一个Map形式的数据结构,所以在上面代码中做出如下修改,然后参数放入的方法使用map的方法put就可以了

public String  test_Model(@RequestParam(value = "username",required = false) String username,@RequestParam(value = "password",required = false) String password,Map<String,Object> model) {
	.....
	model.put("user",user);
	.....
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值