SpringMVC
SpringMVC是一个非常优秀的MVC(Model-View-Control)框架,另外一个是Struts2.
SpringMVC的流程图
- 用户发起请求到前端控制器,前端控制器需要在web.xml里进行配置
<!-- 配置前端控制器 SpringMVC的核心 -->
<servlet>
<servlet-name>ssm</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置SpringMVC需要加载的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ssm</servlet-name>
<!-- 拦截所有请求 -->
<url-pattern>/*</url-pattern>
</servlet-mapping>
- 前端控制器找到处理器映射器,通过url找到对应的Handler,这一步需要springmvc.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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 扫描web相关的bean --> <context:component-scan base-package="sakura.ayane.controller"/> <!-- 开启SpringMVC注解模式 --> <mvc:annotation-driven/> <!-- 静态资源默认servlet配置 --> <mvc:default-servlet-handler/> <!-- 配置jsp 显示ViewResolver --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
- HandlerMapping找到url对应的处理器将其返回,在返回前,会加上很多拦截器
- DispatcherServlet拿到Handler之后,找到HandlerAdapter,通过它来访问处理器
- 执行处理器,即在Controller里调用 业务层Service,Service里调用数据层Dao处理数据
- 处理器会返回一个ModelAndView对象给HandlerAdapter
- 通过HandlerAdaptor将ModelAndView对象返回给DispatcherServlet
- DispatcherServlet请求ViewResolver进行视图解析,根据逻辑视图名解析成真正的视图,本质上就是将ModelAndView对象中存放的视图名字找到对应的页面形成视图对象
- 返回视图对象给DispatcherServlet
- 视图渲染,就是将ModelAndView 对象中的数据放到request域中,用来让页面加载数据
- 将得到数据返回给用户浏览器 显示页面
package sakura.ayane.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import sakura.ayane.pojo.User;
import sakura.ayane.service.UserService;
@Controller
public class UserController {
@Autowired
private UserService userService;
/**
* 1. 如果需要返回数据和视图 可以使用ModelAndView
* 2. 如果只需要返回页面,可以直接返回页面对应的字符串
* 3. 如果只需要返回数据,可以使用@ResponseBody
* 4. 如果方法需要传递的参数是JSON格式,可以在参数前面,加上@RequestBody
* 5. 以上两种方法使用时,需注意添加jackson的依赖
* @param id
* @return
*/
@RequestMapping("/user/select")
@ResponseBody
public ModelAndView selectUser(int id){
User user = userService.selectUser(id);
ModelAndView mv = new ModelAndView();
mv.addObject("name", user.getName());
mv.addObject("password", user.getPassword());
mv.setViewName("/success");
return mv;
}
}
Mybatis
Mybatis是一个支持普通SQL查询,存储过程和高级映射的优秀的持久层框架。
使用Mapper接口开发
按照一定的规范编写Mapper接口和Mapper.xml,mybatis就可以利用反射机制自动生成相关的mapper代理的实现类对象
Mapper.xml
mapper.xml映射文件定义了操作数据库的sql。映射文件内的常用属性有:
- ParameterType 输入数据类型
-
简单类型 需要注意结合 #{ } 和¥{} 的使用
- #{} 相当于站位符? ,会自动进行java类型和jdbc类型的数据转换,可以防止sql注入,可以接收简单类型和pojo属性值,如果是简单类型,括号内可以是value或者其它名称
- ${} 可以将传入的内容拼接在sql中,且不会进行jdbc类型转换,可以接收简单类型和pojo属性值,如果是简单类型,括号内必须是value
<!-- 根据id查询用户信息 --> <select id="findUserById" parameterType="int" resultType="user"> select * from user where id = #{id} </select> <!-- 根据名称模糊查询用户信息 --> <select id="selectUserByName" parameterType="string" resultType="user"> select * from user where username like '%${value}%' </select>
-
传递pojo对象,mybatis使用ognl表达式解析对象字段的值
<!--传递pojo对象查询用户信息--> <select id="findUserByUser" parameterType="user" resultType="user"> select * from user where id=#{id} and username like '%${username}%' </select>
- 传递pojo包装对象
package sakura.ayane.pojo; public class QuerVo { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; }
-
}
<select id="findUser" parameterType="sakura.ayane.pojo.QuerVo" resultMap="sakura.ayane.pojo.User">
select * from user where name like '%${user.name}%'
</select>
- 传递HashMap 一般用户pojo与数据库中字段不一致的情况下
<select id="findUserByIdMap" parameterType="hashmap" resultType="com.luchao.mybatis.first.po.User">
select * from user where id = #{id}
</select>
- parameterMap和resultMap
resultType可以将查询结果映射为指定的pojo,但是需要pojo的属性名和sql查询的列名一致,当其不一致时,可以使用resultMap将字段名和属性名做一个对应关系,resultMap实质上还是将查询结果映射到pojo对象中,使用resultMap可以实现将查询结果映射为复杂类型的pojo,例如查询结果包含pojo和list时<resultMap type="Book.dao.Book" id="BookResultMap"> <id column="id" property="id"/> <result column="name" property="bookName"/> <result column="price" property="bookPrice"/> </resultMap> <!-- resultMap:resultMap的id ,bookName:resultMap的property,即实体类中的属性 --> <parameterMap type="Book.dao.Book" id="BookParameterMap"> <parameter property="bookName" resultMap="BookResultMap" /> <parameter property="bookPrice" resultMap="BookResultMap" /> </parameterMap> <!-- 保存一个Book --> <insert id="saveBook" parameterMap="BookParameterMap"> insert into BOOK_MANAGE (ID,NAME,PRICE) values (Bookmanage_Seq.Nextval,#{bookName},#{bookPrice}) </insert> <!-- 根据ID修改Book --> <update id="updatePersnById" parameterMap="BookParameterMap"> update BOOK_MANAGE set NAME=#{bookName}, PRICE=#{bookPrice} WHERE id=#{id} </update> <!-- --> <resultMap type="user" id="userMap"> <id column="id_" property="id" /> <result column="username_" property="username" /> </resultMap> <select id="findUserMapById" parameterType="java.lang.Integer" resultMap="userMap" > select id id_,username username_ from user where id = #{id} </select>
- resultType输出类型
- 输出简单类型
<select id="findUserCount" parameterType="user" resultType="int"> select count(1) from user </select>
- 输出pojo对象
<!-- 根据id查询用户信息 --> <select id="findUserById" parameterType="int" resultType="user"> select * from user where id = #{id} </select>
- 输出pojo列表
<!-- 根据名称模糊查询用户信息 --> <select id="findUserByUsername" parameterType="string" resultType="user"> select * from user where username like '%${value}%' </select>
- 输出hashmap
<!-- 根据名称模糊查询用户信息 --> <select id="findUserByUsername" parameterType="string" resultType="hashMap"> select * from user where username like '%${value}%' </select>
- 输出简单类型
动态sql
mybatis的核心,对sql语句进行灵活的拼接,组装。
- if
<select id="selectByExample" resultType="user" parameterType="user" >
select * from user
where 1=1
<if test="id != null and id != ''" >
and id = #{id}
</if>
</select>
- where
<select id="selectByExample" resultType="user" parameterType="user" >
select * from user
<where>
<if test="id != null and id != ''" >
and id = #{id}
</if>
</where>
</select>
- foreach 当某个查询条件有多个值,传入的参数为数组或者List的时候
<select id="selectByExample" resultType="user" parameterType="java.util.list" >
select * from user
<where>
<if test="list!=null">
<foreach collection="list" item="item" open="and id in(" separator="," close=")">
#{item.id}
</foreach>
</if>
</where>
</select>
<select id="selectByExample" resultType="user" parameterType="Obejct[]" >
select * from user
<where>
<if test="array!=null">
<foreach collection="array" index="index" item="item" open="and id in(" separator="," close=")">
#{item.id}
</foreach>
</if>
</where>
</select>
- sql片段
<sql id="query_user_where">
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</sql>
<select id="findUserList" parameterType="user" resultType="user">
select * from user
<where>
<include refid="query_user_where"/>
</where>
</select>
如果引用的是其他mapper的片段,引用时需要加上namespace,如:
<include refid="namespace.sql片段">
Spring
Spring是一个整合性框架,其核心为:
- IOC: Inversion Of Control ,控制反转,即将对象的创建和管理交给spring管理,有助于对象之间的解耦
- AOP: Aspect Oriented Programming ,面向切面编程
自动装配检测Bean
在springmvc.xml中配置<context:component-scan>
查找使用注解标注的类,这些注解如下:
- @Component 通用的构造性注解,标识该类为Spring组件
- @Controller 标识该类定义为SpringMVC Controller,一般用在WEB层
- @Service 标识该类定义为服务,一般用在Service层
- @Repository 标识该类定义为数据仓库,一般用在Dao层
AOP的用法
AOP主要包含了通知,切点和连接点
- 通知 定义了切面是什么以及何时调用
- 切点 定义了切处,切点的定义如下:
execution (* package.class.*(..))
- 连接点 连接点是应用执行过程中能够插入切面的一个点,这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时,切面代码可以利用这些连接点插入到应用的正常流程中,并添加新的行为,如日志,安全,事务,缓存等
Spring整合 SpringMVC Mybatis
- 在web.xml里配置Spring的相关信息
<!-- 初始化Spring的容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext-*.xml</param-value>
</context-param>
<!-- 加载Spring的监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- 整合数据库配置,连接池配置,扫描Mapper
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 加载数据库配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置连接池信息 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置SqlSessionFactory -->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 加载mybatis配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/>
<!-- 加载数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 扫描Mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="sakura.ayane.mapper"/>
</bean>
</beans>
- 整合service层
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 扫描service -->
<context:component-scan base-package="sakura.ayane.service.impl"/>
</beans>
- 整合事务管理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 传播行为 -->
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 切面 -->
<aop:config>
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* sakura.ayane.service.impl.*(..))" />
</aop:config>
</beans>