MyBatis
介绍:iBATIS 一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架.iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO),同时还提供一个利用这个框架开发的 JPetStore实例.
总体来说 MyBatis 主要完成两件事情:
1.根据 JDBC 规范建立与数据库的连接.
2.通过Annotaion/XML+JAVA反射技术,实现 Java 对象与关系数据库之间相互转化.
Hibernate(ORM) MyBatis3(SQL语句映射)
SessionFactory SqlSessionFactory
Session SqlSession
Session : 会话(持续的一段有效时间)
HttpSession : 代表浏览器打开到浏览器关闭.
Session : 代表数据库连接(Connection)的获取到数据库连接的关闭.
SqlSession : 代表数据库连接(Connection)的获取到数据库连接的关闭.
MyBatis3下载与安装:
-- 下载地址: https://github.com/mybatis/mybatis-3/releases
-- mybatis-3.3.0.zip | mybatis-3-mybatis-3.3.0.zip (2015.5.24)
-- 解压mybatis-3.3.0.zip:
-- lib : 存放的是第三方的jar(需要依赖的jar).
-- mybatis-3.3.0.jar (自己的jar).
-- mybatis-3.3.0.pdf (学习文档).
MyBatis3入门
1:拷贝jar包
拷贝jar(mybatis-3.3.0\lib\*.jar、mybatis-3.3.0.jar、mysql驱动).
2:在src目录下提供全局配置文件
mybatis-config.xml
MyBatis的CRUD
第一种(基于映射文件)
xxxMapper.xml(命名空间,用来匹分不同的sql语句).
<insert/>
<update/>
<delete/>
<select/>
一张表对应一个sql语句映射文件.
插入数据:
-- 定义sql语句:
<insert id="save"> sql语句 </insert>
-- 执行插入数据的方法:
int res = sqlSession.insert("namespace(配置文件的命名空间).id(定义sql语句的id)", 插入的参数);
可以返回int类型res :受影响的记录条数.
<insert/>可以设置的类型:
useGeneratedKeys:是否返回主键id, 是否用生成的主键列的值
keyColumn : 指定主键列的列名(表的)
keyProperty: 指定封装数据对象的属性名(类的)
例如:<insert id="save2" keyColumn="ID" keyProperty="id" useGeneratedKeys="true"/>
可以配置全局的返回主键id值
(在MyBatis配置文件中配置)
<settings>
<!-- 配置用生成的主键值 -->
<setting name="useGeneratedKeys" value="true"/>
</settings>
修改数据:
定义sql语句:
<update id="update">
update province set name = #{name}, create_date = #{createDate} where id = #{id}
</update>
-- 执行update语句的方法.
int res = sqlSession.update("namespace(配置文件的命名空间).id(定义sql语句的id), "参数");
删除数据:
<delete id="delete">
delete from province where id = #{id}
</delete>
-- 执行delete语句的方法.
int res = sqlSession.delete("namespace(配置文件的命名空间).id(定义sql语句的id), "参数");
查询数据:
<select id="唯一标识符" resultType="cn.itcast.mybatis.pojo.Province">
查询的sql语句
</select>
<select>可以设置的类型
-- resultType: 返回类型(查询表中数据用哪个类来封装,如果要引用类型必须完整路径类名)
<select id="get2" resultType="cn.itcast.mybatis.pojo.Province">
SELECT p.id, p.name,p.create_date AS createDate FROM province AS p where p.id = #{id}
</select>
-- resultMap:自定义类型(可以配置全局引用类型,通过resultMap引入)
<resultMap type="cn.itcast.pojo.Province(接口名或类名)" id="provineMap(自定义别名)" autoMapping="true(是否自动装配)">
<!--
column : 列名
property : 属性名
字段名和类的属性值名一样可以不配,不一致必须配
-->
<result column="CREATE_DATE" property="createDate"/>
</resultMap>
(如果在配置文件扫描实体包,type可以不写完整包名只写类名)
查询返回数据是通过session给的类型
-- 查询返回一个集合:
List<T> lists = sqlSession.selectList();
-- 查询返回一条记录:
Province p = sqlSession.selectOne();
第二种(基于数据访问接口 +映射文件)
1:需要定义数据访问接口类
2:需要 xxxMapper.xml SQL语句定义文件.:
ProvinceMapper.xml 映射文件中命名空间必须填写接口的完整路径名
namespace="cn.itcast.mybatis.mapper.ProvinceMapper"
原因:
代表ProvinceMapper.xml 文件中的SQL语句用ProvinceMapper类中的方法进行操作.
约定:ProvinceMapper接口中的方法必须为ProvinceMapper.xml文件中的sql语句id值.
3:获取数据访问接口代理对象
provinceMapper = session.getMapper(ProvinceMapper.class);
注意:
1:映射文件CRUD中的id名必须填写对应的接口方法名
映射文件:
<insert id="save1">
insert into province(name, create_date) values(#{name},#{createDate})
</insert>
接口类:
public int save1(Province province);
2:通过ProvinceMapper代理点出初入的接口方法
第三种(基于数据访问接口 + 注解 + 映射文件.)
1:定义数据接口类
2:定义xxxMapper.xml SQL映射文件
3:在接口方法上使用注解写入CRUD语句
添加:@Insert("sql语句")
@SelectKey(keyColumn="id", // 主键列的列名
before=false, // 插入之后返回id值
keyProperty="id", // Province对象中的属性
statement="select last_insert_id()", // 查询语句
resultType=Integer.class) // 返回的主键列数据类型
修改:@Update("sql语句")
@Update("update province set name = #{name}, create_date = #{createDate} where id = #{id}")
#{name} --> 如果是对象就调它的getName方法
#{name} --> 如果是Map集合就根据它的key取value.
删除:@Delete("sql语句")
查询:@Select("sql语句")
@ResultType() // 返回的数据类型
@Select("select * from province where id = #{id}")
@ResultMap("provinceMap") // 引用ProvinceMapper.xml中的<resultMap/>的id值
动态sql语句
在第二种基础之上进行改进,在映射文件中写入:
<select id="find1" resultMap="provineMap">
select * from province
<where>
<if test="name !=null && name!=''">
name like CONCAT('%'+#{name}+'%')
</if>
<if test="id >0">
and id >#{id}
</if>
</where>
</select>
可以加入条件语句
Where标签
-- <where/> : 会根据它里面的if条件生成where字符串
If标签
-- <if> :
条件判断.
<if test="name != null && name != ''">
name like CONCAT('%', #{name},'%')
</if>
For标签
<foreach> :
迭代集合或者数组
<!-- 迭代集合或者数组
collection : list集合 、 array数组
open : 打开时加什么
close : 关闭时加什么
separator : 中间分隔符
item : 数组元素
-->
<foreach collection="array" item="id" open="(" separator="," close=")">
#{id}
</foreach>
Set标签
修改时用,会根据它里面的if条件生成set字符串.
update province
<set>
<!-- 判断name -->
<if test="p.name != null && p.name !=''">
name = #{p.name},
</if>
<if test="p.createDate != null">
create_date = #{p.createDate},
</if>
</set>
Trim标签
在sql语句字符串前后添加什么
<!--
prefix : 前缀加什么
suffix: 后缀加什么
-->
<trim prefix="select * from province" suffix="order by id asc">
<where>
<if test="name != null && name !=''">
name like concat('%',#{name},'%')
</if>
</where>
</trim>
可以定义全局的sql语句片段
<sql id="sql1">
from province
<where>
<if test="province.name!=null && province.name!=''">
name like CONCAT('%'+#{province.name}+'%'")
</if>
<if test="province.id > 0">
and id >#{province.id}
</if>
</where>
</sql>
注意:
1:在接口定义方法中,由于传多个参数会无法识别,需要在方法传值中用参数标签声明
List<Province> finByPage(@Param("province")Province province,
@Param("id")int start,
@Param("name")int page);
(1):方法中只传一个对象可以不写注解
(2):方法中只传map集合可以不写注解
(3):方法中只传一个参数可以不写注解
(4):多个参数必须写(string也是对象)
关联映射
一对多
在xml映射文件中必须制定关联的属性,如果是单一对象的一方,用< association >标签,如果是集合对象的一方用< collection >。
单一对象的一方
<resultMap type="City" id="provinceMap" extends="beanCity">
<!-- 省份与城市存在1-N关联 List<City>
property : 指定关联的属性
column : 主键列(关联的列)
ofType : 指定集合中数据类型 City
javaType : 该关联的属性的java类型
select : 引用那个查询方法的id(完整路径名)
-->
<association property="province"
column="province_id"
javaType="Province"
select="cn.itcast.mapper.ProvinceMapper.get"/>
</resultMap>
有集合的一方
<resultMap type="Province" id="provineMap" extends="beanMap">
<!-- 省份与城市存在1-N关联 List<City>
property : 指定关联的属性
column : 主键列(关联的列)
ofType : 指定集合中数据类型 City
javaType : 该关联的属性的java类型
select : 引用那个查询方法的id(完整路径名)
-->
<collection property="cities" column="id"
ofType="City" javaType="list"
select="cn.itcast.mapper.CityMapper.finByPage"/>
</resultMap>
封装两张表时
<resultMap type="City" id="provinceMap2" extends="beanCity">
<association property="province" column="province_id" javaType="Province">
<result column="pid" property="id"/>
<result column="pname" property="name"/>
<result column="create_date" property="createDate"/>
</association>
</resultMap>
多对多
两边都是用集合定义属性
需要查询的一边集合
<resultMap type="Teacher" id="teacherMap" autoMapping="true">
<collection property="students" column="id"
ofType="Student" javaType="java.util.Set"
select="cn.itcast.mapper.StudentMapper.findByPage"/>
</resultMap>
集合需要存放的对象
<select id="findByPage" resultType="Student">
SELECT s.* FROM `tea_2_stu` AS ts, `student` AS s, `teacher` AS t
WHERE ts.`STU_ID` = s.`ID` AND ts.`TEA_ID` = t.`ID` AND t.`ID` = #{id}
</select>
延迟加载和缓存
延迟加载
在MyBatis-config.xml配置文件,全局配置<settings>标签里,写入
1:lazyLoadingEnabled与aggressiveLazyLoading必须指定两个的值才能实现延迟加载
<!-- 全局的属性设置 -->
<settings>
<!-- 配置用生成的主键值 -->
<setting name="useGeneratedKeys" value="true"/>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置按需要加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 配置使用缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
对象缓存
1:除了在MyBatis-config.xml配置文件中需要写入cacheEnabled为开启
2:还需要在映射文件中进行配置
<!-- 配置使用缓存
eviction : 缓存中对象的淘汰算法:LRU(Least Recently Used)近期最少使用算法|FIFO(First Input First Output)先入先出队列
flushInterval: 指缓存过期时间(单位为毫秒)
readOnly : 是否只读
size : 指缓存多少个对象(默认值为1024)
-->
<cache eviction="LRU"
flushInterval="60000"
readOnly="true"
size="1024"/>
Spring
Spring整合MyBatis
在applicationContext.xml配置文件中
1:配置SqlSessionFactory
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="dataSource" //注入数据源
p:configLocation="classpath:mybatis-config.xml" //读取配置文件
p:typeAliasesPackage="cn.itcast.ssm.pojo" //扫描包下实体类并根据类名创建实体
p:mapperLocations="classpath:mapper/*.xml"/> //扫描映射文件
2:配置数据访问接口代理对象Bean
单个配置
<bean id="noticeMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"
p:mapperInterface="cn.itcast.ssm.mapper.NoticeMapper"
p:sqlSessionFactory-ref="sqlSessionFactory"/>
批量配置包扫描(推荐)
<!-- 配置数据访问接口代理对象Bean(批量配置,采用包扫描)
它扫描基础包下所有的数据访问接口类,扫描后会创建接口的代理对象,再交由Spring容器
bean的id默认为接口的类名首字小写-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
p:sqlSessionFactoryBeanName="sqlSessionFactory"
p:basePackage="cn.itcast.ssm.mapper"/>
3:配置数据源事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
4:声明式事务配置
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 定义事务属性 -->
<tx:attributes>
<!-- set方法开头只能做查询 read-only(true) 没有开启事务 -->
<tx:method name="set*" read-only="true"/>
<!-- get方法开头只能做查询 read-only(true) 没有开启事务 -->
<tx:method name="get*" read-only="true"/>
<!-- 剩余的方法可以做CUD R(查询也可以做) read-only(false) 开启了事务 -->
<tx:method name="*" read-only="false" rollback-for="java.lang.RuntimeException"/>
</tx:attributes>
</tx:advice>
5:需要另外配置的全局属性需要创建一个MyBatis-config.xml配置文件
<!-- 全局的属性设置 -->
<settings>
<!-- 配置用生成的主键值 -->
<setting name="useGeneratedKeys" value="true"/>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置按需要加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 配置使用缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
整合SSM
配置Spring配置文件
添加并配置“applicationContext.xml”文件;主要配置组件扫描(service/mapper),属性文件,数据源,事务控制。
<context:component-scan base-package="cn.itcast.ssm.service.impl"></context:component-scan>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<!-- 允许JVM参数覆盖 -->
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<!-- 忽略没有找到的资源文件 -->
<property name="ignoreResourceNotFound" value="true" />
<!-- 配置资源文件 -->
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<!-- 数据库驱动 -->
<property name="driverClass" value="${jdbc.driver}" />
<!-- 相应驱动的jdbcUrl -->
<property name="jdbcUrl" value="${jdbc.url}" />
<!-- 数据库的用户名 -->
<property name="username" value="${jdbc.username}" />
<!-- 数据库的密码 -->
<property name="password" value="${jdbc.password}" />
<!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 -->
<property name="idleConnectionTestPeriod" value="60" />
<!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 -->
<property name="idleMaxAge" value="30" />
<!-- 每个分区最大的连接数 -->
<property name="maxConnectionsPerPartition" value="150" />
<!-- 每个分区最小的连接数 -->
<property name="minConnectionsPerPartition" value="5" />
</bean>
<!-- 定义事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 定义事务策略 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--所有以query开头的方法都是只读的 -->
<tx:method name="query*" read-only="true" />
<!--其他方法使用默认事务策略 -->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- 配置切入点 -->
<aop:config>
<aop:pointcut id="myPointcut" expression="execution(* cn.itcast.ssm.service.impl.*.*(..))" />
<!--将定义好的事务处理策略应用到上述的切入点 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" />
</aop:config>
</beans>
添加jdbc.properties和log4j.properties文件
配置spring与mybatis的配置文件
添加并配置“applicationContext-mybatis.xml”文件;主要配置sqlSessionFactory和mapper接口的扫描。
<!-- 定义Mybatis的SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 设置Mybatis的总配置文件路径 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<!-- 设置所有mapper文件的路径 -->
<property name="mapperLocations" value="classpath:mybatis/mappers/*.xml"></property>
<!-- 设置类型别名 -->
<property name="typeAliasesPackage" value="cn.itcast.ssm.pojo"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- mapper接口所在的包 -->
<property name="basePackage" value="cn.itcast.ssm.mapper"></property>
</bean>
</beans>
配置spring MVC配置文件
添加并配置“xxx-servlet.xml”配置文件;主要配置注解驱动、属性文件、处理器扫描、视图解析器等。
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<!-- 允许JVM参数覆盖 -->
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<!-- 忽略没有找到的资源文件 -->
<property name="ignoreResourceNotFound" value="true" />
<!-- 配置资源文件 -->
<property name="locations">
<list>
<value>classpath:env.properties</value>
</list>
</property>
</bean>
<!-- 注解驱动 -->
<mvc:annotation-driven/>
<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
<!-- 配置视图解析器 -->
<!-- Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp" -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 定义文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置默认字符编码 -->
<property name="defaultEncoding" value="uft-8"></property>
<!-- 设置最大上传文件大小(单位B)5*1024*1024=5242880B=5MB -->
<property name="maxUploadSize" value="5242880"></property>
</bean>
<!-- 解决静态资源404问题 -->
<mvc:default-servlet-handler/>
</beans>
配置web.xml文件
在web.xml文件中;设置spring的监听器、字符过滤器、spring mvc的servlet配置等信息。
<?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_3_0.xsd"
id="WebApp_ID" version="3.0">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext*</param-value>
</context-param>
<!-- 解决rest时put方式提交无法获取表单数据 -->
<filter>
<filter-name>httpPutFormContentFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpPutFormContentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 解决rest时delete方式提交无法获取表单数据,通过post添加_method参数模拟delete方式 -->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-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>
<!-- 配置spring mvc前端控制器 -->
<servlet>
<servlet-name>ssm</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/ssm-servlet.xml</param-value>
</init-param>
<!-- 随着应用服务器启动而初始化 若不配置,则第一次请求后完成初始化 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ssm</servlet-name>
<!-- ssm的映射规则: 可以配置:/、/xxx/*、*.* 不可配置:/* 与应用服务器配置默认冲突 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<display-name>ssm</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Restful风格
什么是Rest:
REST是一种设计风格。它不是一种标准,也不是一种软件,而是一种思想。
RESTful风格的一大特色就是使用URI来标识资源。
URI:统一资源标识符(Uniform Resource Identifier)-- 抽象资源
请求方法:
GET:获取一个资源
POST:新增一个资源
PUT:更新一个资源的状态
DELETE:删除一个资源
接口定义:
http方法 |
资源操作 |
幂等 |
安全 |
GET |
SELECT |
是 |
是 |
POST |
INSERT |
否 |
否 |
PUT |
UPDATE |
是 |
否 |
DELETE |
DELETE |
是 |
否 |
幂等性:对同一REST接口的多次访问,得到的资源状态是相同的。
安全性:对该REST接口访问,不会使服务器端资源的状态发生改变。
响应状态码:
Spring MVC实现RESTful:
Spring MVC原生态的支持了REST风格的架构设计。Spring MVC 对 RESTful应用提供了以下支持:
l 利用@RequestMapping 指定要处理请求的URI和HTTP请求的动作类型
l 利用@PathVariable将URI请求模板中的变量映射到处理方法参数上
l 利用Ajax,在客户端发出PUT、DELETE动作的请求
书写格式:
Get请求(获取参数):
访问方法:
Post请求(新增用户):
访问方法:
、
Put请求(修改用户):
配置过滤器;由于put方式在提交表单数据时不能在后台中获取到,所以在web.xml中添加过滤器实现put方式获取数据;
<filter>
<filter-name>httpPutFormContentFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpPutFormContentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
访问方式
Delete(删除用户):
配置过滤器:由于delete方式提交时后台无法获取表单数据,只能通过POST方式并在提交的过程中附带_method参数指定值为DELETE,模拟DELETE提交;所以也需要在web.xml中添加过滤器;
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
请求方式:
SpringMVC
SpringMVC与Struts2区别
1:SpringMVC的入口是Servlet,Struts2的入口是Filter,两者的实现机制不同。
2:SpringMVC基于方法设计,传递参数是通过方法形参,其实现是单例模式(也可以改为多例,推荐用单例),Struts2基于类设计,传递参数是通过类的属性,只能是多例实现,性能上SpringMVC更高一些。
3:参数传递方面,Struts2是用类的属性接收的,也就是在多个方法间共享,而SpringMVC基于方法,多个方法间不能共享。
页面REST插件测试
1:注意:需要穿json格式需要改选项
2:需要多个参数可以选择
SpringMVC执行流程
开发SpringMVC步骤
1:配置web.xml
<!-- 配置spring mvc前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 随着应用服务器启动而初始化
若不配置,则第一次请求后完成初始化
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
springmvc的映射规则:
可以配置:/、/xxx/*、*.*
不可配置:/* 与应用服务器配置默认冲突
-->
<url-pattern>*.mvc</url-pattern>
</servlet-mapping>
【注意】DispatcherServlet的配置文件路径默认为:
/WEB-INF/{servlet-name}-servlet.xml ,这个名称可以通过contextConfigLocation参数修改。
2:配置映射器
<!-- 注解驱动这一步相当于配置了映射器与适配器 -->
<mvc:annotation-driven/>
<!-- 配置处理器 -->
<!-- <bean name="/hello.mvc" class="cn.itcast.springmvc.controller.HelloController"/> -->
<context:component-scan base-package="cn.itcast.springmvc.controller"/> // 包扫描
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
3:写处理器处理业务逻辑
@Controller
@RequestMapping("/demo") //相当于struts2的命名空间
public class DemoController {
@RequestMapping("/show1") //需要/demo加上此方法命名空间
public ModelAndView show1(){
ModelAndView mv = new ModelAndView("text");
mv.addObject("msg", "show1");
return mv;
}
转发:forward
重定向:redirect
注意:
@RequestMapping三种映射两种限定
映射:1.普通url地址,2.*通配符如/**/demo、/*/show1,3.占位符{abc}
如/show1/jkjf.mvc
限定:1.限定方法2.限定参数
1:@PathVariable标签指定的是页面访问的地址命名空间访问如下:/abcd/show6.mvc
@RequestMapping("/{userId}/show6")
public ModelAndView show6(@PathVariable("userId")String userId)
2: @RequestParam指定的是页面带参数的值例如:/show7.mvc?requestType=faafsa
3: @ResponseBody把json转为pojo对象,@RequestBody把pojo对象转为json字符串
4:所有在页面地址栏url上输入中文需要带入后台的参数,都和get请求转码一样,需要进行处理 :
byte[] bytes = userId.getBytes("iso-8859-1");
String id =new String(bytes,"utf-8");
mv.addObject("msg", "show4 "+id);
5:URLEncoder的编码和URLDecoder解码只能用于中文参数需要重定向到某个接参的方法进行url解码例如:
@RequestMapping("/show9")
public ModelAndView show9() throws Exception{
ModelAndView mv =new ModelAndView("redirect:show10.mvc");
mv.addObject("msg", URLEncoder.encode("张三", "utf-8"));
return mv;
}
@RequestMapping("/show10")
public ModelAndView show10(@RequestParam(value="msg")String requestType) throws Exception{
ModelAndView mv =new ModelAndView("text");
mv.addObject("msg", "这是我的第一个注解的spring mvc应用。方法为:show9重定向而来;携带数据"+URLDecoder.decode(requestType, "utf-8"));
return mv;
}
6.@Value("${PIC_UPLOAD_PATH}") 获取properties配置文件key值
private String PIC_UPLOAD_PATH;
*-servlet.xml配置文件进行配置
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<!-- 允许JVM参数覆盖 -->
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<!-- 忽略没有找到的资源文件 -->
<property name="ignoreResourceNotFound" value="true" />
<!-- 配置资源文件 -->
<property name="locations">
<list>
<value>classpath:env.properties</value>
</list>
</property>
</bean>
上传与下载
上传:
1:引入jar包
将commons-fileupload-1.3.1.jar,commons-io-2.4.jar引入项目
2:添加配置文件在**-servlet.xml文件
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置默认字符编码 -->
<property name="defaultEncoding" value="uft-8"></property>
<!-- 设置最大上传文件大小(单位B)5*1024*1024=5242880B=5MB -->
<property name="maxUploadSize" value="5242880"></property>
</bean>
3:单文件上传,在方法中引入(@RequestParam("file") MultipartFile multipartFile)
@RequestMapping("/upload1")
public String uploadFile1(@RequestParam("file") MultipartFile multipartFile){
try {
if(multipartFile != null){
//保存文件
//获取文件保存路径
String path = PIC_UPLOAD_PATH;
//保存文件
multipartFile.transferTo(new File(path,multipartFile.getOriginalFilename()));
}
} catch (Exception e) {
e.printStackTrace();
}
return "redirect:/success.jsp";
}
多文件上传用数组接收:@RequestParam("files") MultipartFile[] multipartFiles
@RequestMapping("/upload2")
public String upload2(@RequestParam("files") MultipartFile[] multipartFiles) throws Exception{
if (multipartFiles != null) {
//获取服务器中upload目录所在的服务器绝对路径
String path = servletContext.getRealPath("/upload");
for (MultipartFile mf : multipartFiles) {
//将上传的文件保存文件到指定路径
mf.transferTo(new File(path + File.separator + mf.getOriginalFilename()));
}
}
return "redirect:/success.jsp";
}
下载(Excel):
Spring MVC默认的Excel操作api组件为poi,所以需引入poi-xx.jar包到项目中。
具体和struts2一样
拦截器
使用场景:拦截器一般可使用的场景:日志记录、权限检查、性能监控、通用行为(本地化信息、主题信息)。
Spring MVC的拦截器接口定义了三个方法:
preHandle 调用handler之前执行;
postHandle 调用handler之后执行(如没调用执行handler将不执行此方法;也就是如果preHandle方法返回false的话,postHandle方法必定不执行);
afterCompletion 视图渲染完之后并且preHandle方法返回true时执行。
执行过程
当有多个拦截器时,按照上述执行过程,每个拦截器中的三个方法执行的顺序:preHandle按顺序执行,postHandle和afterCompletion都是逆序执行。
自定义拦截器:
1:使用HandlerInterceptor接口
2:添加拦截器配置(配置多个拦截器)
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**/**.mvc"/>
<bean class="cn.itcast.springmvc.interceptor.MyHandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**/**.mvc"/>
<bean class="cn.itcast.springmvc.interceptor.MyHandlerInterceptor2"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**/**.mvc"/>
<bean class="cn.itcast.springmvc.interceptor.MyHandlerInterceptor3"></bean>
</mvc:interceptor>
</mvc:interceptors>
静态资源404与日期问题
在web.xml中配置
当配置的DispatcherServlet的url-pattern为“/”时,意思是匹配所有资源,那么也就包括了系统的所有html、js、css、images等这些静态资源,而后台的Handler是无法处理静态资源的;导致找不到资源出现404报错。在Spring MVC中可以在配置文件中添加<mvc:default-servlet-handler/>解决此问题。意思是将静态资源转交给服务器处理
解决字符转日期问题
在表单中输入日期后提交到后台,如果接收的对象对应的属性类型为日期的那么会提交失败,原因是转换类型失败。解决此问题在Spring MVC中非常简单,在对应的对象的属性上添加@DateTimeFormat注解进行转换即可。具体如下: