ssm框架大整合

一、Spring

Ioc

IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

HelloSpring

导入jar包

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.1.10.RELEASE</version>
</dependency>

//1、编写一个Hello实体类
public class Hello {
  private String name;

  public String getName() {
      return name;
}
  public void setName(String name) {
      this.name = name;
}

  public void show(){
      System.out.println("Hello,"+ name );
}
}
编写spring配置文件
<?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就是java对象 , 由Spring创建和管理-->
  <bean id="hello" class="com.kuang.pojo.Hello">
      <property name="name" value="Spring"/>
  </bean>
</beans>
测试
@Test
public void test(){
  //解析beans.xml文件 , 生成管理相应的Bean对象
  ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  //getBean : 参数即为spring配置文件中bean的id .
  Hello hello = (Hello) context.getBean("hello");
  hello.show();
}

思考

  • Hello 对象是谁创建的 ? 【hello 对象是由Spring创建的

  • Hello 对象的属性是怎么设置的 ? hello 对象的属性是由Spring容器设置的

这个过程就叫控制反转 :

  • 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的

  • 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .

依赖注入 : 就是利用set方法来进行注入的.

IOC是一种编程思想,由主动的编程变成被动的接收

可以通过newClassPathXmlApplicationContext去浏览一下底层源码 .

IOC创建对象方式

1、通过无参构造方法来创建
   
public class User {

  private String name;

  public User() {
      System.out.println("user无参构造方法");
}

  public void setName(String name) {
      this.name = name;
}

  public void show(){
      System.out.println("name="+ name );
}

}
bean.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="user" class="com.kuang.pojo.User">
      <property name="name" value="kuangshen"/>
  </bean>

</beans>

 

2、通过有参构造方法来创建

public class UserT {

  private String name;

  public UserT(String name) {
      this.name = name;
}

  public void setName(String name) {
      this.name = name;
}

  public void show(){
      System.out.println("name="+ name );
}

}
bean.xml

<!-- 第一种根据index参数下标设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
   <!-- index指构造方法 , 下标从0开始 -->
   <constructor-arg index="0" value="kuangshen2"/>
</bean>

<!-- 第二种根据参数名字设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
   <!-- name指参数名 -->
   <constructor-arg name="name" value="kuangshen2"/>
</bean>

<!-- 第三种根据参数类型设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
   <constructor-arg type="java.lang.String" value="kuangshen2"/>
</bean>

依赖注入

set注入

要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is .

Address.java

public class Address {
 
     private String address;
 
     public String getAddress() {
         return address;
    }
 
     public void setAddress(String address) {
         this.address = address;
    }
 }

Student.java

 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 void setName(String name) {
         this.name = name;
    }
 
     public void setAddress(Address address) {
         this.address = address;
    }
 
     public void setBooks(String[] books) {
         this.books = books;
    }
 
     public void setHobbys(List<String> hobbys) {
         this.hobbys = hobbys;
    }
 
     public void setCard(Map<String, String> card) {
         this.card = card;
    }
 
     public void setGames(Set<String> games) {
         this.games = games;
    }
 
     public void setWife(String wife) {
         this.wife = wife;
    }
 
     public void setInfo(Properties info) {
         this.info = info;
    }
 
     public void show(){
         System.out.println("name="+ name
                 + ",address="+ address.getAddress()
                 + ",books="
        );
         for (String book:books){
             System.out.print("<<"+book+">>\t");
        }
         System.out.println("\n爱好:"+hobbys);
 
         System.out.println("card:"+card);
 
         System.out.println("games:"+games);
 
         System.out.println("wife:"+wife);
 
         System.out.println("info:"+info);
 
    }
 }

1、常量注入

<bean id="student" class="com.kuang.pojo.Student">
     <property name="name" value="小明"/>
</bean>

2、Bean注入

<bean id="addr" class="com.kuang.pojo.Address">
     <property name="address" value="重庆"/>
</bean>
 
<bean id="student" class="com.kuang.pojo.Student">
     <property name="name" value="小明"/>
     <property name="address" ref="addr"/>
</bean>

3、数组注入

<bean id="student" class="com.kuang.pojo.Student">
     <property name="name" value="小明"/>
     <property name="address" ref="addr"/>
     <property name="books">
         <array>
             <value>西游记</value>
             <value>红楼梦</value>
             <value>水浒传</value>
         </array>
     </property>
</bean>

4、List注入

<property name="hobbys">
     <list>
         <value>听歌</value>
         <value>看电影</value>
         <value>爬山</value>
     </list>
 </property>

5、Map注入

<property name="card">
     <map>
         <entry key="中国邮政" value="456456456465456"/>
         <entry key="建设" value="1456682255511"/>
     </map>
 </property>

6、set注入

<property name="games">
     <set>
         <value>LOL</value>
         <value>BOB</value>
         <value>COC</value>
     </set>
 </property>

7、Null注入

<property name="wife"><null/></property>

8、Properties注入

<property name="info">
     <props>
         <prop key="学号">20190604</prop>
         <prop key="性别">男</prop>
         <prop key="姓名">小明</prop>
     </props>
 </property>

p命名和c命名注入

User.java

 public class User {
     private String name;
     private int age;
 
     public void setName(String name) {
         this.name = name;
    }
 
     public void setAge(int age) {
         this.age = age;
    }
 
     @Override
     public String toString() {
         return "User{" +
                 "name='" + name + '\'' +
                 ", age=" + age +
                 '}';
    }

1、P命名空间注入 : 需要在头文件中加入约束文件

导入约束 : xmlns:p="http://www.springframework.org/schema/p"
 
 <!--P(属性: properties)命名空间 , 属性依然要设置set方法-->
 <bean id="user" class="com.kuang.pojo.User" p:name="狂神" p:age="18"/>

2、c 命名空间注入 : 需要在头文件中加入约束文件

 导入约束 : xmlns:c="http://www.springframework.org/schema/c"
 <!--C(构造: Constructor)命名空间 , 属性依然要设置set方法-->
 <bean id="user" class="com.kuang.pojo.User" c:name="狂神" c:age="18"/>

发现问题:爆红了,刚才我们没有写有参构造!

解决:把有参构造器加上,这里也能知道,c 就是所谓的构造器注入!

自动装配

自动装配说明

  • 自动装配是使用spring满足bean依赖的一种方法

  • spring会在应用上下文中为某个bean寻找其依赖的bean。

Spring中bean有三种装配机制,分别是:

  1. 在xml中显式配置;

  2. 在java中显式配置;

  3. 隐式的bean发现机制和自动装配。

这里我们主要讲第三种:自动化的装配bean。

Spring的自动装配需要从两个角度来实现,或者说是两个操作:

  1. 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;

  2. 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;

组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。

推荐不使用自动装配xml配置 , 而使用注解 .

1、新建一个项目

2、新建两个实体类,Cat Dog 都有一个叫的方法

public class Cat {
   public void shout() {
       System.out.println("miao~");
  }
}

public class Dog {
   public void shout() {
       System.out.println("wang~");
  }
}

public class User {
   private Cat cat;
   private Dog dog;
   private String str;
}
<?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="dog" class="com.kuang.pojo.Dog"/>
   <bean id="cat" class="com.kuang.pojo.Cat"/>

   <bean id="user" class="com.kuang.pojo.User">
       <property name="cat" ref="cat"/>
       <property name="dog" ref="dog"/>
       <property name="str" value="qinjiang"/>
   </bean>
</beans>
public class MyTest {
   @Test
   public void testMethodAutowire() {
       ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
       User user = (User) context.getBean("user");
       user.getCat().shout();
       user.getDog().shout();
  }
}

结果正常输出,环境OK

byName

autowire byName (按名称自动装配)

由于在手动配置xml过程中,常常发生字母缺漏和大小写等错误,而无法对其进行检查,使得开发效率降低。

采用自动装配将避免这些错误,并且使配置简单化。

测试:

1、修改bean配置,增加一个属性 autowire="byName"

<bean id="user" class="com.kuang.pojo.User" autowire="byName">
   <property name="str" value="qinjiang"/>
</bean>

2、再次测试,结果依旧成功输出!

3、我们将 cat 的bean id修改为 catXXX

4、再次测试, 执行时报空指针java.lang.NullPointerException。因为按byName规则找不对应set方法,真正的setCat就没执行,对象就没有初始化,所以调用时就会报空指针错误。

小结:

当一个bean节点带有 autowire byName的属性时。

  1. 将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。

  2. 去spring容器中寻找是否有此字符串名称id的对象。

  3. 如果有,就取出注入;如果没有,就报空指针异常。

 

byType

autowire byType (按类型自动装配)

使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。

NoUniqueBeanDefinitionException

测试:

1、将user的bean配置修改一下 : autowire="byType"

2、测试,正常输出

3、在注册一个cat 的bean对象!

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>

<bean id="user" class="com.kuang.pojo.User" autowire="byType">
   <property name="str" value="qinjiang"/>
</bean>

4、测试,报错:NoUniqueBeanDefinitionException

5、删掉cat2,将cat的bean名称改掉!测试!因为是按类型装配,所以并不会报异常,也不影响最后的结果。甚至将id属性去掉,也不影响结果。

这就是按照类型自动装配!

使用注解

使用注解

jdk1.5开始支持注解,spring2.5开始全面支持注解。

准备工作:利用注解的方式注入属性。

1、在spring配置文件中引入context文件头

xmlns:context="http://www.springframework.org/schema/context"

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd

2、开启属性注解支持!

<context:annotation-config/>

@Autowired

  • @Autowired是按类型自动转配的,不支持id匹配。

  • 需要导入 spring-aop的包!

测试:

1、将User类中的set方法去掉,使用@Autowired注解

public class User {
   @Autowired
   private Cat cat;
   @Autowired
   private Dog dog;
   private String str;

   public Cat getCat() {
       return cat;
  }
   public Dog getDog() {
       return dog;
  }
   public String getStr() {
       return str;
  }
}

2、此时配置文件内容

<context:annotation-config/>

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User"/>

3、测试,成功输出结果!

@Autowired(required=false) 说明:false,对象可以为null;true,对象必须存对象,不能为null。

//如果允许对象为null,设置required = false,默认为true
@Autowired(required = false)
private Cat cat;

@Qualifier

  • @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配

  • @Qualifier不能单独使用。

测试实验步骤:

1、配置文件修改内容,保证类型存在对象。且名字不为类的默认名字!

<bean id="dog1" class="com.kuang.pojo.Dog"/>
<bean id="dog2" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>

2、没有加Qualifier测试,直接报错

3、在属性上添加Qualifier注解

@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;

@Resource

  • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;

  • 其次再进行默认的byName方式进行装配;

  • 如果以上都不成功,则按byType的方式自动装配。

  • 都不成功,则报异常。

实体类:

public class User {
   //如果允许对象为null,设置required = false,默认为true
   @Resource(name = "cat2")
   private Cat cat;
   @Resource
   private Dog dog;
   private String str;
}
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>

<bean id="user" class="com.kuang.pojo.User"/>

测试:结果OK

配置文件2:beans.xml , 删掉cat2

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>

实体类上只保留注解

@Resource
private Cat cat;
@Resource
private Dog dog;

结果:OK

结论:先进行byName查找,失败;再进行byType查找,成功。

小结

@Autowired与@Resource异同:

1、@Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。

2、@Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用

3、@Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。


使用注解开发

在spring4之后,想要使用注解形式,必须得要引入aop的包

<?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">

</beans>

Bean的实现

我们之前都是使用 bean 的标签进行bean注入,但是实际开发中,我们一般都会使用注解!

1、配置扫描哪些包下的注解

<!--指定注解扫描包-->
<context:component-scan base-package="com.kuang.pojo"/>

2、在指定包下编写类,增加注解

@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
   public String name = "秦疆";
}

属性注入

使用注解注入属性

1、可以不用提供set方法,直接在直接名上添加@value("值")

@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
   @Value("秦疆")
   // 相当于配置文件中 <property name="name" value="秦疆"/>
   public String name;
}

2、如果提供了set方法,在set方法上添加@value("值");

@Component("user")
public class User {

   public String name;

   @Value("秦疆")
   public void setName(String name) {
       this.name = name;
  }
}

衍生注解

我们这些注解,就是替代了在配置文件当中配置步骤而已!更加的方便快捷!

@Component三个衍生注解

为了更好的进行分层,Spring可以使用其它三个注解,功能一样,目前使用哪一个功能都一样。

  • @Controller:web层

  • @Service:service层

  • @Repository:dao层

写上这些注解,就相当于将这个类交给Spring管理装配了!

自动装配注解

在Bean的自动装配已经讲过了,可以回顾!

作用域

@scope

  • singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。

  • prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收

@Controller("user")
@Scope("prototype")
public class User {
   @Value("秦疆")
   public String name;
}

小结

XML与注解比较

  • XML可以适用任何场景 ,结构清晰,维护方便

  • 注解不是自己提供的类使用不了,开发简单方便

xml与注解整合开发 :推荐最佳实践

  • xml管理Bean

  • 注解完成属性注入

  • 使用过程中, 可以不用扫描,扫描是为了类上的注解

<context:annotation-config/>  

作用:

  • 进行注解驱动注册,从而使注解生效

  • 用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向Spring注册

  • 如果不扫描包,就需要手动配置bean

  • 如果不加注解驱动,则注入的值为null!

     

 

 

aop

 

AOP:面向切面、面向方面、面向接口是一种横切技术 横切技术运用: 1.事务管理: (1)数据库事务:(2)编程事务(3)声明事物:Spring AOP-->声明事物 2.日志处理: 3.安全验证: Spring AOP---OOP升级

静态代理原理:目标对象:调用业务逻辑 代理对象:日志管理 表示层调用--->代理对象(日志管理)-->调用目标对象

动态代理原理:spring AOP采用动态代理来实现 (1)实现InvocationHandler接口

(2)创建代理类(通过java API)

Proxy.newProxyInstance(动态加载代理类,代理类实现接口,使用handler);

(3)调用invoke方法(虚拟机自动调用方法)

日志处理 //调用目标对象 method.invoke("目标对象","参数"); 日志处理

通过代理对象--(请求信息)-->目标对象---(返回信息)----> 代理对象

 

Spring 动态代理中的基本概念

1、关注点(concern) 一个关注点可以是一个特定的问题,概念、或者应用程序的兴趣点。总而言之,应用程序必须达到一个目标 安全验证、日志记录、事务管理都是一个关注点 在oo应用程序中,关注点可能已经被代码模块化了还可能散落在整个对象模型中 2、横切关注点(crosscutting concern) 如何一个关注点的实现代码散落在多个类中或方法中 3、方面(aspect) 一个方面是对一个横切关注点模块化,它将那些原本散落在各处的, 用于实现这个关注点的代码规整在一处 4、建议(advice)通知 advice是point cut执行代码,是方面执行的具体实现 5、切入点(pointcut) 用于指定某个建议用到何处 6、织入(weaving) 将aspect(方面)运用到目标对象的过程 7、连接点(join point) 程序执行过程中的一个点

通知类型: try{ //前置通知 //环绕通知 //调用目标对象方法 //环绕通知 //后置通知 }catch(){ //异常通知 }finally{ //终止通知 }

一.静态代理原理实例:

IUserServ接口代码

public interface IUserServ {  
    List<User> findAllUser();  
    int deleteUserById(User user);  
    int saveUser(User user);  
}  

UserServImpl实现类代码

public class UserServImpl implements IUserServ {  
    public int deleteUserById(User user) {  
        System.out.println("******执行删除方法******");  
        return 0;  
    }  
    public List<User> findAllUser() {  
        System.out.println("*******执行查询方法*******");  
        return null;  
    }  
    public int saveUser(User user) {  
        System.out.println("*******执行添加方法********");  
        return 0;  
    }  
}  

UserServProxyImpl实现类代码

//代理类:完成日志输出  
public class UserServProxyImpl implements IUserServ {  
    // 访问目标对象(UserServImpl)  
    // 代理对象(UserServProxyImpl)  
    // 创建目标对象  
    private IUserServ iuserServ ;//= new UserServImpl();  
  
    public UserServProxyImpl(IUserServ iuserServ){  
        this.iuserServ = iuserServ;  
    }  
    public int deleteUserById(User user) {  
        beforeLog();  
        //调用目标对象里方法  
        iuserServ.deleteUserById(user);  
        afterLog();  
        return 0;  
    }  
  
    public List<User> findAllUser() {  
        beforeLog();  
        //调用目标对象里方法  
        iuserServ.findAllUser();  
        afterLog();  
        return null;  
    }  
  
    public int saveUser(User user) {  
        beforeLog();  
        //调用目标对象里方法  
        iuserServ.saveUser(user);  
        afterLog();  
        return 0;  
    }  
  
    private void beforeLog() {  
        System.out.println("开始执行");  
    }  
      
    private void afterLog() {  
        System.out.println("执行完毕");  
    }  
}  

ActionTest测试类代码

public class ActionTest {  
    public static void main(String[] args) {  
        //用户访问代理对象---信息->目标对象  
        IUserServ iuserServ = new UserServProxyImpl(new UserServImpl());  
        iuserServ.findAllUser();  
    }  
}  

运行结果:

开始执行 ***执行查询方法*** 执行完毕

 

二.动态代理实例

IUserServ接口代码与UserServImpl实现类代码和上述代码相同

LogHandler类代码

public class LogHandler implements InvocationHandler {  
    //目标对象  
    private Object targetObject;  
    /** 
     * 创建动态代理类 
     * @return object(代理类) 
     */  
    public Object createProxy(Object targetObject){  
        this.targetObject = targetObject;  
        return Proxy.newProxyInstance(  
                targetObject.getClass().getClassLoader(),   
                    targetObject.getClass().getInterfaces(), this);  
    }  
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object obj = null;  
        try {  
            beforeLog();  
            //obj: 目标对象--->代理对象的返回值--->返回给调用者的信息  
            //this.invoke("目标对象","代理对象给目标对象传递参数");  
            //调用目标对象中方法  
            obj = method.invoke(targetObject, args);  
            afterLog();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return obj;  
    }  
      
    //日志管理方法  
    private void beforeLog(){  
        System.out.println("开始执行");  
    }  
      
    private void afterLog(){  
        System.out.println("执行完毕");  
    }  
  
}  

ActionTest测试类代码:

public class ActionTest {  
    public static void main(String[] args) {  
        //创建代理对象iuserServ  
        LogHandler handler = new LogHandler();  
        IUserServ iuserServ = (IUserServ)handler.createProxy(new UserServImpl());  
        iuserServ.deleteUserById(new User());  
    }  
}  

运行结果: 开始执行 **执行删除方法** 执行完毕

 

三.Spring AOP(方式一)

2.x版本之前

IUserServ接口代码与UserServImpl实现类代码和上述代码相同

1、配置目标对象(applicationContext.xml)

<bean id="userServTarget" class="com.tarena.biz.impl.UserServImpl"/>   

2、配置通知 (a)前置通知(BeforeLogAdvice)

public class BeforeLogAdvice implements MethodBeforeAdvice {  
     /** 
        * Method method:调用目标对象的方法 
        * Object[] args:发送给目标对象的参数列表 
        * Object target:目标对象 
        */  
    public void before(Method method, Object[] args, Object target)  
            throws Throwable {  
        beforeLog();  
    }  
    private void beforeLog(){  
        System.out.println("开始执行");  
    }  
}  

(b)后置通知(AfterLogAdvice)

public class AfterLogAdvice implements AfterReturningAdvice {  
      /** 
        * Object returnValue:目标对象返回值 
        *  Method method:目标对象方法名 
        *  Object[] args:目标对象参数列表 
        *  Object target:目标对象 
        */  
    public void afterReturning(Object returnValue, Method method,  
            Object[] args, Object target) throws Throwable {  
        afterLog();  
    }  
    private void afterLog(){  
        System.out.println("执行完毕");  
    }  
}  

(c)在spring容器中,让容器管理通知(applicationContext.xml)

<!-- 定义通知 -->  
        <!-- 前置通知 -->  
        <bean id="beforeLogAdvice" class="com.tarena.advice.BeforeLogAdvice"/>  
        <!-- 后置通知 -->  
        <bean id="afterLogAdvice" class="com.tarena.advice.AfterLogAdvice"/>  

3、配置代理对象(applicationContext.xml)

<!-- 代理类作用: 生成代理类,织入通知 -->    
  <bean id="userServProxy"   
   class="org.springframework.aop.framework.ProxyFactoryBean">  
   <property name="interfaces">  
   <!-- 可以添加多个接口 -->  
    <list>  
     <value>com.tarena.biz.IUserServ</value>  
    </list>  
   </property>  
   <!-- 引入通知 -->  
   <property name="interceptorNames">  
    <list>  
     <value>beforeLogAdvice</value>  
     <value>afterLogAdvice</value>  
    </list>  
   </property>  
   <!-- 目标对象 -->  
   <property name="target" ref="userServTarget"/>  
  </bean>  

4.访问() Spring容器:通过代理对象调用-->织入通知--->目标对象 程序员:访问代理对象

测试类(ActionTest):

public class ActionTest {  
    public static void main(String[] args) {  
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");  
        IUserServ iuserServ = (IUserServ)ac.getBean("userServProxy");  
        iuserServ.deleteUserById(new User());  
        iuserServ.findAllUser();  
    }  
}  

运行结果:

开始执行 **执行删除方法** 执行完毕 开始执行 ***执行查询方法*** 执行完毕

 

四.Spring AOP(方式二)

2.x版本之后

这种方式需要额外添加两个jar包,

存放位置在spring-framework-2.5.6.SEC01\lib\aspectj文件夹下。

 

IUserServ接口代码与UserServImpl实现类代码和上述代码相同

LogAdvice中

public class LogAdvice {  
    public void beforeLog(){  
        System.out.println("开始执行");  
    }  
    public void afterLog(){  
        System.out.println("执行完毕");  
    }  
}  

applicationContext.xml中

<!-- spring2.x后 -->  
    <!-- 目标对象 -->  
    <bean id="userServImpl" class="com.tarena.biz.impl.UserServImpl"/>  
    <!-- 通知 -->  
    <bean id="logAdvice" class="com.tarena.advice.LogAdvice"/>  
      
    <aop:config>  
        <aop:aspect id="logAspect" ref="logAdvice">  
            <!-- 切入点 -->  
            <aop:pointcut id="beforePointCut"   
        expression="execution(* saveUser*(..))"/>  
        <aop:pointcut id="afterPointCut"   
        expression="execution(* saveUser*(..))"/>  
              
            <!-- 织入(通知作用于切入点) -->  
            <aop:before method="beforeLog" pointcut-ref="beforePointCut"/>  
            <aop:after method="afterLog" pointcut-ref="afterPointCut"/>  
        </aop:aspect>  
    </aop:config>  

测试类:

public class ActionTest {  
    public static void main(String[] args) {  
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");  
        IUserServ iuserServ = (IUserServ)ac.getBean("userServImpl");  
        iuserServ.deleteUserById(new User());  
        iuserServ.findAllUser();  
        iuserServ.saveUser(new User());  
    }  
}  

运行结果 **执行删除方法** ***执行查询方法*** 开始执行 ***执行添加方法**** 执行完毕

注:如果要在业务层所有的方法前后添加日志文件,则需要更改为以下配置

<aop:pointcut id="beforePointCut"   
        expression="execution(* com.tarena.biz.*.*(..))"/>  
        <aop:pointcut id="afterPointCut"   
        expression="execution(* com.tarena.biz.*.*(..))"/>  

运行结果:

开始执行 **执行删除方法** 执行完毕 开始执行 ***执行查询方法*** 执行完毕 开始执行 ***执行添加方法**** 执行完毕

 

五.环绕通知

包含前置、后置等等

示例代码:

日志类:

import org.aspectj.lang.ProceedingJoinPoint;
public class Logger {
    //前置通知
    public void  beforePrintLog(){
        System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志");
    }
    //后置通知
    public void  afterReturnPrintLog(){
        System.out.println("后置通知Logger类中的afterReturnPrintLog方法开始记录日志");
    }
    //异常通知
    public void  afterThrowingPrintLog(){
        System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志");
    }
    //最终通知
    public void  afterPrintLog(){
        System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志");
    }

    /*
     * 环绕通知:
     * 配置环绕通知之后,切入点方法没有执行,但是通知方法执行了
     * 解决:
     * Spring框架为我们提供了一个接口:ProceedingJoinPoint
     * 该接口中提供了一个方法procceed(),此方法就相当于明确调用切入点方法
     * 该接口可以作为环绕通知接口的参数,在程序执行时,
     * 在Spring程序执行时,Spring框架会为我们提供该接口的实现类供我么使用
     */
    public Object  aroundPrintLog(ProceedingJoinPoint pjp){
        Object result = null;
        try {
            Object[] args = pjp.getArgs();//得到方法执行的返回参数

            System.out.println("Logger类中的aroundPrintLog方法开始记录日志...前置");

            pjp.proceed(args);//明确调用业务层方法

            System.out.println("Logger类中的aroundPrintLog方法开始记录日志...后置");
            return result;
        } catch (Throwable throwable) {
            System.out.println("Logger类中的aroundPrintLog方法开始记录日志...异常");
            throw new RuntimeException(throwable);
        }finally {
            System.out.println("Logger类中的aroundPrintLog方法开始记录日志...最终");
        }
    }
}

配置

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置Spring的IOC-->
    <bean id="accountService" class="com.hh.service.AccountServiceImpl"/>
    <bean id="logger" class="com.hh.utils.Logger"/>
    <!--配置AOP-->
    <aop:config>
        <aop:aspect id="logAdvice" ref="logger">
            <!--配置环绕通知-->
            <aop:around method="aroundPrintLog" pointcut-ref="pt"/>
            <aop:pointcut id="pt" expression="execution(* com.hh.service.*.*(..))"/>
        </aop:aspect>
    </aop:config>
</beans>

六.注解实现

xml

开启aop注解支持
<aop:aspectj-autoproxy/>

具体实现

@Component
@Aspect //切面注解
public class Logger {

    @Before(value = "execution(* com.jun.service.*.*(..))")
    public void beforeLog(JoinPoint joinPoint){
        System.out.println("前置通知"+joinPoint.getSignature().getName());
    }

    @After(value = "execution(* com.jun.service.*.*(..))")
    public void afterLog(JoinPoint joinPoint){
        System.out.println("后置通知通知"+joinPoint.getSignature().getName());
    }
}

JdbcTemplate事务

 

基本概念

什么是事务

  • 事务就是将一组SQL语句放在同一批次内去执行

  • 如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行

  • MySQL事务处理只支持InnoDB和BDB数据表类型

 

事务的ACID原则 百度 ACID

原子性(Atomic)

  • 整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(ROLLBACK)到事务开始前的状态,就像这个事务从来没有执行过一样。

一致性(Consist)

  • 一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant),以转账案例为例,假设有五个账户,每个账户余额是100元,那么五个账户总额是500元,如果在这个5个账户之间同时发生多个转账,无论并发多少个,比如在A与B账户之间转账5元,在C与D账户之间转账10元,在B与E之间转账15元,五个账户总额也应该还是500元,这就是保护性和不变性。

隔离性(Isolated)

  • 隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。

持久性(Durable)

  • 在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

 

jdbc基本使用

xml注入配置

 <!--    加载数据库配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--开启包扫描-->
    <context:component-scan base-package="com"/>
    <!--    配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--    配置spring_jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

dao层代码示例

@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public void moneyOut(Integer code, Float money) {
        String sql="update account set money=money-? where code=?";
        jdbcTemplate.update(sql,money,code);

    }

    @Override
    public void moneyIn(Integer code, Float money) {
        String sql="update account set money=money+? where code=?";
        jdbcTemplate.update(sql,money,code);
    }
}

事务处理示例

1、编程式处理(不推荐使用----繁琐)

public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;
    //配置事务管理器
    private DataSourceTransactionManager manager;

    public void setManager(DataSourceTransactionManager manager) {
        this.manager = manager;
    }

    public DataSourceTransactionManager getManager() {
        return manager;
    }

    //set方法注入
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(Integer outCode, Integer inCode, float money) {

        TransactionStatus transaction = null;
        try {
            //定义事务状态
            DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
            //设置传播行为
            definition.setPropagationBehavior(3);
            //获取事务状态
            transaction=manager.getTransaction(definition);

            accountDao.moneyOut(outCode, money);
            int a=10/0;
            accountDao.moneyIn(inCode, money);

            manager.commit(transaction);
        } catch (Exception e) {
            System.out.println("异常回滚");
            manager.rollback(transaction);
        }
    }
}

xml配置

<!--    配置spring_jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--    注入持久层-->
    <bean id="accountDao" class="com.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
    <!--    注入业务层-->
    <bean id="accountService" class="com.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="manager" ref="manger"/>
    </bean>
    <!--    创建事务管理器-->
    <bean id="manger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

 

2、声明式事务管理

 public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;
    //set方法注入
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    @Override
    public void transfer(Integer outCode, Integer inCode, float money) {
        accountDao.moneyOut(outCode, money);
        int a = 10 / 0;
        accountDao.moneyIn(inCode, money);

    }
}

xml声明式配置

 <!--    配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--配置spring_jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--注入持久层-->
    <bean id="accountDao" class="com.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
    <!--注入业务层-->
    <bean id="accountService" class="com.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>


    <!--创建、配置事务管理器-->
    <bean id="manger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置事务属性  配置通知 引入事务,命名空间-->
    <tx:advice id="txAdvice" transaction-manager="manger">
        <tx:attributes>
            <!--配置属性名  即使需要事务的方法名  例如find*  就是find开头的方法  * 就是全部方法-->
            <!-- REQUIRED是默认的-->
            <tx:method name="transfer" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--    配置切入点  aop实现-->
    <aop:config>
        <!--        配置切入点表达式-->
        <aop:pointcut id="txPointCut" expression="execution(* com.service.impl.AccountServiceImpl.*(..))"/>
        <!--        配置通知-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

 

Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。

 

两种方式的优缺点:

 

编程式事务管理

  • 将事务管理代码嵌到业务方法中来控制事务的提交和回滚

  • 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

声明式事务管理

  • 一般情况下比编程式事务好用。

  • 将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。

  • 将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。

 

 

 

spring事务传播特性:

事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。spring支持7种事务传播行为:

  • propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。

  • propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。

  • propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。

  • propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。

  • propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

  • propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。

  • propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作

Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。

假设 ServiveX#methodX() 都工作在事务环境下(即都被 Spring 事务增强了),假设程序中存在如下的调用链:Service1#method1()->Service2#method2()->Service3#method3(),那么这 3 个服务类的 3 个方法通过 Spring 的事务传播机制都工作在同一个事务中。

就好比,我们刚才的几个方法存在调用,所以会被放在一组事务当中!

 

 

二、Spring-MVC

1、回顾MVC

1.1、什么是MVC

  • MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。

  • 是将业务逻辑、数据、显示分离的方法来组织代码。

  • MVC主要作用是降低了视图与业务逻辑间的双向偶合

  • MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。

Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。

View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。

Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。

最典型的MVC就是JSP + servlet + javabean的模式。

1.2、Model1时代

  • 在web早期的开发中,通常采用的都是Model1。

  • Model1中,主要分为两层,视图层和模型层。

  • Model1优点:架构简单,比较适合小型项目开发;

    Model1缺点:JSP职责不单一,职责过重,不便于维护;

    1.3、Model2时代

    Model2把一个项目分成三部分,包括视图、控制、模型。

    1. 用户发请求

    2. Servlet接收请求数据,并调用对应的业务逻辑方法

    3. 业务处理完毕,返回更新后的数据给servlet

    4. servlet转向到JSP,由JSP来渲染页面

    5. 响应给前端更新后的页面

    职责分析:

    Controller:控制器

    1. 取得表单数据

    2. 调用业务逻辑

    3. 转向指定的页面

    Model:模型

    1. 业务逻辑

    2. 保存数据的状态

    View:视图

    1. 显示页面

    Model2这样不仅提高的代码的复用率与项目的扩展性,且大大降低了项目的维护成本。Model 1模式的实现比较简单,适用于快速开发小规模项目,Model1中JSP页面身兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度。Model2消除了Model1的缺点。

MVC框架要做哪些事情

  1. 将url映射到java类或java类的方法 .

  2. 封装用户提交的数据 .

  3. 处理请求--调用相关的业务处理--封装响应数据 .

  4. 将响应的数据进行渲染 . jsp / html 等表示层数据 .

说明:

常见的服务器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF;常见前端MVC框架:vue、angularjs、react、backbone;由MVC演化出了另外一些模式如:MVP、MVVM 等等....

 

2、什么是SpringMVC

2.1、概述

Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。

查看官方文档:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web

我们为什么要学习SpringMVC呢?

Spring MVC的特点:

  1. 轻量级,简单易学

  2. 高效 , 基于请求响应的MVC框架

  3. 与Spring兼容性好,无缝结合

  4. 约定优于配置

  5. 功能强大:RESTful、数据验证、格式化、本地化、主题等

  6. 简洁灵活

Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。

DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;

正因为SpringMVC好 , 简单 , 便捷 , 易学 , 天生和Spring无缝集成(使用SpringIoC和Aop) , 使用约定优于配置 . 能够进行简单的junit测试 . 支持Restful风格 .异常处理 , 本地化 , 国际化 , 数据验证 , 类型转换 , 拦截器 等等......所以我们要学习 .

最重要的一点还是用的人多 , 使用的公司多 .

2.2、中心控制器

Spring的web框架围绕DispatcherServlet设计。DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式。

Spring MVC框架像许多其他MVC框架一样, 以请求为驱动 , 围绕一个中心Servlet分派请求及提供其他功能DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)

图片

SpringMVC的原理如下图所示:

当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。

图片

2.3、SpringMVC执行原理

图片

图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。

简要分析执行流程

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。

    我们假设请求的url为 : http://localhost:8080/SpringMVC/hello

     

    如上url拆分成三部分:

    http://localhost:8080服务器域名

    SpringMVC部署在服务器上的web站点

    hello表示控制器

    通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。

  2. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。

  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。

  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。

  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。

  6. Handler让具体的Controller执行。

  7. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。

  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。

  9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。

  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet。

  11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。

  12. 最终视图呈现给用户。

第一个MVC程序

配置版

1、新建一个Moudle , springmvc-02-hello , 添加web的支持!

2、确定导入了SpringMVC 的依赖!

3、配置web.xml , 注册DispatcherServlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
        version="4.0">

   <!--1.注册DispatcherServlet-->
   <servlet>
       <servlet-name>springmvc</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:springmvc-servlet.xml</param-value>
       </init-param>
       <!--启动级别-1-->
       <load-on-startup>1</load-on-startup>
   </servlet>

   <!--/ 匹配所有的请求;(不包括.jsp)-->
   <!--/* 匹配所有的请求;(包括.jsp)-->
   <servlet-mapping>
       <servlet-name>springmvc</servlet-name>
       <url-pattern>/</url-pattern>
   </servlet-mapping>

</web-app>

4、编写SpringMVC 的 配置文件!名称:springmvc-servlet.xml : [servletname]-servlet.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">

</beans>

5、添加 处理映射器

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

6、添加 处理器适配器

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

7、添加 视图解析器

<!--视图解析器:DispatcherServlet给他的ModelAndView-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">   
    <!--前缀-->   
    <property name="prefix" value="/WEB-INF/jsp/"/>  
    <!--后缀-->   
    <property name="suffix" value=".jsp"/>
</bean>

8、编写我们要操作业务Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图;

//注意:这里我们先导入Controller接口
public class HelloController implements Controller {

   public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
       //ModelAndView 模型和视图
       ModelAndView mv = new ModelAndView();

       //封装对象,放在ModelAndView中。Model
       mv.addObject("msg","HelloSpringMVC!");
       //封装要跳转的视图,放在ModelAndView中
       mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
       return mv;
  }
   

9、将自己的类交给SpringIOC容器,注册bean

<!--Handler--><bean id="/hello" class="com.kuang.controller.HelloController"/>

10、写要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面;

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>   
            <title>Kuangshen</title>
        </head>
        <body>
            ${msg}
        </body>
    </html>

11、配置Tomcat 启动测试!

 

注解版

1、新建一个Moudle,springmvc-03-hello-annotation 。添加web支持!

2、由于Maven可能存在资源过滤的问题,我们将配置完善

<build>
   <resources>
       <resource>
           <directory>src/main/java</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
       <resource>
           <directory>src/main/resources</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
   </resources>
</build>

3、在pom.xml文件引入相关的依赖:主要有Spring框架核心库、Spring MVC、servlet , JSTL等。我们在父依赖中已经引入了!

4、配置web.xml

注意点:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
        version="4.0">

   <!--1.注册servlet-->
   <servlet>
       <servlet-name>SpringMVC</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:springmvc-servlet.xml</param-value>
       </init-param>
       <!-- 启动顺序,数字越小,启动越早 -->
       <load-on-startup>1</load-on-startup>
   </servlet>

   <!--所有请求都会被springmvc拦截 -->
   <servlet-mapping>
       <servlet-name>SpringMVC</servlet-name>
       <url-pattern>/</url-pattern>
   </servlet-mapping>

</web-app>

/ 和 /* 的区别:< url-pattern > / </ url-pattern > 不会匹配到.jsp, 只针对我们编写的请求;即:.jsp 不会进入spring的 DispatcherServlet类 。< url-pattern > /* </ url-pattern > 会匹配 *.jsp,会出现返回 jsp视图 时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错。

    • 注意web.xml版本问题,要最新版!

    • 注册DispatcherServlet

    • 关联SpringMVC的配置文件

    • 启动级别为1

    • 映射路径为 / 【不要用/*,会404】

       

 

  1. 5、添加Spring MVC配置文件

  2. 在resource目录下添加springmvc-servlet.xml配置文件,配置的形式与Spring容器配置基本类似,为了支持基于注解的IOC,设置了自动扫描包的功能,具体配置信息如下:

  3. <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:mvc="http://www.springframework.org/schema/mvc"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
       <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
       <context:component-scan base-package="com.kuang.controller"/>
       <!-- 让Spring MVC不处理静态资源 -->
       <mvc:default-servlet-handler />
       <!--
       支持mvc注解驱动
           在spring中一般采用@RequestMapping注解来完成映射关系
           要想使@RequestMapping注解生效
           必须向上下文中注册DefaultAnnotationHandlerMapping
           和一个AnnotationMethodHandlerAdapter实例
           这两个实例分别在类级别和方法级别处理。
           而annotation-driven配置帮助我们自动完成上述两个实例的注入。
        -->
       <mvc:annotation-driven />
    
       <!-- 视图解析器 -->
       <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
             id="internalResourceViewResolver">
           <!-- 前缀 -->
           <property name="prefix" value="/WEB-INF/jsp/" />
           <!-- 后缀 -->
           <property name="suffix" value=".jsp" />
       </bean>
    
    </beans>
    
    1. 在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。

      • 让IOC的注解生效

      • 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 .....

      • MVC的注解驱动

      • 配置视图解析器

 

  1. 6、创建Controller

  2. 编写一个Java控制类:com.kuang.controller.HelloController , 注意编码规范

  3. package com.kuang.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("/HelloController")
    public class HelloController {
    
       //真实访问地址 : 项目名/HelloController/hello
       @RequestMapping("/hello")
       public String sayHello(Model model){
           //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
           model.addAttribute("msg","hello,SpringMVC");
           //web-inf/jsp/hello.jsp
           return "hello";
      }
    }
    
    • @Controller是为了让Spring IOC容器初始化时自动扫描到;

    • @RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;

    • 方法中声明Model类型的参数是为了把Action中的数据带到视图中;

    • 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。

 

  1. 7、创建视图层

  2. 在WEB-INF/ jsp目录中创建hello.jsp , 视图可以直接取出并展示从Controller带回的信息;

  3. 可以通过EL表示取出Model中存放的值,或者对象;

  4. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
       <title>SpringMVC</title>
    </head>
    <body>
    ${msg}
    </body>
    </html>
    
  5. 小结

  6. 实现步骤其实非常的简单:

    1. 新建一个web项目

    2. 导入相关jar包

    3. 编写web.xml , 注册DispatcherServlet

    4. 编写springmvc配置文件

    5. 接下来就是去创建对应的控制类 , controller

    6. 最后完善前端视图和controller之间的对应

    7. 测试运行调试.

  7. 使用springMVC必须配置的三大件:

  8. 处理器映射器、处理器适配器、视图解析器

  9. 通常,我们只需要手动配置视图解析器,而处理器映射器处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置

RestFul 风格

概念

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

功能

资源:互联网所有的事物都可以被抽象为资源

资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。

分别对应 添加、 删除、修改、查询。

传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get

http://127.0.0.1/item/queryItem.action?id=1 查询,GET

http://127.0.0.1/item/saveItem.action 新增,POST

http://127.0.0.1/item/updateItem.action 更新,POST

http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST

使用RESTful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!

http://127.0.0.1/item/1 查询,GET

http://127.0.0.1/item 新增,POST

http://127.0.0.1/item 更新,PUT

http://127.0.0.1/item/1 删除,DELETE

学习测试

  1. 在新建一个类 RestFulController

    @Controller
    public class RestFulController {
        
    }
    
  2. 在Spring MVC中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上。

    @Controller
    public class RestFulController {
    
       //映射访问路径
       @RequestMapping("/commit/{p1}/{p2}")
       public String index(@PathVariable int p1, @PathVariable int p2, Model model){
           
           int result = p1+p2;
           //Spring MVC会自动实例化一个Model对象用于向视图中传值
           model.addAttribute("msg", "结果:"+result);
           //返回视图位置
           return "test";
           
      }
       
    }
     
    

 

 


 

三、mybatis

配置第一个mybatis

mybatis-config.xml 核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--   引入外部配置文件-->
    <properties resource="db.properties"/>
<!--    设置日志-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
        <!--开启驼峰命名法-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
<!--    别名-->
    <typeAliases>
        <typeAlias type="com.jun.pojo.Figure" alias="Figure"></typeAlias>
        <typeAlias type="com.jun.pojo.Camp" alias="Camp"></typeAlias>
        <typeAlias type="com.jun.pojo.Pro" alias="Pro"></typeAlias>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/jun/mapper/UserMapper.xml"/>
        <mapper resource="com/jun/mapper/FigureMapper.xml"/>
    </mappers>
</configuration>
xml映射文件  ****.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.BooksMapper">
<select id="queryAllBooks" resultType="domain.Books">
    select * from book
</select>
</mapper>
数据库相关信息  database.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/book?serverTimezone=UTC
username=root
password=1234
测试运行 java
     
        String resource="mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

		SqlSession sqlSession=sqlSessionFactory.openSession;
		XXXMapper mapper=sqlSession.getMapper(XXXMapper.class);
		mapper.xxx;

可能遇到的问题资源过滤maven

 <build>
        <resources>
            <resource>
                <!--   描述存放资源的目录,该路径相对POM路径-->
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

日志设置

导包log4j
 <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
 </dependency>


配置文件 resources/log4j.properties

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

设置启用
 <settings>
        <setting name="logImpl" value="LOG4J"/>
 </settings>

mybatis一对多和多对一处理

多对一的处理

按查询嵌套处理

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jun.mapper.StudentMapper">

   <!--
   需求:获取所有学生及对应老师的信息
   思路:
       1. 获取所有学生的信息
       2. 根据获取的学生信息的老师ID->获取该老师的信息
       3. 思考问题,这样学生的结果集中应该包含老师,该如何处理呢,数据库中我们一般使用关联查询?
           1. 做一个结果集映射:StudentTeacher
           2. StudentTeacher结果集的类型为 Student
           3. 学生中老师的属性为teacher,对应数据库中为tid。
              多个 [1,...)学生关联一个老师=> 一对一,一对多
           4. 查看官网找到:association – 一个复杂类型的关联;使用它来处理关联查询
   -->
   <select id="getStudents" resultMap="StudentTeacher">
       select * from student
   </select>
   <resultMap id="StudentTeacher" type="Student">
       
       如果属性名和数据库字段名一致  此处的属性映射可以省略
       只进行 关联  的映射操作  如下
       
       <!--association关联属性 property属性名 javaType属性类型 column在多的一方的表中的列名-->
       <association property="teacher"  column="tid" javaType="Teacher"                                                                             select="getTeacher"/>
   </resultMap>
   <!--
   这里传递过来的id,只有一个属性的时候,下面可以写任何值
   association中column多参数配置:
       column="{key=value,key=value}"
       其实就是键值对的形式,key是传给下个sql的取值名称,value是片段一中sql查询的字段名。
   -->
   <select id="getTeacher" resultType="teacher">
      select * from teacher where id = #{id}
   </select>

</mapper>

按结果嵌套处理

<!--
按查询结果嵌套处理
思路:
   1. 直接查询出结果,进行结果集的映射
-->
<select id="getStudents2" resultMap="StudentTeacher2" >
  select s.id sid, s.name sname , t.name tname
  from student s,teacher t
  where s.tid = t.id
</select>

<resultMap id="StudentTeacher2" type="Student">
    映射属性
   <id property="id" column="sid"/>
   <result property="name" column="sname"/>
    
   <!--关联对象property 关联对象在Student实体类中的属性-->
   <association property="teacher" javaType="Teacher">
       <result property="name" column="tname"/>
   </association>
</resultMap>

一对多的处理

按查询嵌套处理

<select id="getTeacher2" resultMap="TeacherStudent2">
select * from teacher where id = #{id}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
   <!--column是一对多的外键 , 写的是一的主键的列名-->
   <collection property="students" javaType="ArrayList" ofType="Student" column="id" select="getStudentByTeacherId"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
  select * from student where tid = #{id}
</select>

按结果嵌套处理

<mapper namespace="com.kuang.mapper.TeacherMapper">

   <!--
   思路:
       1. 从学生表和老师表中查出学生id,学生姓名,老师姓名
       2. 对查询出来的操作做结果集映射
           1. 集合的话,使用collection!
               JavaType和ofType都是用来指定对象类型的
               JavaType是用来指定pojo中属性的类型
               ofType指定的是映射到list集合属性中pojo的类型。
   -->
   <select id="getTeacher" resultMap="TeacherStudent">
      select s.id sid, s.name sname , t.name tname, t.id tid
      from student s,teacher t
      where s.tid = t.id and t.id=#{id}
   </select>

   <resultMap id="TeacherStudent" type="Teacher">
       <result  property="name" column="tname"/>
       <collection property="students" ofType="Student">
           <result property="id" column="sid" />
           <result property="name" column="sname" />
           <result property="tid" column="tid" />
       </collection>
   </resultMap>
</mapper>

 

 


四、SSM整合

环境搭建

1、新建一Maven项目!ssmbuild , 添加web的支持

2、导入相关的pom依赖!

<dependencies>
   <!--Junit-->
   <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.12</version>
   </dependency>
   <!--数据库驱动-->
   <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.47</version>
   </dependency>
   <!-- 数据库连接池 -->
  <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.6</version>
  </dependency>

   <!--Servlet - JSP -->
   <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>servlet-api</artifactId>
       <version>2.5</version>
   </dependency>
   <dependency>
       <groupId>javax.servlet.jsp</groupId>
       <artifactId>jsp-api</artifactId>
       <version>2.2</version>
   </dependency>
   <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>jstl</artifactId>
       <version>1.2</version>
   </dependency>

   <!--Mybatis-->
   <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis</artifactId>
       <version>3.5.2</version>
   </dependency>
   <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis-spring</artifactId>
       <version>2.0.2</version>
   </dependency>

   <!--Spring-->
   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-webmvc</artifactId>
       <version>5.1.9.RELEASE</version>
   </dependency>
   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-jdbc</artifactId>
       <version>5.1.9.RELEASE</version>
   </dependency>
</dependencies>

3、Maven资源过滤设置

<build>
   <resources>
       <resource>
           <directory>src/main/java</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
       <resource>
           <directory>src/main/resources</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
   </resources>
</build>

4、相关配置文件

mybatis-config.xml (mybatis配置文件)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--    设置日志-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
<!--    别名-->
    <typeAliases>
        <package name="domain.Books" />
    </typeAliases>
</configuration>

db.properties(数据库资源文件)

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/book?serverTimezone=UTC
jdbc.username=root
jdbc.password=1234

log4j.properties (日志配置文件)

#????DEBUG????????console?file???????console?file?????????
log4j.rootLogger=DEBUG,console,file
#??????????
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#?????????
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#??????
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

 

 

spring整合mybatis

 

spring-mybatis (Spring整合mybatis)

<?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
                           https://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 配置整合mybatis -->
    <!-- 1.关联数据库文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
    <!-- 2.数据库连接池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!--连接池基本属性-->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!--其他属性-->
        <property name="maxActive" value="20"/>
        <property name="maxWait" value="9000"/>
    </bean>
    <!-- 3.配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    <!-- 4.配置扫描Dao接口包,动态实现mapper接口注入到spring容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="mapper"/>
    </bean>
</beans>

 

 

spring整合MVC

web.xml (前端控制拦截器)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--DispatcherServlet-->
    <servlet>
        <servlet-name>example</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--encodingFilter-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--Session过期时间-->
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>
</web-app>

spring-mvc (spring整合mvc配置文件)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context.xsd
   http://www.springframework.org/schema/mvc
   https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 配置SpringMVC -->
    <!-- 1.开启SpringMVC注解驱动 -->
    <mvc:annotation-driven />
    <!-- 2.静态资源默认servlet配置-->
    <mvc:default-servlet-handler/>
    <!-- 3.配置jsp 显示ViewResolver视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <context:component-scan base-package="controller"/>
</beans>

 

 

Spring整合Service

spring-service (spring管理service层配置文件)

<?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">
    <!--开启service注解-->
    <context:component-scan base-package="service"/>
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
    </bean>
</beans>

applicationContext.xml (spring总容器)

<?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">
    <import resource="spring-mybatis.xml"/>
    <import resource="spring-service.xml"/>
    <import resource="spring-mvc.xml"/>
</beans>

 

 

 

五、文件上传

导入jar包

<dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
</dependency>

<dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
</dependency>

添加mvc层配置

 <bean id="multipartResolver"          class="org.springframework.web.multipart.commons.CommonsMultipartResolver" >
        <property name="maxUploadSize" value="104857600"/>
        <property name="defaultEncoding" value="utf-8"/>
        <property name="maxInMemorySize" value="40960"/>
 </bean>

表单添加属性

<form action="/upFile" method="post" enctype="multipart/form-data">
        <input type="file" name="file">
        <button type="submit">上传</button>
</form>

上传之后文件的保存,I/O流

Controller代码
    
@RequestMapping("/upFile")
    public void upload(@RequestParam("file") MultipartFile file){
//       获得文件名  aa.jpg
        String filename = file.getOriginalFilename();
        String name=System.currentTimeMillis()+filename;
        String path="F:/IDEA-   WorkFile/javaweb_demo/JavaEEWork/shiyanbaogao/web/image/upload";
        FileUpload.uploadFile(path,name,file);
    }


工具类
    public static void uploadFile(String path, String fileName, MultipartFile file) {
        File f = new File(path);
        if (!f.exists()) {
            f.mkdirs();
        }
        if (!file.isEmpty()) {
            try {
                FileOutputStream fileOutputStream = new FileOutputStream(path + "/" +                      fileName);
                InputStream inputStream = file.getInputStream();
                int b = 0;
                while ((b = inputStream.read()) != -1) {
                    fileOutputStream.write(b);
                }
                fileOutputStream.close();
                inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("文件上传到了--" + path + "/" + fileName);
    }

 

posted @ 2022-03-18 12:53  haijun666  阅读(48)  评论(0)    收藏  举报