Spring+SSM

Spring

基于黑马程序员SSM框架的课堂笔记,感谢黑马程序员!

# Spring+SpringMVC+MyBatis

Spring快速入门

  1. 导入相关依赖

    • 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>
    
  2. 接口 实现类 注册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>
    
  3. 测试

    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

注:

  1. 当scope的取值为singleton时

    Bean的实例化个数:1个

    Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例

    Bean的生命周期:

    • 对象创建:当应用加载,创建容器时,对象就被创建了
    • 对象运行:只有容器在,对象一直活着
    • 对象销毁:当应用加载,销毁容器时,对象就被销毁了
  2. 当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 
-->
  1. 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>
    
  2. 构造方法注入

  3. 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的实现类

  1. ClassPathXmlApplicationContext

    它是从类的根路径下加载配置文件推荐使用这种

            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
  2. FileSystemXmlApplicationContext

    它是从磁盘路径下加载配置文件,配置文件可以在磁盘的任意位置

            ApplicationContext context = new FileSystemXmlApplicationContext("C:\\Users\\jotian\\IdeaProjects\\Spring_SpringMVC_MyBatis\\Spring-01-Iop\\src\\main\\resources\\applicationContext.xml");
    
  3. 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();
    }
}
  1. 导入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>
    
  2. 使用@RunWith注解替换原来的运行期

  3. 使用@ContextConfiguration指定配置文件或者配置类

  4. 使用@Autowired注入需要测试的对象

  5. 创建测试方法进行测试

    @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供使用者获取应用上下文对象。

所以我们需要做的只有两件事:

  1. 在web.xml中配置ContextLoaderListener监听器(导入spring-web坐标)

        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>5.2.0.RELEASE</version>
        </dependency>
    
  2. 在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环境步骤

  1. 配置ContextLoaderListener监听器
  2. 使用WebApplicationContextUtils获取应用上下文

SpringMVC简介

SpringMVC概述

SpringMVC是一种基于java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品,已经融合在Spring Web Flow中。

SpringMVC已经成为目前最主流的MVC框架之一,并且随着Spring3.0的发布,全面超越Struts2,成为最优秀的MVC框架,它通过一套注解,让一个简单的java类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful编程风格的请求。

SpringMVC快速入门

需求:客户端发起请求,服务器端接收请求,执行逻辑并进行视图跳转。

开发步骤:

  1. 导入SpringMVC相关坐标
  2. 配置SpringMVC核心控制器DispathcerServlrt
  3. 创建Controller类和视图页面
  4. 使用注解配置Controller类中业务方法的映射地址
  5. 配置SpringMVC核心文件spring-MVC.xml
  6. 客户端发起请求测试
  • 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的执行流程

  1. 用户发送请求至前端控制器DispatcherServlet
  2. DispathcherServlet收到请求调用HandlerMapping处理器映射器
  3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有就生成)并返回给DispatcherServlet
  4. DispatcherServlet调用HandlerAdapter处理器适配器
  5. HandlerAdapter经过适配器调用具体的处理器(Controller,也叫后端控制器)
  6. Controller执行完成返回ModelAndView
  7. HandlerAdapte将controller执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  9. ViewReslover解析后返回具体View
  10. 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数据响应的方式

  1. 页面跳转

    • 直接返回字符串
    • 通过ModelAndView对象返回
  2. 回写数据

    • 直接返回字符串
    • 返回对象或结果集

    页面跳转

    返回字符串形式

    直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转

@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中想直接回写字符串该怎么样呢?

  1. 通过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";      //这个应该是自动寻找视图跳转  而不是回文字,所以会直接报错
    }
    
  2. 直接返回字符串

    将需要回写的字符串直接返回,但是此时需要通过@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的数据响应方式

  1. 页面跳转
    • 直接返字符串
    • 通过ModelAndView对象返回
  2. 回写数据
    • 直接返回接返回字符串
    • 返回对象或集合

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);
      }
      

文件上传

  1. 文件上传客户端三要数

    • 表单项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

posted @ 2021-12-24 10:08  Tian-Jotian-Yongxing  阅读(36)  评论(0)    收藏  举报