Spring+SSM
Spring
基于黑马程序员SSM框架的课堂笔记,感谢黑马程序员!
# Spring+SpringMVC+MyBatis
Spring快速入门
- 
导入相关依赖 - Spring-context
- junit
 <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.1.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies>
- 
接口 实现类 注册bean - 接口
 public interface UserDao { void save(); }- 实现类
 public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("Sava running..."); } }- 注册bean applicationContext.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="com.jotian.dao.Impl.UserDaoImpl"/> </beans>
- 
测试 public class MyTest { @Test public void Test01(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = context.getBean("userDao", UserDao.class); userDao.save(); } }
Spring配置文件
1.Bean标签的基本配置
用于配置对象交由Spring来创建。默认情况下它调用的是类的无参构造函数,如果没有无参构造函数则创建不成功。
基本属性:
- id: Bean实例在Spring容器中的唯一标识
- class: Bean的全限定名称
2.Bean标签的范围配置
- scpoe : 指对象的作用范围,取值如下:
| 取值范围 | 说明 | 
|---|---|
| singleton | 默认值,单例的 | 
| prototype | 多例的 | 
| request | WEB项目中,Spring创建一个Bean对象,将对象存入到request域中 | 
| session | WEB项目中,Spring创建一个Bean对象,将对象存入到session域中 | 
| global session | WEB项目中,应用在Portlet环境,如果没有Portlet环境那么globalSession相当于session | 
测试:
- 单例模式【加载配置文件的时候创建对象】
默认情况【scope="singleton"】
<?xml version="1.0" encoding="UTF-8"?>
<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 id="userDao" class="com.jotian.dao.Impl.UserDaoImpl" scope="singleton"/>
</beans>
测试
public class MyTest {
    @Test
    public void Test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        UserDao userDao1 = context.getBean("userDao",UserDao.class);
        System.out.println(userDao);
        System.out.println(userDao1);
    }
}
结果:
com.jotian.dao.Impl.UserDaoImpl@51e2adc7
com.jotian.dao.Impl.UserDaoImpl@51e2adc7
- 多例模式【getBean时创建对象】
设置【scope="singleton"】
<?xml version="1.0" encoding="UTF-8"?>
<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 id="userDao" class="com.jotian.dao.Impl.UserDaoImpl" scope="prototype"/>
</beans>
测试
public class MyTest {
    @Test
    public void Test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        UserDao userDao1 = context.getBean("userDao",UserDao.class);
        System.out.println(userDao);
        System.out.println(userDao1);
    }
}
结果:
com.jotian.dao.Impl.UserDaoImpl@3cb1ffe6
com.jotian.dao.Impl.UserDaoImpl@3dfc5fb8
注:
- 
当scope的取值为singleton时 Bean的实例化个数:1个 Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例 Bean的生命周期: - 对象创建:当应用加载,创建容器时,对象就被创建了
- 对象运行:只有容器在,对象一直活着
- 对象销毁:当应用加载,销毁容器时,对象就被销毁了
 
- 
当scope的取值为prototype时 - Bean的实例化个数:多个
- Bean的实例化时机:当调用getBean()方法时实例化Bean
- 对象创建:当使用对象时,创建新的对象实例
- 对象运行:只要对象在使用中,就一直活着
- 对象销毁:当对象长时间不使用时,就被java的垃圾回收器回收了
 
 
Bean的生命周期配置
- init-method : 指定类的初始化方法名称
- destroy-method :指定方法销毁的方法名称
public class UserDaoImpl implements UserDao {
    public UserDaoImpl() {
        System.out.println("无参构造执行了。。。");
    }
    public void init(){
        System.out.println("初始化方法。。。");
    }
    public void destory(){
        System.out.println("销毁方法。。。");
    }
    @Override
    public void save() {
        System.out.println("Sava running...");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<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 id="userDao" class="com.jotian.dao.Impl.UserDaoImpl" scope="singleton" init-method="init" destroy-method="destory"/>
</beans>
public class MyTest {
    @Test
    public void Test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        ((ClassPathXmlApplicationContext)context).close();
    }
}
无参构造执行了。。。
初始化方法。。。
销毁方法。。。
注:
调用.close() 方法为了告诉程序,结束的切入点。从而调用销毁的方法
Bean实例化的三种方式
- 无参构造方法实例化【之前的都是无参构造实例化】
- 工厂静态方法实例化
- 工厂实例方法实例化
第二种:
public class StaticFactory {
    public static UserDao getUserDao(){
        return new UserDaoImpl();
    }
}
public class UserDaoImpl implements UserDao {
    public UserDaoImpl() {
        System.out.println("无参构造执行了...");
    }
    @Override
    public void save() {
        System.out.println("Save Running ...");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<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 id="userDao" class="com.jotian.factory.StaticFactory" factory-method="getUserDao"/>
</beans>
第三种:
public class DynamicFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}
public class UserDaoImpl implements UserDao {
    public UserDaoImpl() {
        System.out.println("无参构造执行了...");
    }
    @Override
    public void save() {
        System.out.println("Save Running ...");
    }
}
    <bean id="favtory" class="com.jotian.factory.DynamicFactory"/>
    <bean id="userDao" factory-bean="favtory" factory-method="getUserDao"/>
</beans>
Bean的依赖注入分析
set方法 构造方法 注入
初始:
public interface UserService {
    void save();
}
public class UserServiceImpl implements UserService {
    @Override
    public void save() {
        UserDao userDao = new UserDaoImpl();
        userDao.save();
    }
}
    @Test
    public void Test01() {
        UserServiceImpl userService = new UserServiceImpl();
        userService.save();
    }
}
改进
public interface UserService {
    void save();
}
public class UserServiceImpl implements UserService {
    @Override
    public void save() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        userDao.save();
    }
}
    <bean id="userDao" class="com.jotian.dao.Impl.UserDaoImpl"/>
    <bean id="userService" class="com.jotian.service.Impl.UserServiceImpl"/>
    @Test
    public void Test01() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserServiceImpl userService = context.getBean("userService", UserServiceImpl.class);
        userService.save();
    }
分析:
目前UserService实例和UserDao实例都存在容器中,当前的做法是在容器外部获得UserService实例和UserDao实例,然后在程序中结合。

所以-->因为UserService和UserDao都在Spring容器中,而最终程序直接使用的是UserService,所以可以在Spring容器中,将UserDao设置到UserService内部。

Bean的依赖注入概念
依赖注入(Dependency Injection):它是Spring框架核心IOC的具体实现
在编写程序时,通过控制反转,把对象的创建交给Spring,但是代码中不可能出现没有依赖的情况。IOC解耦只是降低它们之间的依赖关系,但是不会消除,例如:业务层任然会调用持久层的方法。
那这种业务层和持久层的依赖关系,在使用Spring之后,就让Spring来维护了。
简单的说,就是坐等框架把持久层对象传入到业务层,而不是我们自己去获取。
- 构造方法
- set方法
public interface UserService {
    void save();
}
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void save() {
              userDao.save();
    }
}
    <bean id="userDao" class="com.jotian.dao.Impl.UserDaoImpl"/>
    <bean id="userService" class="com.jotian.service.Impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>
<!--前userDao是UserServiceImpl属性名
	后userDao是引用容器中bean的id 
-->
- 
set方法注入 p命名空间注入的本质是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下: 首先,需要引入p命名空间 xmlns:p="http://www.springframework.org/schema/p"其次,需要修改注入方式 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="com.jotian.dao.Impl.UserDaoImpl"/> <bean id="userService" class="com.jotian.service.Impl.UserServiceImpl" p:userDao-ref="userDao"> </bean> </beans>
- 
构造方法注入 
- 
public class UserServiceImpl implements UserService { private UserDao userDao; public UserServiceImpl(UserDao userDao) { this.userDao = userDao; } @Override public void save() { userDao.save(); } }<bean id="userDao" class="com.jotian.dao.Impl.UserDaoImpl"/> <bean id="userService" class="com.jotian.service.Impl.UserServiceImpl"> <constructor-arg name="userDao" ref="userDao"/> </bean> <!--前userDao是构造方法里面的参数名 后userDao引用容器中的id -->
Bean的依赖注入的数据类型
上面的操作,都是注入的应用Bean,除了对象的引用可以注入,普通数据类型,集合等都可以在容器中进行注入。
注入的数据类型:
- 普通数据类型
- 引用数据类型【上面的注入全是引用数据类型的注入】
- 集合数据类型
public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    public String[] getBooks() {
        return books;
    }
    public void setBooks(String[] books) {
        this.books = books;
    }
    public List<String> getHobbys() {
        return hobbys;
    }
    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }
    public Map<String, String> getCard() {
        return card;
    }
    public void setCard(Map<String, String> card) {
        this.card = card;
    }
    public Set<String> getGames() {
        return games;
    }
    public void setGames(Set<String> games) {
        this.games = games;
    }
    public String getWife() {
        return wife;
    }
    public void setWife(String wife) {
        this.wife = wife;
    }
    public Properties getInfo() {
        return info;
    }
    public void setInfo(Properties info) {
        this.info = info;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="address" class="com.jotian.pojo.Address"/>
<!--第一种:普通值注入,value-->
    <bean id="student" class="com.jotian.pojo.Student" >
        <property name="name" value="冰天雪地"/>
<!--第二种: Bean注入,ref-->
        <property name="address" ref="address"/>
<!--第三种:数组-->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
        </property>
<!--第四种:List-->
        <property name="hobbys">
            <list>
                <value>上课</value>
                <value>看书</value>
                <value>看网课</value>
                <value>敲代码</value>
            </list>
        </property>
<!--Map-->
        <property name="card">
            <map>
                <entry key="语文" value="87"/>
                <entry key="数学" value="140"/>
                <entry key="英语" value="37"/>
                <entry key="物理" value="87"/>
            </map>
        </property>
<!--Set-->
        <property name="games">
            <set>
                <value>CS</value>
                <value>CF</value>
                <value>游戏</value>
                <value>莫忘少年凌云志,曾许人间第一流</value>
            </set>
        </property>
<!--null-->
        <property name="wife">
            <null/>
        </property>
<!--properties-->
        <property name="info">
            <props>
                <prop key="姓名">路星河</prop>
                <prop key="年龄">18</prop>
                <prop key="出生">同桌的你</prop>
                <prop key="live">耿耿星河</prop>
            </props>
        </property>
    </bean>
</beans>
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student = (Student) context.getBean("student");
        System.out.println(student.getName());
        System.out.println(student.getAddress());
        for (String book : student.getBooks()) {
            System.out.println(book);
        }
        System.out.println(student.getCard());
        System.out.println(student.getGames());
        System.out.println(student.getHobbys());
        System.out.println(student.getInfo());
        System.out.println(student.getWife());
    }
}
注:
map集合
<list>
    <entry key="user" value-ref=""></entry></entry>
</list>
<!--value-ref 后缀ref表示引用  引用的存在与容器当中-->
引入其他配置文件(分模块开发)
实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将这部分配置拆解到其他的配置文件中,而在Spring主配置文件通过import标签进行加载

<import resource="applicationContext-xxx.xml"/>
知识点小结
Spring的重点配置
标签  id 属性:在容器中Bean实例的唯一表识,不允许重复
 class 属性:要实例化的Bean的全限定名
 scope属性:Bean的作用范围,常用在Singleton(默认)【单例】和prototype【多例】
标签 :属性注入  name 属性:属性的名称
 value 属性:注入的普通属性值
 ref 属性:注入的对象引用值
标签
标签 
标签 
标签:导入其他的Spring的分文件 
Spring相关API
applicationContext:接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象

ApplicationContext的实现类
- 
ClassPathXmlApplicationContext 它是从类的根路径下加载配置文件推荐使用这种 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- 
FileSystemXmlApplicationContext 它是从磁盘路径下加载配置文件,配置文件可以在磁盘的任意位置 ApplicationContext context = new FileSystemXmlApplicationContext("C:\\Users\\jotian\\IdeaProjects\\Spring_SpringMVC_MyBatis\\Spring-01-Iop\\src\\main\\resources\\applicationContext.xml");
- 
AnnotationConfigApplicationContext 当使用注解配置容器对象时,需要使用此类来创建spring容器,它用来读取注解。 注解开发时讲 
getBean()方法使用
public Object getBean(String name) throws BeansException {
    this.assertBeanFactoryActive();
	return this.getBeanFactory().getBean(name);
    }
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    this.assertBeanFactoryActive();
    return this.getBeanFactory().getBean(name, requiredType);
    }
public <T> T getBean(Class<T> requiredType) throws BeansException {
    this.assertBeanFactoryActive();
    return this.getBeanFactory().getBean(requiredType);
    }
context.getBean("userService")
context.getBean("userService",UserService.class)
context.getBean(UserService.class)
其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回时Object,需要强转。当参数的数据类型是Class类型时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法报错。
知识要点
Spring的重点API
ApplicationContext context = new ClassPathXmlApplicationContext("xml文件")
context.getBean("id")
context.getBean(Class)
Spring配置数据源
数据源(连接池)的作用
- 数据源(连接池)是提高程序性能出现的
- 事先实例化数据源,初始化部分连接资源
- 使用连接资源时从数据库中获取
- 使用完毕之后将连接资源归还给数据源
常见的数据源(连接池): DBCP、C3P0、BoneCp、Druid等
不懂!!!???
数据源的开发步骤
- 
导入数据源的坐标和数据库驱动的坐标 - 数据库驱动的mysql-connector-java
 <!-- https://mvnrepository.com/artifact/c3p0/c3p0 --> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency>- c3p0
 <!-- https://mvnrepository.com/artifact/c3p0/c3p0 --> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency>- druid
 <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency>
- 
创建数据源对象 
- 
设置数据源的基本连接数据 
- 
使用数据源获取连接资源归还连接资源 
数据源的手动创建
测试:
    @Test
    //手动创建c3p0数据源
    public void test1() throws Exception {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mybatis");
        dataSource.setUser("root");
        dataSource.setPassword("1121");
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }
    @Test
    //测试手动创建druid数据源
    public void test2() throws SQLException {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
        dataSource.setUsername("root");
        dataSource.setPassword("1121");
        DruidPooledConnection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }
抽取配置文件:
- 
配置文件 jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.user=root jdbc.pwd=1121
- 
测试 @Test //测试手动创建druid数据源 public void test2() throws SQLException { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis"); dataSource.setUsername("root"); dataSource.setPassword("1121"); DruidPooledConnection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); }方便解耦不要把代码写死了! Spring配置数据源可以将DataSource的创建权交由Spring容器去完成set注入 - 
容器加载 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="user" value="root"/> <property name="password" value="1121"/> </bean>name后写的是setJdbcUrl 的 JdbcUrl -->jdbcUrl 
- 
测试u @Test public void test3() throws SQLException { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ComboPooledDataSource dataSource = context.getBean("dataSource", ComboPooledDataSource.class); Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); }
 
- 
抽取jdbc配置文件
applicationContext.xml加载jdbc.properties配置文件获取连接信息。
首先,需要引入context命名空间和约束路径
- 
命名空间:xmlns:context="http://www.springframework.org/schema/context" 
- 
约束路径:http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd <?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.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.pwd}"/> </bean> </beans>@Test public void test3() throws SQLException { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ComboPooledDataSource dataSource = context.getBean("dataSource", ComboPooledDataSource.class); Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); }
知识要点
Spring容器加载properties文件
<context:property-placeholder location="classpath:jdbc.properties"/>
        <property name="" value="${}"/>
Spring原始注解
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。
Spring原始注解主要是代替
注解
| 注解 | 说明 | 
|---|---|
| @Component | 使用在类上用于实例化Bean | 
| @Controller | 使用在web层类用于实例化Bean | 
| @Service | 使用在service层类上用于实例化Bean | 
| @Repository | 使用在dao层类上用于实例化Bean | 
| @Autowired | 使用在字段上用于根据类型依赖注入 | 
| @Qualifier | 结合@Autoeired一起使用用于根据名称进行依赖注入 | 
| @Resource | 相当于@Autowired+@Qualifier,按照名称进行注入 | 
| @Value | 注入普通属性 | 
| @Scope | 标注Bean的作用范围 | 
| @PostConstruct | 使用在方法上标注该方法是Bean的初始化方法 | 
| @PreDestroy | 使用在方法上标注该方法是Bean的销毁方法 | 
演示【xml配置】:
- 
dao public interface UserDao { void sava(); }public class UserDaoImpl implements UserDao { @Override public void sava() { System.out.println("UserDao---->sava方法执行"); } }
- 
service public interface UserService { void save(); }public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void save() { userDao.sava(); } }
- 
Bean注册 <bean id="userDao" class="com.jotian.dao.Impl.UserDaoImpl"/> <bean id="userService" class="com.jotian.service.Impl.UserServiceImpl"> <property name="userDao" ref="userDao"/> </bean>
- 
web【假的】 @Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserServiceImpl userService = context.getBean("userService", UserServiceImpl.class); userService.save();
演示【注解】
注意
使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定那个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类,字段和方法。
注解方式可以不要set方法!注意注解的位置
<!--注解的组件扫描-->
    <context:component-scan base-package="com.jotian"/>
- 
dao public interface UserDao { void sava(); }//<bean id="userDao" class="com.jotian.dao.Impl.UserDaoImpl"/> @Component("userDao") public class UserDaoImpl implements UserDao { @Override public void sava() { System.out.println("UserDao---->sava方法执行"); } }
- 
service public interface UserService { void save(); }//<bean id="userService" class="com.jotian.service.Impl.UserServiceImpl"> @Component("userService") public class UserServiceImpl implements UserService { private UserDao userDao; // <property name="userDao" ref="userDao"/> @Autowired @Qualifier("userDao") public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void save() { userDao.sava(); } }
- 
Bean注册 <!--配置组件扫描--> <context:component-scan base-package="com.jotian"/>
- 
Web @Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserServiceImpl userService = context.getBean("userService", UserServiceImpl.class); userService.save(); }
扩展衍生注解
- 
dao //<bean id="userDao" class="com.jotian.dao.Impl.UserDaoImpl"/> //@Component("userDao") @Repository("userDao") public class UserDaoImpl implements UserDao { @Override public void sava() { System.out.println("UserDao---->sava方法执行"); } }
- 
service //<bean id="userService" class="com.jotian.service.Impl.UserServiceImpl"> //@Component("userService") @Service("userService") public class UserServiceImpl implements UserService { // <property name="userDao" ref="userDao"/> @Autowired //按照数据类型从Spring容器中进行匹配的 @Qualifier("userDao") //是按照id值从容器中进行匹配。但是主要此处@Qualifier结合@Autowired一起使用 @Resource(name="userDao") //相当于@Autoeired和@Qualifier private UserDao userDao; @Override public void save() { userDao.sava(); } }@Value("itvast") private String name; @Value("${}") //配置文件里面找value private Stirng user
Spring新注解
使用上面的注解还不能全部代替xml配置文件,还需要使用注解代替的配置如下:
- 非自定义的Bean的配置:
- 加载properties文件的配置:<context:property-placeholder>
- 组件扫描的配置:context:component-scan
- 引入其他文件:
| 注解 | 说明 | 
|---|---|
| @Configuration | 用于指定当前类是一个Spring配置类,当创建容器时会从该类上加载注解 | 
| @ComponentScan | 用于指定Spring在初始化时要扫描的包。作用和在Spring的xml的配置文件中的<context:component-scan base-package=com.jotian/> | 
| @Bean | 使用在方法上,标注该方法的返回值存储到Spring容器中 | 
| @PropertySource | 用于加载.properties文件中的配置 | 
| @import | 用于导入其他的配置类 | 
@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Override
    public void sava() {
        System.out.println("UserDao---->sava方法执行");
    }
}
@Service("userService")
public class UserServiceImpl implements UserService {
    //    <property name="userDao" ref="userDao"/>
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;
    @Override
    public void save() {
     userDao.sava();
    }
}
// <context:property-placeholder location=""/>
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.user}")
    private String user;
    @Value("${jdbc.pwd}")
    private String pwd;
    @Bean("dataSource")
    public DataSource getDateSoutrce() throws Exception {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        return dataSource;
    }
}
//标志该类是Spring的核心配置类
@Configuration
//<!--配置组件扫描-->
//<context:component-scan base-package="com.jotian"/>
@ComponentScan("com.jotian")
//<import resource=""/>
@Import({DataSourceConfiguration.class})  //数组
public class SpringCofiguration {
}
    @Test
    public void test1(){
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringCofiguration.class);
        UserServiceImpl userService = context.getBean("userService", UserServiceImpl.class);
        userService.save();
    }
Spring集成Junit
原始Junit测试Spring的问题
在测试类中,每个测试方法都有以下两行代码:
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml")
IAccountService as = context.getBean("accountService",IAccountService.class);
这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常,所以又不能轻易删掉。
上述问题的解决方案
- 让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它
- 将需要进行测试Bean直接在测试类中进行注入
Spring集成junit步骤
@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Override
    public void sava() {
        System.out.println("save --> running");
    }
}
@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;
    @Override
    public void save() {
        userDao.sava();
    }
}
- 
导入spring继承的junit坐标 <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.12.RELEASE</version> </dependency>
- 
使用@RunWith注解替换原来的运行期 
- 
使用@ContextConfiguration指定配置文件或者配置类 
- 
使用@Autowired注入需要测试的对象 
- 
创建测试方法进行测试 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringConfiguration { @Autowired @Qualifier("userService") private UserService userService; @Test public void test1(){ userService.save(); } }
出现错误
- 当我们使用spring 5.x版本的时候,要求junit的jar必须是4.12及以上。
- 版本不一致。版本不匹配
Spring与Web环境集成
Tomcat
maven坐标导入--->web
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.2.1</version>
        </dependency>
ApplicationContext应用上下文获取方式
应用上下文对象是通过该 new ClassPathXmlApplicationContext(Spring配置文件)方式获取的,但是每次从容器中获得Bean时都要编写new ClassPathXmlApplicationContext(Spring配置文件),这样的弊端是配置文件加载多次,应用上下文对象创建多次。
在Web项目中,可以使用ServletContextListener监听Web应用的启动,我们可以在Web应用启动时,就夹在Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域servletContext域中,这样就可以在任意位置从域中获取上下文ApplicationContext对象了。
Spring提供获取应用上下文的工具
例子
public class ContextLoaderListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //读取web.xml中的全局参数
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //将Spring的应用上下文对象存储到ServletContext域中
        ServletContext servletContext = servletContextEvent.getServletContext();
        servletContext.setAttribute("context",context);
        System.out.println("Spring容器创建完毕。。。");
    }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    }
}
<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <!--全局初始化参数-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>applicationContext.xml</param-value>
    </context-param>
    <!--  配置监听器-->
    <listener>
        <listener-class>com.jotian.listener.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>userServlet</servlet-name>
        <servlet-class>com.jotian.web.UserServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>userServlet</servlet-name>
        <url-pattern>/userServlet</url-pattern>
    </servlet-mapping>
</web-app>
public class ContextLoaderListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext servletContext = servletContextEvent.getServletContext();
        //读取web.xml中的全局参数
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
        ApplicationContext context = new ClassPathXmlApplicationContext(contextConfigLocation);
        //将Spring的应用上下文对象存储到ServletContext域中
        servletContext.setAttribute("context",context);
        System.out.println("Spring容器创建完毕。。。");
    }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    }
}
public class WebApplicationContextUtils {
    public static ApplicationContext getWebApplicationContext(ServletContext servletContext){
       return (ApplicationContext) servletContext.getAttribute("context");
    }
}
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
//        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        ServletContext servletContext = req.getServletContext();
        ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        UserService userService = context.getBean("userService", UserService.class);
        userService.save();
    }
}
Spring提供获取应用上下文的工具
上面分析的不用手动实现,Spring提供了一个监听器ContextLoaderListener就是对上述功能的封装,该监听器类不加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供了一个客户端工具WebApplicationContextUtils供使用者获取应用上下文对象。
所以我们需要做的只有两件事:
- 
在web.xml中配置ContextLoaderListener监听器(导入spring-web坐标) <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.0.RELEASE</version> </dependency>
- 
在WebApplicationContextUtils获取应用上下文对象ApplicationContext ![]() 
    <!--全局初始化参数-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--  配置监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
导入Spring集成web的坐标
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.0.RELEASE</version>
    </dependency>
配置ContextLoaderListener监听器
    <!--全局初始化参数-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>applicationContext.xml</param-value>
    </context-param>
    <!--  配置监听器-->
    <listener>
        <listener-class>com.jotian.listener.ContextLoaderListener</listener-class>
    </listener>
通过工具获取应用上下文对象
ApplicationContext context = WebApplicationConextUtils。getWebApplicationContext(servletConext);
Object obj = applicationContext.getBean("id");
Spring继承web环境步骤
- 配置ContextLoaderListener监听器
- 使用WebApplicationContextUtils获取应用上下文
SpringMVC简介
SpringMVC概述
SpringMVC是一种基于java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品,已经融合在Spring Web Flow中。
SpringMVC已经成为目前最主流的MVC框架之一,并且随着Spring3.0的发布,全面超越Struts2,成为最优秀的MVC框架,它通过一套注解,让一个简单的java类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful编程风格的请求。

SpringMVC快速入门
需求:客户端发起请求,服务器端接收请求,执行逻辑并进行视图跳转。
开发步骤:
- 导入SpringMVC相关坐标
- 配置SpringMVC核心控制器DispathcerServlrt
- 创建Controller类和视图页面
- 使用注解配置Controller类中业务方法的映射地址
- 配置SpringMVC核心文件spring-MVC.xml
- 客户端发起请求测试
- 
success.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>我的第一个MVC ! hello</h1> </body> </html>
- 
web.xml <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <!--全局初始化参数--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!--监听器--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--配置SpringMVC的前端控制器--> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
- 
applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--注解的组件扫描--> <context:component-scan base-package="com.jotian"/> </beans>
- 
spring-mvc.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--Controller的组件扫描--> <context:component-scan base-package="com.jotian.controller"/> </beans>
- 
UserController.java @Controller @RequestMapping("/user") public class UserController { // 请求地址 http://localhost:8034/quick @RequestMapping("/quick") public String save(){ System.out.println("Controller save running..."); return "/success.jsp"; } }
SpringMvc流程图

SpringMVC组件解析
SpringMVC的执行流程

- 用户发送请求至前端控制器DispatcherServlet
- DispathcherServlet收到请求调用HandlerMapping处理器映射器
- 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有就生成)并返回给DispatcherServlet
- DispatcherServlet调用HandlerAdapter处理器适配器
- HandlerAdapter经过适配器调用具体的处理器(Controller,也叫后端控制器)
- Controller执行完成返回ModelAndView
- HandlerAdapte将controller执行结果ModelAndView返回给DispatcherServlet
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- ViewReslover解析后返回具体View
- DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet响应用户
SpringMVC注解解析
@Controller
作用:使用在web层类用于实例化Bean
@RequestMapping
作用:用于建立请求URL和处理请求方法之间的对应关系
位置:
- 类上,请求URL的第一级访问目录、此处不写的话,就相当于应用 的根目录
- 方法上,请求URL的第二级访问目录,写在类上的使用@RequestMapping标注的一级目录一起组成访问虚拟路径
- value:用于指定请求的URL。它和path属性的作用是一样的
- method:用于指定请求的方式
- params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的key和value必须与配置的一摸一样
- params={"accountName"} ,表示请求参数必须由accountName
- params={"moeny!100"},表示请求参数中money不能是100
@Controller
// 请求地址 http://localhost:8034/user/quick
@RequestMapping("/user")
public class UserController {
//    请求地址 http://localhost:8034/quick
    @RequestMapping("/quick")
    public String save(){
        System.out.println("Controller save running...");
        return "/success.jsp";
    }
}
mvc命名空间注入
命名空间:
xmlns:context="http://www.springframework.org/schema/context"
约束地址:
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
组件扫描
SpringMVC基于Spring容器,所以进行SpringMVC操作时,需要将Controller存储到Spring容器中,如果使用@Controller注解标注的话,就需要使用<context:component-scan base-package=”com.jotian.controller“>进行组件扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--注解的组件扫描-->
    <context:component-scan base-package="com.jotian"/>
</beans>
    <!--注解的组件扫描-->
    <context:component-scan base-package="com.jotian">
        <!--只扫描Controller这个组件-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--只扫描Controller这个组件之外的-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
Spring XMl文件配置
SpringMVC的相关组件
- 前端控制器:DispatcherServlet
- 处理器映射器:HandlerMapping
- 处理器适配器:HandlerAdapter
- 处理器:Handler
- 视图解析器:view Resolver
- 视图:View
SpringMVC的注解和配置
- 
请求映射注解:@RequestMapping 
- 
视图解析器配置:(前后缀) REDIRECT_URL_PREFIX = "redirect" FORWARD_URL_PREFIX = "forward" prefix=""; suffix="";
SpringMVC的数据响应
Spring数据响应的方式
- 
页面跳转 - 直接返回字符串
- 通过ModelAndView对象返回
 
- 
回写数据 - 直接返回字符串
- 返回对象或结果集
 页面跳转返回字符串形式直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转 
@Controller
@RequestMapping("/user")
public class UserController {
//    请求地址 http://localhost:8034/quick
    @RequestMapping("/quick")
    public String save(){
        System.out.println("Controller save running...");
        return "success";
    }
}

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
返回ModelAndView
    @RequestMapping("quick2")
    public ModelAndView save2(){
        /**
         * modol:模型 作用封装数据
         * view: 视图 作用战术数据
         */
        ModelAndView modelAndView = new ModelAndView();
        //设置模型数据
        modelAndView.addObject("username","itcast");
        //设置视图名称
        modelAndView.setViewName("success");
        return modelAndView;
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>我的第一个MVC ! hello</h1>
<h1> ${username} </h1>
</body>
</html>
取不到数据 <%isELIgnored="false"%> 加上这个
Spring会自动提供数据对象 例如
    @RequestMapping("quick3")
    public ModelAndView save3(ModelAndView modelAndView){
        modelAndView.addObject("username","jotian");
        modelAndView.setViewName("success");
        return modelAndView;
    }
    @RequestMapping("quick4")
    public String save4(Model model){
        model.addAttribute("username","自学java");
        return "success";
    }
@RequestMapping("quick5")
public String save5(HttpServletRequest request){
    request.setAttribute("username","jotian自学java");
    return "success";
}
回写数据
直接返回字符串
Web基础阶段,客户端访问服务器端,如果想直接回写字符串作为相应体返回的话,只需要使用response.getWriter().print(“hello word”)即可,那么再Controller中想直接回写字符串该怎么样呢?
- 
通过SpringMVC框架注入的response对象,使用reponse.getWriter().pring(“hello word”)回写数据,此时不需要视图跳转,业务方法返回值void @RequestMapping("/quick6") public void quickMethod4(HttpServletResponse response) throwa IOException{ response.getWriter().print("hello world") }错误 Spring不能智能到知道你是要跳转页面还是回写文字 @RequstMapping("/quisk7") public String save7(){ return "hello word"; //这个应该是自动寻找视图跳转 而不是回文字,所以会直接报错 }
- 
直接返回字符串 将需要回写的字符串直接返回,但是此时需要通过@ResponseBody注解告知SpringMVC框架,方法返回的字符串不是跳转是直接在http响应中返回。 @RequnstMapping("/quick8") @ResponseBody public String save8(){ return "(\"username\":\"zhangsan\",\"age\":18)"; }导入josn包 <dependecy> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependecy> <dependecy> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependecy> <dependecy> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependecy>@RequnstMapping("/quick8") @ResponseBody public String save8(){ User user = new User(); user.setUserName("张三"); user.setAge(18); //使用json的转换工具将对象装换成json格式字符串在返回。 ObjecMapper objectMapper = new ObjectMapper(); String json = objectMapper.wrteValueAsString(user); return json; }返回对象或集合<!--配置处理器映射器--> <bean class="org.springframework.web.server.annotation.RequestMapingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/> </list> </property> </bean>@RequnstMapping("/quick8") @ResponseBody //期望SpringMVC自动将User装换成json格式的字符串 public User save8(){ User user = new User(); user.setUserName("张三"); user.setAge(18); return user; }细节点: 在方法上添加@ResponseBody就可以返回json格式的字符串,但是这样配置比较麻烦,配置的代码比较多,因此,我们可以使用mvc的注解驱动代替上述配置 <!--mvc的注解驱动--> <mvc:annotation-driven/>在SpringMVC的各个组件中,处理器映射器,处理器适配器,视图解析器称为SpringMVC的三大组件。使用mvc:annotation-drivern自动加载RequestMappingHandlerMapping(处理器映射器)和RequestMappingHandlerAdapter(处理适配器),可用Spring-xml.xml配置文件中使用mvc:annotation-driven替代注解处理器和适配器的配置。 同时使用mvc:annotation-driven默认底层就会集成jackson进行对象或集合的json格式字符串的转换。 
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <mvc:annotation-driven/>
知识要点
SpringMVC的数据响应方式
- 页面跳转
- 直接返字符串
- 通过ModelAndView对象返回
 
- 回写数据
- 直接返回接返回字符串
- 返回对象或集合
 
SpringMVC获得请求数据
获得请求参数
客户端请求参数的格式是:name=value&name=value...
服务器端要获得请求参数,又是还需要进行数据的封装,SpringMVC可以接收如下类型的参数:
- 基本类型参数
- POJO类型参数
- 数组类型参数
- 集合类型参数
获得基本类型参数
Controller的业务方法的参数名称要与请求参数的name一致,参数值会自动映射匹配
http://localhost:8080/jotian_springmvc/quick?username=zhangsan&age=18
@RequestMapping("/quick")
@ResponseBody
public void save(String username,int age)throw Exception{
    System.out.println(username);
    System.out.pringln(age);
}
获得POJO类型参数
Controller的业方法的POJO参数的属性名与请求参数的name一致,参数值会自动映射匹配
http://localhost:8080/jotian_springmvc/quick?username=zhangsan&age=18
@Date
public void User{
    private String username;
    private int age;
}
@RequestMappring("/quick")
@ResponseBody
public void quickMethod(User user)throws Exception{
    System.out.pringln(user)
}
获得数组类型参数
Controller中的业务方法数组名称与请求参数的name一致,参数会自动映射匹配
http://localhost:8080/jotian_springmvc/quick?strs=zhangsan&strs=18
@RequestMapping("/quick")
@ResponseBody
public void quickMethod(Stinrg[] strs)throws Exception{
System.out.pringln(Arrays.asList(strs));
}
获得集合类型参数
获得集合参数时,要将集合参数包装到一个POJO中才可以
- VO对象
@Date
public class VO {
	private List<User> userList;
}
@RequestMapping("/quick")
@ResponseBody
public void save(Vo vo)throws Exception{
    System.out.pringln(vo);
}
<from action="${pageContext.request.contextPath}/user/quick14" method="post">
    <input type="test" name="usetList[0].username"><br/>
    <input type="test" name="usetList[0].age"><br/>
    <input type="test" name="usetList[1].username"><br/>
    <input type="test" name="usetList[1].age"><br/>
    <input type="submit" value="提交">
</from>
获得集合类型参数
当使用ajax提交时,可以指定contentType未json形式,那么在方法参数位置使用RequestBody可以直接接收集合数据而无需似乎用POJO进行包装
获取Restful风格的参数
Restful是一种软件架构风格,设计风格,而不是标准,只是提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
Restful风格的请求是使用“url+请求方式”表示一次请求的目的,HTTP协议里面是个表示操作的动词如下:
- GET:用于获取资源
- POST:用于新建资源
- PUT:用于更新资源
- DELETE:用于删除资源
例如:
- /user/1 GET : 得到id=1的user
- /user/1 DELETE : 删除id=1 的user
- /user/1 PUT: 更新id=1的user
- /user POST: 新增user
上述url地址/user/1中的1就是要要获得的请求参数,在SpringMVC中可以使用占位符进行参数绑定,地址/user/1可以写成/user/{id},占位符{id}对应的就是1的值,在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取工作。
http://localhost:8080/itheima_springmvc/quick/zhangsan
@RequestMapping("/quick/{name}")
@ResponseBody
public void quickMethod(@PathVariable(value="name" required=true)String name){
		System.out.println(name);
}
自定义类型转换器
- SpringMVC默认已经提供了一些常用的类型转换器,例如客户端提供的字典转换成int型进行参数设置。
- 但是不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器,例如:日期类型的数据就需要自定义转换器。
自定义类型转换器的开发步骤:
- 定义转换器类型的Converter接口
- 在配置文件中声明转换器
- 在中引用转换器 
获取Servlet相关的API
SpringMVC支持使用原始ServletAPI对象作为控制器方法的参数进行注入,常用的对象如下:
- 
HttpServletRequest 
- 
HttpServletResponse 
- 
HttpSession @ResquestMapping("/quick") @ResponseBody public void quickMethod16(HttpServletRequest request,HttpServletResponse response,HttpSession session){ System.out.println(resquest); System.out.println(response); System.out.println(session); }
获取请求头@Resquest
- 
@ResquestHeader 使用@ResquestHeader可以获得请求头信息,相当于web阶段学习的request.getHeader(name)@ResquestHeader注解的属性如下: - value:请求头名称
- required :是否必须携带此请求头
 @ResquestMapping("/quick") @ResponseBody public void save(@ResquestHeader(value="User_Agent",required=false)String user_agent)throws Exception{ System.out.println(user_agent) }
- 
@CookieValue 使用@CooKieValue可以获得指定Cookie的值 @CookieValue注解的属性如下: - 
value:指定cookie的名称 
- 
required:是否必须携带此cookie @ResquestMapping("quick") @ResponseBody public void save(@CookieValue(value="JESSIONID")String jessionId){ System.out.println(jessionId); }
 
- 
文件上传
- 
文件上传客户端三要数- 
表单项type=“file” 
- 
表单的提交方式是post 
- 
表单的enctype属性是多部分表单形式,级enctype=“multipart/form-data” <form action="${pageContext.request.contextPath}/quick" method="post" enctype="multipart/form-data"> 名称:<input type="text" name="name"><br> 文件:<input type="file" name="file"><br> <input type="submit" value="提交"><br> </form>
- 
当from表单修改为多部份表单时,request.getParameter()将失效 
- 
enctype=“appilcation/x-www-from-urlencoded”时,form表单的正文内容格式是:key=value&key=value&key=value 
- 
当form表单的enctype取值为Mutilpart/from-data时,请求正文内容就变为多部份形式: 
 单文件上传的步骤- 导入fileupload和io坐标
 <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency>- 配置文件上传解析器
 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommoonsMultipartResolver"> <!--上传文件总大小--> <property name="maxUploadSize" value="5242800"/> <!--上传单个文件的大小--> <property name="maxUploadSizePerFile" value="5343800" <!--上传文件的编码类型--> <property name="defaultEncoding" value="UTF-8"> <bean/>- 编写文件上传代码
 @RequestMapping("/quick") @ResponseBody public void quickMethod20(String name,MultipaetFile uploadFile)throws IOException{ //获得文件名称 String originalFilename = uploadFile.getOriginalFilename(); //保存文件 uploadFile.transferTo(new File("C:\\upload\\"+oridinalFilename)); }
- 
多文件上传实现
多文件上传,只需要将页面修改为多个文件上传项,将方法参数MultipartFile类型修改为MultipartFile[]即可
<h1>多文件上传测试</h1>
<form action="${pageContext.request.contextPath}/quick" method="post" enctype="multipart/form-data">
    名称:<input type="text" name="name"><br>
    文件1:<input type="file" name="uploadFiles"><br>
    文件2:<input type="file" name="uploadFiles"><br>
    文件3:<input type="submit" value="提交"><br>
</form>
@RequestMappping("/quick")
@ResponseBody
public void quickMethod(String name,MultipartFile[] uploadFiles)throws IOException{
    for(MultipartFile uploadFile:uploadFiles){
        String originalFilename = uploadFile.getOriginalFilename();
        uploadFile.transferTo(new File("C:\\upload\\"+originalFilename));
    }
}
知识要点
MVC实现数据请求方式
- 基本类型参数
- POJO类型参数
- 数组类型参数
- 集合类型参数
MVC获取数据细节
- 中文乱码问题
- @RequestParam和@PathVariable
- 自定义类型转换器
- 获得Serclet相关API
- @RequestHeader和@CookieValue
- 文件上传
附页:
Springmvc jar包介绍
spring.jar是包含有完整发布的单个jar 包,spring.jar中包含除了spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环境下才会用到 spring-mock.jar来进行辅助测试,正式应用系统中是用不得这些类的。
除了spring.jar文件,Spring还包括有其它13个独立的jar包,各自包含着对应的Spring组件,用户可以根据自己的需要来选择组合自己的jar包,而不必引入整个spring.jar的所有类文件。
(1) spring-core.jar
这个jar文件包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统中使用这些工具类。
(2) spring-beans.jar
这个jar文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI支持,引入spring-core.jar及spring-beans.jar文件就可以了。
(3) spring-aop.jar
这个jar文件包含在应用中使用Spring的AOP特性时所需的类。使用基于AOP的Spring特性,如声明型事务管理(Declarative Transaction Management),也要在应用里包含这个jar包。
(4) spring-context.jar
这个jar文件为Spring核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI所需的全部类,UI方面的用来与模板(Templating)引擎如Velocity、FreeMarker、JasperReports集成的类,以及校验Validation方面的相关类。
(5) spring-dao.jar
这个jar文件包含Spring DAO、Spring Transaction进行数据访问的所有类。为了使用声明型事务支持,还需在自己的应用里包含spring-aop.jar。
(6) spring-hibernate.jar
这个jar文件包含Spring对Hibernate 2及Hibernate 3进行封装的所有类。
(7) spring-jdbc.jar
这个jar文件包含对Spring对JDBC数据访问进行封装的所有类。
(8) spring-orm.jar
这个jar文件包含Spring对DAO特性集进行了扩展,使其支持 iBATIS、JDO、OJB、TopLink,因为Hibernate已经独立成包了,现在不包含在这个包里了。这个jar文件里大部分的类都要依赖spring-dao.jar里的类,用这个包时你需要同时包含spring-dao.jar包。
(9) spring-remoting.jar
这个jar文件包含支持EJB、JMS、远程调用Remoting(RMI、Hessian、Burlap、Http Invoker、JAX-RPC)方面的类。
(10) spring-support.jar
这个jar文件包含支持缓存Cache(ehcache)、JCA、JMX、邮件服务(Java Mail、COS Mail)、任务计划Scheduling(Timer、Quartz)方面的类。
(11) spring-web.jar
这个jar文件包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。
(12) spring-webmvc.jar
这个jar文件包含Spring MVC框架相关的所有类。包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、XSLT相关类。当然,如果你的应用使用了独立的MVC框架,则无需这个JAR文件里的任何类。
(13) spring-mock.jar
这个jar文件包含Spring一整套mock类来辅助应用的测试。Spring测试套件使用了其中大量mock类,这样测试就更加简单。模拟HttpServletRequest和HttpServletResponse类在Web应用单元测试是很方便的。
如何选择这些发布包,决定选用哪些发布包其实相当简单。
如果你正在构建Web应用并将全程使用Spring,那么最好就使用单个全部的spring.jar文件;
如果你的应用仅仅用到简单的Inversion of Control / Dependency Injection(IoC/DI)容器,那么只需spring-core.jar与spring-beans.jar即可;
如果你对发布的大小要求很高,那么就得精挑细选了,只取包含自己所需特性的jar文件了。
采用独立的发布包你可以避免包含自己的应用不需要的全部类。当然你可以采用其它的一些工具来设法令整个应用包变小,节省空间的重点在于准确地找出自己所需的Spring依赖类,然后合并所需的类与包就可以了。
Eclispe有个插件叫ClassPath Helper可以帮你找找所依赖的类。
Spring包依赖说明:
\1) spring-core.jar需commons-collections.jar,spring-core.jar是以下其它各个的基本。
\2) spring-beans.jar需spring-core.jar,cglib-nodep-2.1_3.jar
\3) spring-aop.jar需spring-core.jar,spring-beans.jar,cglib-nodep-2.1_3.jar,aopalliance.jar
\4) spring-context.jar需spring-core.jar,spring-beans.jar,spring-aop.jar,commons-collections.jar,aopalliance.jar
\5) spring-dao.jar需spring-core.jar,spring-beans.jar,spring-aop.jar,spring-context.jar
\6) spring-jdbc.jar需spring-core.jar,spring-beans.jar,spring-dao.jar
\7) spring-web.jar需spring-core.jar,spring-beans.jar,spring-context.jar
\8) spring-webmvc.jar需spring-core.jar/spring-beans.jar/spring-context.jar/spring-web.jar
\9) spring-hibernate.jar需spring-core.jar,spring- beans.jar,spring-aop.jar,spring-dao.jar,spring-jdbc.jar,spring- orm.jar,spring-web.jar,spring-webmvc.jar
\10) spring-orm.jar需spring-core.jar,spring-beans.jar,spring-aop.jar,spring-dao.jar,spring-jdbc.jar,spring-web.jar,spring-webmvc.jar
\11) spring-remoting.jar需spring-core.jar,spring-beans.jar,spring- aop.jar,spring-dao.jar,spring-context.jar,spring-web.jar,spring- webmvc.jar
\12) spring-support.jar需spring-core.jar,spring-beans.jar,spring-aop.jar,spring-dao.jar,spring-context.jar,spring-jdbc.jar
\13) spring-mock.jar需spring-core.jar,spring-beans.jar,spring-dao.jar,spring-context.jar,spring-jdbc.jar
一、只是使用spring框架
dist\spring.jar
lib\jakarta-commons\commons-logging.jar
如果使用到了切面编程(AOP),还需要下列jar文件
lib\aspectj\aspectjweaver.jsr 和 aspectjrt.jar
lib\cglib\cglib-nodep-2.1_3.jar
如果使用了JSR-250中的注解如@Resource/@PostConstruct/@PreDestroy
还需下列jar文件
lib\j2ee\common-annotations.jar
二、只是使用spring框架若使用注解方式
只要加一些命名空间和开启解析器
并且@Resource需要加lib\j2ee\common-annotations.jar
打开处理器
三、要自动扫描
只要开启解析器和一些命名空间
四、spring框架采用aop编程
需要导入一些命名空间
xmlns:aop.......
开启解析器
如果使用到了切面编程(AOP),还需要下列jar文件
lib\aspectj\aspectjweaver.jsr 和 aspectjrt.jar
lib\cglib\cglib-nodep-2.1_3.jar
五、spring+Jdbc开发
需要数据源文件 lib\jakarta-commons\commons-pool.jar、lib\jakarta-commons\commons-dbcp.jar
1、spring文件 :
dist\spring.jar、
lib\jakarta-commons\commons-logging.jar
2、jdbc驱动文件 mysql**** sql*** :
导入tx命名空间
对事务注解的解析器
六、spring2.5+hibernate3.3+struts1.3
(1)、hibernate核心包
hibernate3.jar
lib\required*.jar
lib\optional\ehcache-1.2.3.jar (二级缓存文件)
hibernate注解包
lib\test\slf4j-log4j12.jar
(2)、spring包
dist\spring.jar
lib\jakarta-commons\commons-logging.jar 和commons-pool.jar、commons-dbcp.jar(后为数据源文件)
dist\modules\spring-webmvc-struts.jar (与struts1的集成)
lib\aspectj\aspectjweaver.jsr 和 aspectjrt.jar (Aop文件)
lib\cglib\cglib-nodep-2.1_3.jar (Aop文件)
lib\j2ee\common-annotations.jar (注解文件)
lib\log4j\log4j-1.2.15.jar
(3)、sturs1.3.8
建议将jstl-1.0.2.jar和standard-1.0.2.jar文件更换为1.1版本此时JSTL文件
还有spring已存在antlr-2.7.6.jar文件所以将struts中的antlr-2.7.6.jar文件删除以免冲突
数据库驱动
mysql*** sql****根据需求换
如果在web容器实例spring容器
加文件到web.xml......
如果action让容器管理,则path(Struts的配置文件)和name(Spring配置文件)要一致
还必须在struts的配置文件里加一个控制器
spring为struts1.3解决乱码问题
在web.xml配置一个filter
七、spring2.5+hibernate3.3+struts2整合开发
struts2文件lib里面所有不带-plugin结尾的jar文件,但除了struts2-spring-plugin-2.0.11.1.jar
 
                    
                     
                    
                 
                    
                

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号