基于流行SSM框架:Spring+SpringMVC+Mybatis
项目配置: 使用Maven进行项目jar导入
使用Git进行版本控制,并将每次编写的代码上传到Gitee进行保存
IDEA(装有Web相关插件以及Maven插件和Git插件)
Navcat(mysql 5.7 图形化管理工具)
JDK 1.8
IDEA中的Maven配置,Git配置,请自行查阅,网上有相关资源
Maven Repository : https://mvnrepository.com/
Gitee:https://gitee.com/
Gitee 项目仓库:https://gitee.com/xuzhi7162/SSM
GitHub项目仓库:https://github.com/xuzhi7162/SSM/tree/master/NewProject/JavaWebTest
(使用IntelliJ IDEA尝试开发)
Mybatis教程:https://blog.csdn.net/hellozpc/article/details/80878563#3Mybaits_109
SpringMVC文档地址(老版):https://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/htmlsingle/#overview-distribution-zip
##引入相关依赖
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
##在全局配置文件中添加相应的setting设置
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>
##在resources目录下建立log4j.properties配置文件,并在内部做出相应修改
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.xuzhi.mapper=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
###修改内容如下
官方语句为
log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE
修改为
log4j.logger.com.xuzhi.mapper=DEBUG
即将原先的org.mybatis.example.BlogMapper.selectBlog修改为你mapper所在的包,并将后面的TRACE修改为DEBUG以便于在控制台打印
##Mybatis的全局配置文件
<configuration>
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="xuzhi7162"/>
properties>
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>
<environments default="mybatis">
<environment id="mybatis">
<transactionManager type="JDBC" />
<dataSource type="UNPOOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/xuzhi/mapper/UserInfoMapper.xml" />
<package name="com/xuzhi/po"/>
mappers>
configuration>
##两种mapper引入方法:直接引入配置文件,引入实体类所在的包
##UserInfoMapper实体类的配置文件,该配置文件必须在全局配置文件mybatis.cfg,xml中注册
<mapper namespace="com.xuzhi.mapper.UserInfoMapper">
<insert id="insert" parameterType="com.xuzhi.po.UserInfo">
insert into user_info(user_name,user_pass,user_phone) values(#{userName},# {userPass},#{userPhone})
insert>
mapper>
##对相应数据表的GRUD操作的语句都写于该配置文件中,
#{}和${}
#{} 只是替换?,相当于PreparedStatement使用占位符去替换参数,可以防止sql注入。
是 进 行 字 符 串 拼 接 , 相 当 于 s q l 语 句 中 的 S t a t e m e n t , 使 用 字 符 串 去 拼 接 s q l ; {} 是进行字符串拼接,相当于sql语句中的Statement,使用字符串去拼接sql; 是进行字符串拼接,相当于sql语句中的Statement,使用字符串去拼接sql;可以是sql中的任一部分传入到Statement中,不能防止sql注入。
注:所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
##用与返回SqlSession
package com.xuzhi.util;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
/**
* 单例类,在程序中仅有一个类
* @author 绪志
*
*/
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;
/**
* 静态代码块,在程序的所有运行过程中,该代码块仅执行一次,类似于单例
*/
static {
//指定全局配置文件
String resource="mybatis.cfg.xml";
InputStream in=null;
try {
//读取配置文件
in = Resources.getResourceAsStream(resource);
//构建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static SqlSession getSession(){
//返回SqlSession
return sqlSessionFactory.openSession();
}
}
package com.xuzhi.mapper;
import com.xuzhi.po.UserInfo;
/**
* 该接口中主要是对UserInfo实体类的GRUD操作,不需要实现该接口,仅需要在UserInfoMapper.xml中添加相应的sql语句既可
* @author 绪志
*
*/
public interface UserInfoMapper {
int insert(UserInfo userInfo);
}
##推荐使用注解方法 @Param()
/**
* 通过name和flower进行复合查询,通过注解可以在mapper的配置文件中直接使用#{name}和#{flower}来接收参数
* 否则必须使用mybatis默认的参数接收方式,param1,param2或者arg0,arg1
* 推荐使用注解的方式来进行传递参数
* @param name
* @param flower
* @return
*/
Girl queryByNameFlower(@Param("name") String name,@Param("flower") String flower);
##通过就Javabean进行参数传递
/**
* 通过javabean来传递参数
* mapper.xml中调用参数时只需要使用实体类中的属性名即可
* @param girl
* @return
*/
Girl queryByNameFlower1(Girl girl);
###在传入多个javabean时,在接收参数时可以使用param1.XXX,此方法是不友好的,可以在定义方法时使用@Param注解,
例:@Param(“a”) Girl girl==========使用时可以使用"a.XXX"
##通过hashmap进行参数传递(在mapper中按照键的名称取值)
/**
* 通过hashmap传参
* @return
*/
Girl queryByNameFlower2(Map<String,Object> map);
##本部分没有做测试类,完全摘自Mybatis官方文档
if
choose (when, otherwise)
trim (where, set)
foreach
bind
sql
动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如:
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
AND state = #{state}
if>
<if test="title != null">
AND title like #{title}
if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
if>
where>
select>
##在使用where条件是可以使用专门的标签,从而使mybatis自动处理查询条件前面的‘and’关键字,推荐在所有的if语句中所有的查询关键字前面都加上and关键字,即使是第一个在其内容中也要加入and关键字,因为mybatis会帮我们处理好这个and关键字,例如
<where>
<if test="state != null">
AND state = #{state}
if>
where>
##有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
when>
<otherwise>
AND featured = 1
otherwise>
choose>
select>
标签代码同标签内的代码
标签可以看成为的自定义标签,可以通过内部的某些属性来处理AND/OR,还可以处理“,”
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
trim>
###官方文档没有完全给出标签内的所有属性,具体使用时需要具体百度
标签可以处理标签中多余的“,”,例如update中的set后项目的“,”
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},if>
<if test="password != null">password=#{password},if>
<if test="email != null">email=#{email},if>
<if test="bio != null">bio=#{bio},if>
set>
where id=#{id}
update>
###同标签处理AND/OR一样,可以在每个语句的后面都填上“,”,标签都可以帮我们处理掉
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
foreach>
select>
· item:自命名,用来表示需要遍历的集合的其中的一个子项
·index:当前遍历到的下标
·collection:需要遍历的类型 #list、set、map
·open:以什么为开始
·separator:每个子项之间用什么符号分隔开
·close:以什么为结尾
上述代码可“编译出”,
select * from post p where ID in (a,b,c,d)
###bind
元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
select>
这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中。它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化. 比如:
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password sql>
这个 SQL 片段可以被包含在其他语句中,例如:
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/>include>,
<include refid="userColumns"><property name="alias" value="t2"/>include>
from some_table t1
cross join some_table t2
select>
##使用mybatis处理一般的单表时常使用resultType属性,但是用mybatis处理多表查询时,使用resultType进行结果集的封装不太适用,所以此时要使用自定义封装结果集,多使用resultMap进行自定义结果集的封装
##简要说明,一对一举例,一个用户拥有自己独特的个人信息,一个用户对应一个用户详情信息
<方法一:使用assocation进行具体对象的封装>
<mapper namespace="com.xuzhi.mapper.GirlDetailMapper">
<resultMap id="BaseGirlDetail" type="com.xuzhi.model.GirlDetail">
<id property="id" column="uid" />
<result property="name" column="name" />
<result property="flower" column="flower" />
<result property="birthday" column="birthday" />
resultMap>
<resultMap id="GirlWithDetailMap" type="com.xuzhi.model.GirlDetail">
<id property="id" column="uid" />
<result property="name" column="name" />
<result property="flower" column="flower" />
<result property="birthday" column="birthday" />
<association property="girlWithDetail" javaType="com.xuzhi.model.GirlWithDetail">
<id property="gid" column="gdid" />
<result property="address" column="address" />
association>
resultMap>
<resultMap id="GirlWithDetailMap2" type="com.xuzhi.model.GirlDetail">
<id property="id" column="uid" />
<result property="name" column="name" />
<result property="flower" column="flower" />
<result property="birthday" column="birthday" />
<result property="girlWithDetail.gid" column="gdid" />
<result property="girlWithDetail.address" column="address" />
resultMap>
<resultMap id="GirlWithDetailMap3" extends="BaseGirlDetail" type="com.xuzhi.model.GirlDetail">
<association property="girlWithDetail" select="com.xuzhi.mapper.GirlWithDetailMapper.queryById" column="uid">
association>
resultMap>
<select id="queryById" resultMap="GirlWithDetailMap2">
select t1.id as uid,t1.`name`,t1.flower,t1.birthday,t2.id as gdid, t2.address
from girl t1,girl_detail t2
<where>
t1.id=t2.gid
and t1.id=#{id}
where>
select>
<select id="queryByIdByStep" resultMap="GirlWithDetailMap3">
select t1.id as uid,t1.`name`,t1.flower,t1.birthday
from girl t1
<where>
and t1.id=#{id}
where>
select>
mapper>
##对于javabean的封装多使用oop思想
Girl.java
package com.xuzhi.model;
import java.io.Serializable;
import java.util.Date;
public class Girl implements Serializable {
private long id;
private String name;
private String flower;
private Date birthday;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFlower() {
return flower;
}
public void setFlower(String flower) {
this.flower = flower;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Girl(String name, String flower){
this.name=name;
this.flower=flower;
}
public Girl(){
}
@Override
public String toString() {
return "Girl{" +
"id=" + id +
", name='" + name + '\'' +
", flower='" + flower + '\'' +
", birthday=" + birthday +
'}';
}
}
GirlWithDetail.java
package com.xuzhi.model;
import java.io.Serializable;
public class GirlWithDetail implements Serializable {
private Integer gid;
private String address;
private Girl girl;
public Integer getGid() {
return gid;
}
public void setGid(Integer gid) {
this.gid = gid;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Girl getGirl() {
return girl;
}
public void setGirl(Girl girl) {
this.girl = girl;
}
@Override
public String toString() {
return "GirlWithDetail{" +
"gid=" + gid +
", address='" + address + '\'' +
'}';
}
}
GirlDetail.java
package com.xuzhi.model;
import java.io.Serializable;
public class GirlDetail extends Girl{
private GirlWithDetail girlWithDetail;
public GirlWithDetail getGirlWithDetail() {
return girlWithDetail;
}
public void setGirlWithDetail(GirlWithDetail girlWithDetail) {
this.girlWithDetail = girlWithDetail;
}
@Override
public String toString() {
return "Girl{" +
"id=" + getId() +
", name='" + getName() + '\'' +
", flower='" + getFlower() + '\'' +
", birthday=" + getBirthday() +
'}'+
"GirlDetail{" +
"girlWithDetail=" + girlWithDetail +
'}';
}
}
##一对多关系映射举例:一个用户可以写多篇博客
##废话不多说,几段代码可以说明一切
GirlWithBlogMapper.xml
<mapper namespace="com.xuzhi.mapper.GirlWithBlogMapper">
<resultMap id="BaseGirlDetail" type="com.xuzhi.model.GirlDetail">
<id property="id" column="gid" />
<result property="name" column="name" />
<result property="flower" column="flower" />
<result property="birthday" column="birthday" />
resultMap>
<resultMap id="girlWithBlogMap" extends="BaseGirlDetail" type="com.xuzhi.model.GirlBlog" >
<collection property="blog" ofType="com.xuzhi.model.Blog">
<id property="id" column="bid" />
<result property="title" column="title" />
<result property="summary" column="summary" />
<result property="content" column="blogContent" />
<collection property="comments" ofType="com.xuzhi.model.Comment">
<id property="id" column="cid"/>
<result property="content" column="commentContent" />
collection>
collection>
resultMap>
<select id="queryByIdWithBlog" resultMap="girlWithBlogMap">
SELECT t1.id as gid,t1.`name`,t1.flower,t1.birthday,
t2.id as bid,t2.title,t2.summary,t2.content as blogContent,
t3.id as cid,t3.content as commentContent
from girl t1,blog t2,`comment` t3
<where>
t1.id=t2.g_id
and t2.id=t3.b_id
and t1.id=#{id}
where>
select>
mapper>
Blog.java
package com.xuzhi.model;
import java.util.List;
public class Blog {
private Integer id;
private String title;
private String summary;
private String content;
private Girl girl;
private List<Comment> comments;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Girl getGirl() {
return girl;
}
public void setGirl(Girl girl) {
this.girl = girl;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
@Override
public String toString() {
return "Blog{" +
"id=" + id +
", title='" + title + '\'' +
", summary='" + summary + '\'' +
", content='" + content + '\'' +
", girl=" + girl +
", comments=" + comments +
'}';
}
}
Comment.java
package com.xuzhi.model;
public class Comment {
private Integer id;
private String content;
private Blog blog;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Blog getBlog() {
return blog;
}
public void setBlog(Blog blog) {
this.blog = blog;
}
@Override
public String toString() {
return "Comment{" +
"id=" + id +
", content='" + content + '\'' +
'}';
}
}
GirlBlog.java
package com.xuzhi.model;
import java.util.List;
public class GirlBlog extends Girl {
private List<Blog> blog;
public List<Blog> getBlog() {
return blog;
}
public void setBlog(List<Blog> blog) {
this.blog = blog;
}
@Override
public String toString() {
return "Girl{" +
"id=" + getId() +
", name='" + getName() + '\'' +
", flower='" + getFlower() + '\'' +
", birthday=" + getBirthday() +
'}'+
"GirlBlog{" +
"blog=" + blog +
'}';
}
}
###简要说明:
在该例中,一个Girl用户可以拥有多个Blog,一个Blog又可以拥有多个Comment,这就构成了简单的一对多关系,其中还是使用了oop思想,最终想要封装的结果集类型是GirlBlog类型,在该类型包含了用户的部分个人信息,还包括了该用户的Blog,在每个Blog中有包含了该Blog所拥有的Comment,在Blog和GirlBlog中分别使用了List和List来反应一对多关系
1、添加spring依赖
2、编写一个spring的配置文件
3、通过spring的应用程序上下文对象获取对象
spring全局配置文件
<beans
xmlns="http://www.springframework.org/schema/beans"
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.xsd ">
<bean class="com.xuzhi.pojo.Girl" id="girl">
bean>
beans>
bean类
###Girl.java
package com.xuzhi.pojo;
public class Girl {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Girl{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
###测试类–>SpringTest.java
package com.xuzhi.spring;
import com.xuzhi.pojo.Girl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test
public void test1(){
// 1、获取上下文对象,spring里面声明对象都需要通过上下文来获取
//在引入配置文件的时候,可以同时引入多个配置文件,在ClassPathXmlApplicationContext中使用String数组作为参数
/* 例:ApplicationContext ctx=
new ClassPathXmlApplicationContext(new String[]{"xxx1.xml","xxx2.xml"});
*/
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
// 2、通过这个对象来获取girl
Girl girl= (Girl) ctx.getBean("girl");
//因为后面指定了class,所以不需要进行强制类型转换(个人感觉这种方式比较好)
//Girl girl =ctx.getBean("girl",Girl.class);
System.out.println(girl);
}
}
普通的获取对象的方式,所有的对象之间的依赖,类之间的依赖关系都是在java代码里面维护的,很难维护的,如果说我们有替换方案,替换比较困难
对象的产生全部是在配置里面完成的,其实我们想分析关系,直接在配置文件里面就看出来了。
IOC概念(依赖注入):
控制反转(inverse of contril ):什么控制,谁反转了谁
控制:创建对象,彼此关系的权利
普通方式:控制权是在开发人员在程序代码当中进行掌控,new
spring方式:夺取控制权,反转给spring的容器
反转过程:
声明要什么
spring容器来进行具体的控制
依赖注入:
依赖:
容器
pojos:自己定义的这些类
metadata:在spring的配置文件里面写的这些就是元数据
实例化容器:classpath…将配置文件传入,实例化完毕
setter()方法注入(最常用的方法)
必须其字段有对应的setter()方法才可完成
通过property子节点完成注入
构造注入
属性探讨
abstract:该bean将无法被实例化
parent:指定它的父bean是谁,将会继承父bean的所有内容,通过id进行指引
destroy-method:指定这个bean最后销毁的时候一定执行的方法,适合于清理型工作,触发条件是必须bean确实是被销毁才生效
容器close被触发
refresh也会触发
过时的destroy也可以触发
init-method:指定bean的初始化方法,准备性的工作
name:别名,可以通过他一样获取,可以写多个,彼此分割可以使用多种分隔符,空格,逗号等等,
<bean class="com.xuzhi.pojo.Girl" id="girl" abstract="true" destroy-method="clearDress" init-method="dress" name="g1,g2,g3">
<property name="name" value="myFirends" />
bean>
注:clearDress是Girl类里面的一个方法名,dress也是如此,
scope:指定范围
singleton:单例,在spring上下文当中,只有一个实例
prototype:原型,要一个就给一个
lazy-init:true就是spring一上来不会直接初始化我们的bean,当我们需要使用它的时候,spring才会初始化
直接初始化
当应用程序启动会慢一点,内存消耗会更大一点
当我们使用bean的时候会快一些
延迟初始化
程序启动快一些,内存消耗更小一点
使用bean会慢一点
depends-on:依赖的bean,如果某一个bean的使用严重依赖于另外一个bean的准备的话,就可以配置depends-on
对于非字面值可以描述的值的注入问题
<bean id="pay" class="com.xuzhi.spring.AliPay">
bean>
<bean id="girl" class="com.xuzhi.pojo.Girl" >
<property name="pay" ref="pay" />
bean>
通过ref指向另外一个bean的ID
关于在spring的配置文件当中单独定义别名
alias标签完成
spring多个配置文件里面的bean是可以相互引用的(被上下文扫描到的前提下)
构造注入:
构造注入方式一:
<bean id="car" class="com.xuzhi.pojo.Car">
<constructor-arg name="name" value="宝马" />
<constructor-arg name="price" value="12123123123" />
<constructor-arg name="speed" value="123123" />
bean>
构造注入方式二:(不推荐使用,实在是太垃圾了了)
<bean id="car2" class="com.xuzhi.pojo.Car">
<constructor-arg index="0" value="宝马" />
<constructor-arg index="1" value="123123" />
bean>
public Car(String name, double price) {
this.name = name;
this.price = price;
}
public Car(double price, double speed) {
this.price = price;
this.speed = speed;
}
public Car(String name, double price, double speed) {
this.name = name;
this.price = price;
this.speed = speed;
}
注:他优先时候后面的构造器
构造注入方式三:(不推荐使用,感觉还是很垃圾的)
###根据构造方法里面的参数的类型注入
<bean id="car3" class="com.xuzhi.pojo.Car" >
<constructor-arg type="java.lang.String" value="宝马" />
<constructor-arg type="java.lang.Double" value="123" />
bean>
数组、List、Set、Map
如果其对应的值是简单的字面值,就直接写就可以了,如果是一个其他的类,那么使用内部bean的方式完成
<bean class="com.xuzhi.pojo.People" id="people" >
<property name="name" value="小明" />
<property name="age" value="12" />
<property name="friends">
<array>
<value>小红value>
<value>小刚value>
<value>你爸爸value>
array>
property>
<property name="numbers">
<list>
<value>1value>
<value>2value>
<value>3value>
list>
property>
<property name="girls">
<list>
<bean class="com.xuzhi.pojo.Girl">
<property name="name" value="nihao" />
bean>
<bean class="com.xuzhi.pojo.Girl">
<property name="name" value="测试" />
bean>
list>
property>
<property name="pays">
<set>
<bean class="com.xuzhi.spring.AliPay">
bean>
<bean class="com.xuzhi.spring.AliPay">
bean>
set>
property>
<property name="girlMap">
<map>
<entry key="girl1">
<bean class="com.xuzhi.pojo.Girl">
<property name="name" value="nihaoi" />
bean>
entry>
<entry key="girl2">
<bean class="com.xuzhi.pojo.Girl">
<property name="name" value="nihaoi" />
bean>
entry>
map>
property>
bean>
###最新的官方文档推荐是用自动注入
<import resource="classpath:spring/spring-test.xml" />
<import resource="classpath:spring/spring-test2.xml" />
<import resource="classpath:spring/spring-*.xml" />
<context:property-placeholder location="classpath:jdbc.properties" />
<bean class="com.xuzhi.pojo.DaoTest" id="jdbc" >
<property name="url" value="${url}" />
<property name="driver" value="${driver}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
bean>
注:使用import等标签时需要完整的xml命名空间
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjrtartifactId>
<version>1.9.2version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.2version>
dependency>
<aop:aspectj-autoproxy />
<bean class="com.xuzhi.advice.BeforeAdvice" id="beforeAdvice" >
bean>
<aop:config>
<aop:aspect id="beforeAspect" ref="beforeAdvice">
<aop:before method="methodBefore" pointcut="execution(* com.xuzhi.service.ProviderService.add(..))" />
<aop:before method="before" pointcut="execution(* com.xuzhi.service.ProviderService.add(..))" />
aop:aspect>
<aop:aspect id="afterAspect" ref="afterAdvice">
<aop:after method="methodAfter" pointcut="execution(* com.xuzhi.service.ProviderService.add(String,int))" />
aop:aspect>
aop:config>
//JoinPoint可以获取几乎所有的这个方法的信息
//作用,可以打印输出日志文件
public void before(JoinPoint joinPoint){
//获取方法的方法名
String name=joinPoint.getSignature().getName();
System.out.println("method:"+name);
//获取方法的参数
Object[] args = joinPoint.getArgs();
System.out.println(Arrays.toString(args));
}
先写访问修饰符,包名的限定,类名,方法名,参数列表+组合条件符合,多个条件很都可以
public com.sz..*.*(String)
public com.sz.*.*.*(Integer )
1、创建web项目
2、编写web.xml,在其中注册一个特殊的servlet,前端控制器
3、编写一个springmvc的配置文件
1、注册一个视图解析器
4、编写控制器
5、编写一个结果页面
web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
依赖引入:
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.0.8.RELEASEversion>
dependency>
springmvc-servlet.xml
###springmvc的配置文件,对每一个springmvc控制器都需要配置bean标签
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd">
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/jsp/" />
<property name="suffix" value=".jsp" />
bean>
<bean class="com.xuzhi.controller.HelloController" name="/helloController" >
bean>
beans>
HelloController.java
###控制器,类似于struts的action
package com.xuzhi.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//实现一个Controller接口的方式
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("hello","Hello World!");
modelAndView.setViewName("hello");
return modelAndView;
}
}
hello.jsp
###视图代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
Happy New Year:${hello}
web.xml
注册前端控制器,目的在于,我们希望让springmvc去处理所有的请求
通过
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
确实是处理所有的请求(不是真的所有)
url-pattern的写法问题
/ =>(推荐使用)
/* =>(永远都不要这么写)
*.do
springmvc设计的理念是希望开发者尽量远离原生的servletAPI,API不是很好用,有些繁琐,将操作进一步的简化,他将很多东西责任进行了拆分,不希望我们将一些技术点绑定死,可以做到随意的切换。本身还是基于servlet设计的,分发的servlet,
默认情况下是dispatcherServlet的名字当做命名空间
[ServletName]-servlet.xml (WEB-INF)
servletName-servlet.xml = namespace.xml
之下寻找
降配置文件移动位置之后,出现了相应的错误
如果非要重新使用另外一个名字,可以使用
<init-param>
<param-name>namespaceparam-name>
<param-value>mvcparam-value>
init-param>
默认的规则要求在web-inf下,但是maven项目的标准应该在resources下面,解决方案:
重新指定上下文的配置文件的位置即可
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
springmvc支持多种视图技术
内部的资源视图解析器
解析器的作用类似于
request.getDispatcherServlet.forward(request,response);
物理视图是由逻辑视图转换而来
物理视图是webapp/jsp/hello.jsp
逻辑视图 p View =prefix + logicViewName + suffix
控制器
是一种比较传统的实现一个接口的方式完成的,Controller
如果一个接口只有一个方法,这种接口叫做函数式接口
###ModelAndView方法是Controller接口内的唯一的一个方法,故Controller为函数式接口
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
}
该代码类似于servlet里面由doGet doPost里面入参就是请求与相应。
在springmvc中,在model当中填充数据,然后在具体的视图进行展示
还需要在配置文件当中配置一下bean,这个bean要取个名字,就用来充当这个URI,他就处理一个请求,跟servlet的差别不是很大。
基于实现接口的方式已经是过去式了,采用注解开发很简单
@Controller
@RequestMapping
###推荐使用二者结合的方式
组合使用实例
@Controller
@RequestMapping("/bye")
public class ByeController {
//要想访问该Controller具体的地址应该是":8080/bye/bye"
@RequestMapping("/bye")
public String bye(Model model){
model.addAttribute("hello","我的世界");
//返回的为viewName,即视图的名字,此时寻找视图的路径为 /jsp/hello.jsp
return "hello";
}
}
###使用联合方式,第一个/bye可以区分大类,第二个/bye直接调用该具体Controller
###需要添加相应的命名空间,以使用Context
<context:component-scan base-package="com.xuzhi.controller" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/jsp/" />
<property name="suffix" value=".jsp" />
bean>
package com.xuzhi.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
//使用注解需要在springmvc的配置文件里面导入一个包,以启动注解扫描
//不需要继承任何的类也不需要实现任何的接口
@Controller
public class ByeController {
@RequestMapping
public String bye(Model model){
//往view层传值
model.addAttribute("hello","我的世界");
//返回的为viewName,即视图的名字,此时寻找视图的路径为 /jsp/hello.jsp
return "hello";
}
}
1、配置基础扫描的包,这样配置的注解才会生效
2、在指定的类上面添加@Controller注解
3、在Controller类的方法前添加@RequestMapping注解,类似于前面的Controller的那个名字(不同requesthandler处理的handlerMapping)
当我们写上Controller之后,就标记了它为spring的一个组件,并且是控制器的组件,此时我们的handlermapping会去扫描寻找这个controller是否与之匹配,如果发现匹配就把这里处理的工作交给它
匹配的规则:
具体的匹配就是通过请求的路径进行匹配的
@RequestMapping(URI)
此时就是通过这个URI进行匹配
转发
//请求
@RequestMapping("/forward")
public String forward(Model model){
//springmvc model默认是在请求域中存储值
System.out.println("请求");
model.addAttribute("skill","请求测试");
return "forward";
}
重定向
//重定向
@RequestMapping("/redirect")
public String redirect(Model model){
model.addAttribute("skill","重定向测试");
System.out.println("重定向");
//重定向是需要在return的内容中增加重定向的标识=>“redirect:”+重定向视图的路径
return "redirect:/jsp/redirect.jsp";
}
转发到页面 (默认)
重定向到页面 redirect:path
转发到另外一个控制器 forward:path
request
session
application
可以通过模拟的对象完成操作,也可以使用原生的servletAPI完成,直接在方法当中入参即可
package com.xuzhi.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.WebRequest;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/web")
public class WebElementController {
//request元素
@RequestMapping("request")
public String request(WebRequest request){
System.out.println(request.getParameter("test"));
return "forward";
}
//session元素
@RequestMapping("session")
public String session(HttpSession session){
session.setAttribute("test","我是你爸爸");
return "forward";
}
//application元素
@RequestMapping("application")
public String application(HttpSession session){
//获取application并设置test
session.getServletContext().setAttribute("application","application测试");
return "redirect:/jsp/forward.jsp";
}
}
value 写的是路径,是一个数组的形式,可以匹配多个路径
path 是value的别名,所以二者人选其一,他们的作用是一样的
method 指定可以访问的请求的类型,比如post,get,他也可以写成一个数组的形式
params 可以指定参数,还可以去限定这个参数的特征,比如等于某个值
headers 能够影响浏览器的行为
consumers 消费者,媒体类型,可以限定为application.json;charset=UTF-8
produces 产生的响应的类型
//请求映射的路径path可以有多个值,即请求这个controller可以用多个名字,m1,m2都可以请求这个 Controller
// @RequestMapping(value = {"/m1","/m2"})
// @RequestMapping(path = {"/m1","/m2"})
//该请求只能接受post提交的表单
@RequestMapping(path = {"/m1","/m2"},method = RequestMethod.POST)
public String m1(Model model){
model.addAttribute("annotations","@RequestMapping注解");
return "annotations";
}
//用以处理post请求,参数为两个,分别为a和b
@RequestMapping(path = "/m2",method = RequestMethod.GET,params = {"a","b"})
public String m2(@RequestParam("a")Integer a, @RequestParam("b") Integer b){
System.out.println(a+b);
return "annotations";
}
相等于RequestMapping中的method指定为get或者post,只能相应处理get或者post请求
resultful风格
###请求时的url可以写成=》/product/add/产品id/产品名称/产品价格
该Controller可以自动接收通过url传入的参数
@Controller
@RequestMapping("/product")
public class ProductController {
@RequestMapping("/add/{id}/{name}/{price}")
public String addProduct(@PathVariable("id")Integer id,@PathVariable("name")String name,@PathVariable("price")Double price){
System.out.println(id+name+price);
return "forward";
}
}
对于非get,post请求的支持,需要有额外的内容添加,要增加一个过滤器来额外处理
他返回的不是页面,而是数据
DeleteMapping
PutMapping
过滤器
<filter>
<filter-name>hiddenHttpMethodFilterfilter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
表单提交里面还要添加一个隐藏的参数
@PutMapping
@WebServlet(urlPatterns = {},loadOnStartup = 2)
public class WebPathInitServlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
//在整体应用上下文当中存储了一个ctx的值,用他来引用上下文路径
config.getServletContext().setAttribute("ctx",config.getServletContext().getContextPath());
super.init(config);
}
}
###在jsp页面中需要全局项目名称时只需要引用${ctx},在此后的访问静态资源时会使用
springmvc支持ant风格
?任意的字符
“*” 0到n,任意个字符都可以,/除外
** 支持任意层路径,
// 访问地址可以写为"/test/m3"+"任意单个字符,/除外"
// @RequestMapping(path = "/m3?")
// 访问地址可以写为"/test/m3"+"可以放任意长度的字符串,但是不能包括/"
// @RequestMapping(path = "m3*")
// 访问地址可以写为"/m3"+"/a"+"/b",可以有多层路径
@RequestMapping(path = "m3/**")
public String m3(){
System.out.println("m3....");
return "annotations";
}
由于我们的servlet设置了URL匹配方式为/,所以,他将静态资源也当做一个后台的请求,
比如http://localhost:8080/SpringMVC/static/css/index.css
他尝试去匹配一个static/css/index.css的Controller里面的requestMapping的组合,因为没有,所以404,解决方式很多,最简单的,是让springmvc单独处理,将这些交给容器的默认的servlet处理,就不让DispatcherServlet来处理了
解决方式一(推荐使用这种方式,当需要引用的文件不能被识别时,可以增加第二种方式来引入)
<mvc:default-servlet-handler />
<mvc:annotation-driven />
解决方式二
<mvc:resources mapping="static/css/*" location="static/css/" />
添加一个过滤器即可,springmvc提供了非常好的字符编码过滤器,所以我们注册即可
在web.xml中添加这样的配置进行注册(最好是放在servlet过滤器之前)
<filter>
<filter-name>characterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceRequestEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>characterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
通过属性名称进行绑定,可以完成数据绑定
页面当中表单元素的name值要和后台的形参的名字保持一致。
如果有多个,多个形参按名字绑定即可,当传入的值校对的时候,会比较麻烦
@PutMapping("put")
@ResponseBody
//形参要与前台页面传过来的name名称相对应
public String put(String name){
System.out.println(name);
return "@PutMapping测试成功";
}
jsp页面不变
后台
@PutMapping("put")
@ResponseBody
public String put1(@RequestParam("name") String name){
System.out.println(name);
return "@PutMapping测试成功";
}
jsp页面一致
@PutMapping("/put2")
@ResponseBody
public String put2(User user){
System.out.println(user.getName()+user.getPassword());
return "@PutMapping测试成功";
}
@InitBinder("user")
public void init(WebDataBinder webDataBinder){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
sdf.setLenient(false);
webDataBinder.registerCustomEditor(Date.class,new CustomDateEditor(sdf,false));
}
@PostMapping("/model3")
public String model3(@ModelAttribute("user") User user){
System.out.println(user.getName()+user.getPassword());
System.out.println(user.getBirth());
return "msg";
}
//通过initBinder指定了user名字和modelAttribute里面的user绑定
2、不指定名字,根据数据类型一样可以分析解析转换成功
@InitBinder()
public void init(WebDataBinder webDataBinder){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
sdf.setLenient(false);
webDataBinder.registerCustomEditor(Date.class,new CustomDateEditor(sdf,false));
}
@PostMapping("/model3")
public String model3(@ModelAttribute() User user){
System.out.println(user.getName()+user.getPassword());
System.out.println(user.getBirth());
return "msg";
}
3、时间+日期的处理(推荐使用注解方式)
//通过Java源码的方式(如1、2),解决方案不是很理想,只能处理固定格式的时间日期格式,个人建议使用注解的方式来解决 比较好
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
返回数据,一般情况下返回json格式,需要引用json包
put.jsp =>put请求方式为例
UserController.java
@Controller
@RequestMapping("/user")
public class UserController {
//相应put请求
@PutMapping("put")
//表示将返回一个数据结果,而不是页面
@ResponseBody
public String put(String name){
System.out.println(name);
//返回数据,为测试方便,结果返回一个String字符串
return "@PutMapping测试成功";
}
}
使用方式一:
//就是在controller里面的任意一个处理具体的方法之前执行
@ModelAttribute
public User init(){
User u=new User();
u.setName("王是你爸爸");
return u;
}
@RequestMapping("/model")
public String model(Model model){
//判断init()方法是否在该方法之前执行,即判断init()方法是否返回了User对象,同时确定了 init()返回的对象名是什么
System.out.println(model.containsAttribute("user"));
System.out.println(model.addAttribute("user"));
return "msg";
}
如果某些对象从头到尾每次请求当中都要存在,不消失,就适合使用这种方法。
使用方式二
//就是在controller里面的任意一个处理具体的方法之前执行
@ModelAttribute
public void init(Model model){
User u=new User();
u.setName("王是你爸爸");
model.addAttribute("user",u);
}
@RequestMapping("/model")
public String model(Model model){
//判断init()方法是否在该方法之前执行,即判断init()方法是否返回了User对象,同时确定了init()返回的对象名是什么
System.out.println(model.containsAttribute("user"));
System.out.println(model.addAttribute("user"));
return "msg";
}
使用方式三:
//如果前台没有传过来相应的值,使用该注解后会自动去我们的model模型中寻找相应的user,
//如果前台传值过来,则init()方法返回的内容则由前台穿过来的model模型替换
@RequestMapping("/model2")
public String model2(@ModelAttribute User user){
System.out.println(user.getName()+user.getPassword());
return "msg";
}
用以标记处理springmvc的中传值时间日期问题,格式化时间日期
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
json数据,不是通过form表单传递
ajax({
data:
})
@Controller
@RequestMapping("/user3")
@SessionAttributes("user")
public class User3Controller {
@PostMapping("/session")
public String session(User user){
return "redirect:/jsp/user.jsp";
}
}
要求当前这次访问当中的会话当中必须有某个对象,简而言之,@SessionAttributes是往会话中添加某个模型数据,而@SessionAttribute是为了检查当前会话中是否有需要检测的模型数据
@RestController=@Controller+@ResponseBody
该注解标记的Controller类可以指定该Controller类中的所有方法都返回数据,而不是返回页面
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.5version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.9.5version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>2.9.5version>
dependency>
<dependency>
<groupId>net.sf.json-libgroupId>
<artifactId>json-libartifactId>
<version>2.4version>
<classifier>jdk15classifier>
dependency>
<dependency>
<groupId>org.codehaus.jacksongroupId>
<artifactId>jackson-core-aslartifactId>
<version>1.9.2version>
dependency>
<dependency>
<groupId>org.codehaus.jacksongroupId>
<artifactId>jackson-mapper-aslartifactId>
<version>1.9.2version>
dependency>
//返回一个pojo
@RequestMapping("/m1")
@ResponseBody //这个注解将制定返回的不是视图,而是数据,他会将我们的返回数据格式转换为json数据格式
public User json1(){
User user=new User();
user.setName("我是你爸爸");
user.setPassword("root");
return user;
}
//返回一个Map
@RequestMapping("/m2")
@ResponseBody //这个注解将制定返回的不是视图,而是数据,他会将我们的返回数据格式转换为json数据格式
public Map<String,Object> json2(){
Map<String,Object> map=new HashMap<>();
map.put("name","你爸爸就是你爸爸");
map.put("age",21);
return map;
}
@RequestMapping("/m3")
@ResponseBody
public User[] json3(){
User user1=new User();
user1.setName("我是你爸爸1");
user1.setPassword("你爸爸");
User user2=new User();
user2.setName("你爸爸就是你爸爸");
user2.setPassword("你就是你");
return new User[]{user1,user2};
}
@RequestMapping("/m4")
@ResponseBody
public List<User> json4(){
List<User> list=new ArrayList<>();
User user1=new User();
user1.setName("我是你爸爸");
user1.setPassword("你爸爸");
User user2=new User();
user2.setName("你爸爸就是你爸爸");
user2.setPassword("你就是你");
list.add(user1);
list.add(user2);
return list;
}
$.ajax({
url:'${ctx}/json/m1',
type:'post',
success:function (data) {
alert(data.name);
alert(data.password);
}
})
//接收返回的map
$('#map').click(function () {
$.ajax({
url:'${ctx}/json/m2',
type:'post',
success:function (data) {
alert(data.name);
alert(data.age);
}
})
})
//接收返回的数组
$('#array').click(function () {
$.ajax({
url:'${ctx}/json/m3',
type:'post',
success:function (data) {
for(var i=0;i<data.length;i++){
alert(data[i].name);
alert(data[i].password);
}
}
})
})
//接收返回的数组
$('#list').click(function () {
$.ajax({
url:'${ctx}/json/m4',
type:'post',
success:function (data) {
for(var i=0;i<data.length;i++){
alert(data[i].name);
alert(data[i].password);
}
}
})
})
必须要添加,来规范传输json数据格式以及编码标准
contentType:"application/json;charset=utf-8"
$('#user').click(function () {
var obj={
"name":"我是你爸爸",
"password":"你爸爸就是你爸爸"
};
$.ajax({
url:'${ctx}/json2/add',
type:'post',
contentType:'application/json',
data:JSON.stringify(obj),
success:function (data) {
}
})
})
//前台提交一个user过来
@RequestMapping("/add")
//User user入参只能处理form表单提交的数据
//要想接收前台ajax发过来的json数据,需在入参时添加@RequestBody注解
public String add(@RequestBody User user){
System.out.println(user.getName()+user.getPassword());
return "msg";
}
$('#userList').click(function () {
var obj={
"name":"我是你爸爸",
"password":"你爸爸就是你爸爸"
};
var obj2={
"name":"我是你爷爷",
"password":"你爷爷就是你爷爷"
};
var array=new Array();
array.push(obj);
array.push(obj2);
$.ajax({
url:'${ctx}/json2/addList',
type:'post',
contentType:'application/json',
data:JSON.stringify(array),
success:function (data) {
if(data.code==2000){
alert("测试成功");
}
}
})
})
//前台提交一个user过来
@RequestMapping("/addList")
//User user入参只能处理form表单提交的数据
//要想接收前台ajax发过来的json数据,需在入参时添加@RequestBody注解
@ResponseBody
public Map<String,Integer> addList(@RequestBody List<User> user){
Map<String,Integer> map=new HashMap<>();
map.put("code",2000);
System.out.println(user);
return map;
}
对于很多第三方开发,还是有很多会采用xml作为数据交互,比如微信
<dependency>
<groupId>com.fasterxml.jackson.dataformatgroupId>
<artifactId>jackson-dataformat-xmlartifactId>
<version>2.9.3version>
dependency>a
##仅作为小测试,需要用时自行查阅
//produces用于指定返回数据的数据类型,在这里我们指定为XML格式
@RequestMapping(value = "/m1",produces = MediaType.APPLICATION_ATOM_XML_VALUE)
@ResponseBody
public User m1(){
User user=new User();
user.setName("我是你爸爸");
user.setPassword("你爸爸就是你爸爸");
return user;
}
1、添加相关依赖
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.3.3version>
dependency>
2、在springmvc的配置文件中注册一个文件上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1048576" />
<property name="defaultEncoding" value="UTF-8" />
<property name="maxUploadSizePerFile" value="1024" />
bean>
3、准备一个上传的页面
<%--要实现文件上传,必须要添加enctype="multipart/form-data" --%>
4、后台处理程序
@Controller
@RequestMapping("/file")
public class FileController {
private static String uploadPath="I:/newFile/";
/**
* 文件上传要处理的问题
* 1、传到哪里去;2、要传什么东西;3、文件传输的细节
* @param multipartFile
* @return
*/
@RequestMapping("/upload")
public String upload(@RequestParam("upload")MultipartFile multipartFile, Model model){
//1、判断上传的文件是否为空
if(multipartFile!=null && !multipartFile.isEmpty()){
//2、获取上传文件的原始文件名
String originalFilename = multipartFile.getOriginalFilename();
//3、截取源文件名的前缀,不带后缀
String fileNamePrefix=originalFilename.substring(0,originalFilename.lastIndexOf("."));
//4、加工处理原文件名,原文件名+时间戳
String newFileNameProfix=fileNamePrefix+new Date().getTime();
//5、得到新的文件名
String newFileName=newFileNameProfix+originalFilename.substring(originalFilename.lastIndexOf("."));
//6、构建文件对象
File file =new File(uploadPath+newFileName);
//7、上传
try {
multipartFile.transferTo(file);
model.addAttribute("fileName",newFileName);
} catch (IOException e) {
e.printStackTrace();
}
}
return "success";
}
}
@Controller
@RequestMapping("/download")
public class DownloadController {
//定义一个文件下载的路径
private static String DownloadPath="I:/newFile/";
//
@RequestMapping("/down")
public String download(HttpServletResponse response){
//通过输出流写入到客户端
//1、获取文件下载名
String fileName="typora-setup-x64.exe";
//2、构建一个文件对象通过Paths工具类获取一个Path对象
Path path = Paths.get(DownloadPath, fileName);
//3、判断文件是否存在
if(Files.exists(path)){
//存在则此下载
//通过response设定它响应的类型
//4、获取文件的后缀,即获取文件的类型
String fileSuffix=fileName.substring(fileName.lastIndexOf(".")+1);
//5、设置contentType,只有指定他才能下载文件
response.setContentType("application/"+fileSuffix);
//6、添加头信息
//因为是springmvc只能处理ISO8859-1,所以要将文件名通过UTF-8提取出字节流名称再转换成标 准的ISO8859-1
try {
response.setHeader("Content-Disposition","attachment;filename="+new String(fileName.getBytes("UTF-8"),"ISO8859-1"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//7、通过path写出该文件
try {
Files.copy(path,response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
return "success";
}
}
springmvc提供了拦截器,类似于过滤器,他将在我们的请求距离之前先做检查,有权决定,接下来是否继续,对我们的请求进行加工。拦截器,可以设计多个,
通过实现HandlerIntercepror,这是一个接口,定义了三个非常重要的方法
后台代码
package com.xuzhi.interceptors;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 方法耗时统计的拦截器
*/
public class MethodTimerInterceptor implements HandlerInterceptor {
private static final Logger LOGGER=Logger.getLogger(MethodTimerInterceptor.class);
//前置功能 开始到结束,计算两个点之间所需要的时间
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1、定义开始时间
long start=System.currentTimeMillis();
//2、将开始时间存到请求域当中
request.setAttribute("start",start);
//记录请求日志
LOGGER.info(request.getRequestURI()+"请求到达!");
//返回true,才会去找下一个拦截器,如果没有下一个拦截器,则去到Controller执行请求
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//1、得到开始的时间
long start= (long) request.getAttribute("start");
//2、得到结束的时间
long end=System.currentTimeMillis();
//3、计算耗时
long speedTime=end-start;
if(speedTime>=1000){
LOGGER.warn("请求耗时严重,耗时:"+speedTime+"毫秒");
}else{
LOGGER.info("请求耗时正常,耗时:"+speedTime+"毫秒");
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
配置文件
<mvc:interceptor>
<mvc:mapping path="/**/*"/>
<bean class="com.xuzhi.interceptors.MethodTimerInterceptor" />
mvc:interceptor>
后台代码
package com.xuzhi.interceptors;
import com.xuzhi.pojo.User;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 会话拦截器
*/
public class SessionInterceptor implements HandlerInterceptor {
private static final Logger LOGGER=Logger.getLogger(SessionInterceptor.class);
//检查当前会话是不是有该User,如果有,放行,如果没有,则拦截
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取会话中的User对象
Object user=request.getSession().getAttribute("SESSION_USER");
//判断该用户是否登录,
if(user == null){
LOGGER.warn("您不具备该权限,请先登录");
return false;
}
//先判断user是否为空,即判断用户是不是登录
//如果用户登录,则判断用户是不是User类型
if(user instanceof User){
//去数据库检测该用户是否存在,给予该用户冻结状态,密码附空
User u= (User) user;
u.setPassword(null);
request.getSession().setAttribute("SESSION_USER",u);
LOGGER.info(u.getName()+"登录状态");
return true;
}else{
LOGGER.warn("请先登录,不要搞事情");
return false;
}
}
}
配置文件
<mvc:interceptor>
<mvc:mapping path="/user/**/*"/>
<mvc:exclude-mapping path="/user/login" />
<bean class="com.xuzhi.interceptors.SessionInterceptor">
bean>
mvc:interceptor>
如果有n个拦截器,并且都能拦截到某个URI的时候,执行顺序问题,
在springmvc中当中拦截器定义的先后顺序有关系,配置在前面的优先执行,按照顺序来
例如:有三个拦截器 i1.i2.i3
前置处理顺序:i1,i2,i3
后置处理顺序:i3,i2,i1
spring和springmvc是天然集成,所以只需要解决mybatis和spring整合的问题,中间项目mybatis-spring项目进行整合
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.38version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.5version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.9.5version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>2.9.5version>
dependency>
<dependency>
<groupId>net.sf.json-libgroupId>
<artifactId>json-libartifactId>
<version>2.4version>
<classifier>jdk15classifier>
dependency>
<dependency>
<groupId>org.codehaus.jacksongroupId>
<artifactId>jackson-core-aslartifactId>
<version>1.9.2version>
dependency>
<dependency>
<groupId>org.codehaus.jacksongroupId>
<artifactId>jackson-mapper-aslartifactId>
<version>1.9.2version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.3.3version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformatgroupId>
<artifactId>jackson-dataformat-xmlartifactId>
<version>2.9.3version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.2version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.2version>
<scope>testscope>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>com.mchangegroupId>
<artifactId>c3p0artifactId>
<version>0.9.2.1version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>1.3.0version>
dependency>
<dependency>
<groupId>joda-timegroupId>
<artifactId>joda-timeartifactId>
<version>2.9.9version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.1.2version>
dependency>
<dependency>
<groupId>commons-codecgroupId>
<artifactId>commons-codecartifactId>
<version>1.10version>
dependency>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:/spring/applicationContext.xmlparam-value>
context-param>
<filter>
<filter-name>characterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceRequestEncodingparam-name>
<param-value>trueparam-value>
init-param>
<init-param>
<param-name>forceResponseEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>characterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter>
<filter-name>hiddenHttpMethodFilterfilter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
核心配置文件用于引入其他配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd">
<import resource="classpath:spring/spring-*.xml"/>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd ">
<context:component-scan base-package="com.xuzhi" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/" />
<property name="suffix" value=".jsp" />
bean>
<mvc:default-servlet-handler />
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8value>
list>
property>
bean>
mvc:message-converters>
mvc:annotation-driven>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" >
<list>
<value>text/html;charset=UTF-8value>
list>
property>
bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8value>
<value>application/json;charset=UTF-8value>
list>
property>
bean>
list>
property>
bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1073741824" />
<property name="defaultEncoding" value="UTF-8" />
<property name="maxUploadSizePerFile" value="4194304" />
bean>
beans>
整合ORM功能
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd ">
<context:component-scan base-package="com.xuzhi.mapper">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}" />
<property name="jdbcUrl" value="${url}" />
<property name="user" value="${username}" />
<property name="password" value="${password}" />
<property name="maxPoolSize" value="30" />
<property name="minPoolSize" value="10" />
<property name="autoCommitOnClose" value="false" />
<property name="checkoutTimeout" value="100000" />
<property name="acquireRetryAttempts" value="2" />
bean>
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean" >
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:com/xuzhi/mapper/**/*.xml" />
<property name="configLocation">
<bean class="org.apache.ibatis.session.Configuration">
<property name="mapUnderscoreToCamelCase" value="true" />
bean>
property>
<property name="plugins" >
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<value>
helperDialect=mysql
reasonable=true
supportMethodArguments=true
params=count=countSql
autoRuntimeDialect=true
value>
property>
bean>
array>
property>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xuzhi.mapper" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean" />
bean>
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" value="dataSource" />
bean>
<tx:advice transaction-manager="transactionManager" id="transactionAdvice">
<tx:attributes>
<tx:method name="select*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception" />
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="txCut" expression="execution(* com.xuzhi.service..*.*(..))" />
<aop:advisor advice-ref="transactionAdvice" pointcut-ref="txCut" />
aop:config>
<tx:annotation-driven transaction-manager="transactionManager" />
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd ">
<context:annotation-config />
<context:component-scan base-package="com.xuzhi" />
<aop:aspectj-autoproxy />
<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean" id="conversionService" >
<property name="registerDefaultFormatters" value="false" />
<property name="formatters">
<set>
<bean class="org.springframework.format.number.NumberFormatAnnotationFormatterFactory" />
set>
property>
<property name="formatterRegistrars">
<set>
<bean class="org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar" >
<property name="dateFormatter">
<bean class="org.springframework.format.datetime.joda.DateTimeFormatterFactoryBean">
<property name="pattern" value="yyyyMMdd" />
bean>
property>
bean>
set>
property>
bean>
beans>