spring

一、spring IOC

1.spring IOC定义

        IOC 是 Inversion of Control 的缩写,多数书籍翻译成“控制反转”。简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从⽽降低了解决问题的复杂度,⽽且可以灵活地被᯿⽤和扩展。IOC 理论提出的观点⼤体是这样的:借助于“第三⽅”实现具有依赖关系的对象之间的解耦。如下图:

由于引进了中间位置的“第三⽅”,也就是 IOC 容器,使得 A、B、C、D 这 4 个对象没有了耦合关系,⻮轮之间的传动全部依靠“第三⽅”了,全部对象的控制权全部上缴给“第三⽅”IOC 容器,所以,IOC 容器成了整个系统的关键核⼼,它起到了⼀种类似“粘合剂”的作⽤,把系统中的所有对象粘合在⼀起发ഀ作⽤,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有⼈把 IOC 容器⽐喻成“粘合剂”的由来。  

        把上图中间的 IOC 容器拿掉,然后再来看看这套系统:

 

现在看到的画⾯,就是我们要实现整个系统所需要完成的全部内容。这时候,A、B、C、D 这 4 个对象之间已经没有了耦合关系,彼此毫⽆联系,这样的话,当你在实现 A 的时候,根本⽆须再去考虑 B、C 和 D了,对象之间的依赖关系已经降低到了最低程度。所以,如果真能实现 IOC 容器,对于系统开发⽽⾔,这将是⼀件多么美好的事情,参与开发的每⼀成员只要实现⾃⼰的类就可以了,跟别⼈没有任何关系!我们再来看看,控制反转(IOC)到底为什么要起这么个名字?我们来对⽐⼀下:

        软件系统在没有引⼊ IOC 容器之前,对象 A 依赖于对象 B,那么对象 A 在初始化或者运⾏到某⼀点的时候,⾃⼰必须主动去创建对象 B 或者使⽤已经创建的对象 B。⽆论是创建还是使⽤对象 B,控制权都在⾃⼰⼿上。软件系统在引⼊ IOC 容器之后,这种情形就完全改变了,由于 IOC 容器的加⼊,对象 A 与对象 B 之间失去了直接联系,所以,当对象 A 运⾏到需要对象 B 的时候,IOC 容器会主动创建⼀个对象 B 注⼊到对象 A 需要的地⽅。通过前后的对⽐,我们不难看出来:对象 A 获得依赖对象 B 的过程,由主动⾏为变为了被动⾏为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。

spring IOC 容器

一、节省内存 十万个用户在注册:

        new User(name, age, height, sex){........} ​

        工具类对象:

        new xxxObj() ​ 如果IOC容器中有这个 唯一的对象 xxxObj

        机器性能更好

2、松耦合: 面向抽象

Student 对象需要 vehicle对象

交通工具 Vehicle

car

bus

plane

bike

3、bean容器的创建

3.1.导包

3.1.1.导入spring核心依赖包

aop:jdk 语法、代理类

1.

 

2.

 

编写application-context.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="s" class="com.hqyj.model.Student">

    </bean>

</beans>

3.1.2编写语句

  1. package com.hqyj;
    ​
    import com.hqyj.model.Student;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;
    ​
    public class MyTest1 {
        public static void main(String[] args) {
            //应用程序上下文,创建容器
            //BeanFactory,ApplicationContext,AbstractApplicationContext是接口,不能new
            //方法一:
    //        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
            //方法二:
            BeanFactory context = new ClassPathXmlApplicationContext("application-context.xml");
            
            //方法三:
    //        ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
            //方法四:
    //        AbstractApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
    ​
    ​
            //写法一:返回值Object
    //        Student student = (Student) context.getBean("s");
            //写法二:获取类
            Student student = context.getBean(Student.class);
            student.work();
        }
    ​
    }
    ​

  2. 测试

3.2.容器bean对象创建的方式

1、直接调 bean类 的构造方法
2、调用静态工厂的静态方法创建bean对象
3、调用实例工厂的   方法创建bean对象

主要表现为:

3.2.1 方法一

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");

BeanFactory context = new ClassPathXmlApplicationContext("application-context.xml");
​
​
BeanFactory context = new FileSystemXmlApplicationContext("D:/hqyj/ssm/spring/studyIOC/src/application-context.xml");
​


ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");

AbstractApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
​

Resource rs=new FileSystemResource("D:\\Java\\chentaoWorkspace\\studySping-IOC\\src\\application-context.xml");

BeanFactory beanFactory=new XmlBeanFactory(rs);

beanFactory.getBean("student");

BeanFactory context = new XmlBeanFactory(new FileSystemResource("D:/hqyj/ssm/spring/studyIOC/src/application-context.xml"));
​

获取类写法:

 //写法一:返回值Object
        Student student1 = (Student) context.getBean("s");
        Student student2 = (Student) context.getBean("s");
        Student student3 = (Student) context.getBean("s");
//写法二:获取类
//      Student student1 = context.getBean(Student.class);
//      Student student2 = context.getBean(Student.class);
//      Student student3 = context.getBean(Student.class);

3.2.2 方法二

<!-- 静态工厂建立--> <bean name="fs" class="com.hqyj.model.StudentFactory" factory-method="pruduce"></bean>

 

3.2.3 方法三

调用实例工厂,创建bean对象

<!--    实例创建-->
    <bean id="maker" class="com.hqyj.model.StudentMaker" ></bean>
    <bean name="ms" factory-bean="maker" factory-method="make"></bean>
​
    <bean id="maker" class="com.hqyj.model.StudentMaker"></bean>
    <bean name="ms" factory-bean="maker" factory-method="make"></bean>

3.3.bean会创建多少个对象

3.3.1.singleton—1个 单例

创建一个对象

<bean id="s" scope="singleton" class="com.hqyj.model.Student">

3.3.2.prototype—多个 原型

创建多个对象

 <bean id="s" scope="prototype" class="com.hqyj.model.Student">

3.3.3.测试

public static void main(String[] args) {
        //应用程序上下文,创建容器
        //BeanFactory,ApplicationContext,AbstractApplicationContext是接口,不能new
        BeanFactory context = new ClassPathXmlApplicationContext("application-context.xml");
​
        //返回值Object
        Student student1 = (Student) context.getBean("s");
        Student student2 = (Student) context.getBean("s");
        Student student3 = (Student) context.getBean("s");
​
        System.out.println(student1);
        System.out.println(student2);
        System.out.println(student3);
​
        student1.work();
​
    }

3.4.bean 对象何时被创建

3.4.1.容器创建时创建

容器创建时就创建了,改为容器创建时不创建。设置为懒加载方式:

lazy-init="true"

 

3.4.2.获取的时候创建

在getBean()时创建,必然是懒加载的

 

3.5.bean对象的初始化和销毁

 

二、IOC-DI依赖注入—给属性设置值

DI: dependency Injection

1、 DI依赖注入—xml文件注入方式

1.1.简单数据注入

1.1.1 使用set方法进行注入,spting自己调用

 

1.1.2直接调用bean类的构造方法

<bean name="s"
      class="com.hqyj.model.Student">
</bean>

第三方可能提供一个student.class 文件

class StudentFactory{

    Student produce(){

        return new Studen t();

    }

}

1.1.3 引用别的bean对象

 

 

 

1.1.4.名称空间注入

namespace(XML文件)不常用

 <bean name="c1" class="com.hqyj.model.Car" p:brand="奔驰" p:color="黑色">
       
 </bean>

 

1.2.复杂数据注入

1.2.1.引入其他的bean的值

使用ref关键字——ref = "其他bean的name"

1.2.2 注入数组

<bean name="c1" class="com.hqyj.model.Car" >
        <property name="brand" value="宝马"></property>
        <property name="color" value="红色"></property>
</bean>
​
<bean name="s" class="com.hqyj.model.Student">
        <property name="id" value="1"></property>
        <property name="name" value="zs"></property>
        <property name="age" value="10"></property>
        <property name="car" ref="c1"></property>
        <property name="objs">
            <array>
                <value>香蕉</value>
                <value>西瓜</value>
                <value>葡萄</value>
                <value>草莓</value>
                <ref bean="c1"></ref>
            </array>
        </property>
</bean>

 

 

 

以上的方法不建议使用

 

通常要使用Arraay.tostring()方法对元素进行转化,转化后就显示的是具体的值。

1.2.3 注入集合—list

tostring()方法中不需要使用Array.tostring()方法,可以打印其元素:

 

<bean name="c1" class="com.hqyj.model.Car" >
        <property name="brand" value="宝马"></property>
        <property name="color" value="红色"></property>
</bean>
​
<bean name="s"  class="com.hqyj.model.Student">
        <property name="id" value="1"></property>
        <property name="name" value="zs"></property>
        <property name="age" value="10"></property>
        <property name="car" ref="c1"></property>
        <property name="objs">
            <array>
                <value>香蕉</value>
                <value>西瓜</value>
                <value>葡萄</value>
                <value>草莓</value>
                <ref bean="c1"></ref>
            </array>
        </property>
​
        <property name="likes">
            <list>
                <value>音乐</value>
                <value>跑步</value>
                <value>足球</value>
                <value>跳舞</value>
            </list>
        </property>
</bean>
   

 

 1.2.4.注入集合—set集合

 

 

 

1.2.5.注入集合—map映射

格式:

<property name="属性名">
 <map>
     <entry key="key" value="value"></entry>
 </map>
</property>

 

 

 

1.2.6.注入集合—Properties

会自动排序,与map相似

 

 

 

1.3. DI依赖注入——xm文件方式的代码

application-context.xml:
​
<bean name="c1" class="com.hqyj.model.Car" >
        <property name="brand" value="宝马"></property>
        <property name="color" value="红色"></property>
</bean>
​
<bean name="s"  class="com.hqyj.model.Student">
        <property name="id" value="1"></property>
        <property name="name" value="zs"></property>
        <property name="age" value="10"></property>
        <property name="car" ref="c1"></property>
        <property name="objs">
            <array>
                <value>香蕉</value>
                <value>西瓜</value>
                <value>葡萄</value>
                <value>草莓</value>
                <ref bean="c1"></ref>
            </array>
        </property>
​
        <property name="likes">
            <list>
                <value>音乐</value>
                <value>跑步</value>
                <value>足球</value>
                <value>跳舞</value>
            </list>
        </property>
​
        <property name="anm">
            <set>
                <value>猫</value>
                <value>狗</value>
                <value>青蛙</value>
                <value>乌龟</value>
            </set>
        </property>
​
        <property name="socres">
            <map>
                <entry key="数学" value="90"></entry>
                <entry key="英语" value="80"></entry>
                <entry key="体育" value="100"></entry>
                <entry key="美术" value="80"></entry>
​
            </map>
        </property>
​
        <property name="health">
            <props>
                <prop key="height">170厘米</prop>
                <prop key="weight">40千克</prop>
                <prop key="视力">5.2</prop>
                <prop key="血压">正常</prop>
​
            </props>
        </property>
  </bean>
​
​
​
实体类:Student:

​
import java.util.*;
​
public class Student {
​
    private int id;
    private String name;
    private int age;
    private Car car;
​
    private Object[] objs;  //数组
​
    private List likes;
​
    private Set anm;
​
    private Map socres;
​
    private Properties health;
​
    public Student(int id, String name, int age) {
        System.out.println("id,name,age被调用了");
        this.id = id;
        this.name = name;
        this.age = age;
    }
​
    public Student(String name,int id,  int age) {
        System.out.println("name,id,age被调用了");
        this.id = id;
        this.name = name;
        this.age = age;
    }
​
​
    public Properties getHealth() {
        return health;
    }
​
    public void setHealth(Properties health) {
        this.health = health;
    }
​
    public Map getSocres() {
        return socres;
    }
​
    public void setSocres(Map socres) {
        this.socres = socres;
    }
​
    public Set getAnm() {
        return anm;
    }
​
    public void setAnm(Set anm) {
        this.anm = anm;
    }
​
    public List getLikes() {
        return likes;
    }
​
    public void setLikes(List likes) {
        this.likes = likes;
    }
​
    public Object[] getObjs() {
        return objs;
    }
​
    public void setObjs(Object[] objs) {
        this.objs = objs;
    }
​
    public int getId() {
        return id;
    }
​
    public void setId(int id) {
        this.id = id;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public Car getCar() {
        return car;
    }
​
    public void setCar(Car car) {
        this.car = car;
    }
​
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", car=" + car +
                ", objs=" + Arrays.toString(objs) +
                ", likes=" + likes +
                ", anm=" + anm +
                ", socres=" + socres +
                ", health=" + health +
                '}';
    }
​
    public Student() {
        System.out.println("构造方法被调用");
    }
    public void work(){
        System.out.println("干活");
    }
​
    public void xxx(){
        System.out.println("初始化");
    }
    public void  yyy(){
        System.out.println("销毁");
    }
​
}
​
测试类:MyTest1:
​

import com.hqyj.model.Car;
import com.hqyj.model.Student;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
​
public class MyTest1 {
    public static void main(String[] args) {
        //应用程序上下文,创建容器
        //BeanFactory,ApplicationContext,AbstractApplicationContext是接口,不能new
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
​
context.getBean(Student.class);
        Student s = (Student) context.getBean("s");
        System.out.println(s);
    }
​
}

2、DI依赖注入—注解注入方式

2.1.@Component注解—修饰了一个类

2.1.1 组件

@Component:组件,以下属于其组件

@Controller 控制器

@Service 服务层

@Repository 持久层

以上三者都继承于@Component

@Component(value = "s")
@Controller(value = "s")     
@Service(value = "s")
@Repository(value = "s")

这就相当于在xml文件里面定义了一个<bean>组件

容器创建,查看其创建了没?

@Component
public class Student {
​
    private int id;
    private String name;
    private int age;
​
​
    public Student() {
        System.out.println("无参构造方法执行");
    }
}
<?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-4.0.xsd
​
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
​
    <!--annotation:注解的配置,使用注解需要使用这个关键字-->
    <context:annotation-config/>
    <context:component-scan base-package="com.hqyj.model"></context:component-scan>
​
​
</beans>
​
 

2.1.2 给属性赋值

package com.hqyj.model;
​
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
​
@Component(value = "s")
public class Student {
​
    @Value("1")
    private int id;
    @Value("zs")
    private String name = "i";
    @Value("10")
    private int age;
​
​
    public Student() {
        System.out.println("无参构造方法执行");
    }
    public String getName() {
        return name;
    }
​
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
​
public class MyTest1 {
    public static void main(String[] args) {
        //应用程序上下文,创建容器
        //BeanFactory,ApplicationContext,AbstractApplicationContext是接口,不能new
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
​
        //注解注入DI
​
        Student s = (Student) context.getBean("s");
       System.out.println(s);
​
    }
​
}
​

2.2.@Value注解—设置属性

package com.hqyj.model;
​
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
​
@Component()
public class Student {
​
    @Value("1")
    private int id;
    @Value("zs")
    private String name = "i";
    @Value("10")
    private int age;
​
​
    public Student() {
        System.out.println("无参构造方法执行");
    }
    public String getName() {
        return name;
    }
​
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
​
//注解注入DI
Student s = context.getBean(Student.class);
System.out.println(s);   //zs

 

2.3.@Resource注解—获得对象

不是spring框架下的注解,包不同,是属于其他的特有功能的注解

2.3.1 根据类型注入

 

 

package com.hqyj.model;
​
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
​
import javax.annotation.Resource;
import javax.annotation.Resources;
​
@Component(value = "s")
public class Student {
​
    @Value("1")
    private int id;
    @Value("zs")
    private String name = "i";
    @Value("10")
    private int age;
    @Resource()
    private Car car;
​
    public Student() {
        System.out.println("无参构造方法执行");
    }
​
}

2.3.2 name指定资源

注意:一一对应

 

2.4.Autowired—自动注入,根据类型

 

当容器中有两个一样的对象时,拿到哪一个对象呢?

2.4.1 bean声明两个car

 

报错,两个bean表示时,有冲突

2.4.2.当注解有一个car对象,bean有一个car对象

注解优先,起作用,不会报错

2.4.3.解决问题—配合使用

@Autowired 和  @Qualifier(value = "c2")  配合使用

 
@Qualifier(value = "c2")   //候选的合格者
    @Qualifier("c2")   //候选的合格者
功能相同:

 

2.5.java Configuration

2.5.1 容器创建——放入容器

创建容器的时候就直接加载这个类MyConfig.class

@Configutation //相当于一个xml文件

Class MyConfig{

@Bean

Student fun(){

return new Student("","");

}

}

 

 

2.5.2 从容器中取

 

@Configuration
public class MyConfig {
    @Bean
    Student fun(Car car){    //Car从容器中拿取
//        Car car = new Car("梅赛德斯","蓝色");
        return new Student(1,"小花",20,car);
    }
​
    @Bean      //放在容器中
    Car car(){
        return  new Car("奎蟒","蓝黑");
    }
}

2.6、松耦合

2.6.1 vehice对象

Student 需要 vehice对象?

交通工具vehicle:

car

bus

plane

bike

interface vehicle(){

go(); //抽象

}

 

 

 

 

三.(重点)IOC-DI依赖注入- 面试题

IOC / DI: IOC不是一种技术,主要是一种设计思想。在项目中,传统创建方法是new一个对象,但这样会使得对象间的耦合度增加。 Spring将所有的对象都登机在Spring容器中,并且在系统运行适当的时候通过DI注入到对象当中。 控制反转就是将对象的注册从对象中创建 反转为 Spring统一注册。

四、spring AOP

改变对象原有的行为,但又无法改变源代码

aop:面向切面编程:与过滤器filter相似

1、Aop概念

连接点Joinpoint可以进行切入开发的点。如一个方法、一个代码块、一个try块(AspectJ中原本规定可以有这些)。但是spring**只支持把方法作为连接点**。
切入点Pointcut已经被选定作为切面开发的点。
通知/增强Advice对切入点可以做的各种事情。如前置通知before()、后置通知after()、环绕通知around()、异常通知exception()等。 java程序中,往往把这些通知放入到一个额外的类中书写。
目标对象Target(略) 目标对象是被切入的对象。但是由于类是对象的模板,是由类new()出来的,所以目标当然就是一个个的类了。
代理对象Proxy(略)由于本章节,是spring自行内在完成代理对象的所有工作,我们只管用就好,所以不必专门学习。如果要知道原理请学习动态代理。
切面Aspect切入点被融入通知后,产生的整体效应。(不必强行理解这个词)

2、面向切面编程

2.1. 定义——画图方式理解

AsprctJ:定义了非常丰富的面向切面,各种切法

spring:Interceptor 拦截器

开门 person.openDoor()---自动--->door.open()

进入 person.enter();

关门 person.close()---自动----->door.close()

 

2.2. 步骤

2.2.1.导包

*aspectj*下载的地方:

AspectJ Downloads | The Eclipse Foundation

aspectjweaver下载的地方:

http://mvnrepository.com/artifact/org.aspectj/aspectjweaver/1.8.7

我用的是其中这两个包

aspectj-1.8.13.jar aspectjweaver-1.8.7.jar
AspectJ的高版本可能一个包就可以了

当然spring的aop包也得有,我用的是

spring-aop-4.3.4.RELEASE.jar

spring-aspects-4.3.4.RELEASE.jar

 

2.2.2.编写代码

1.Person.java

package com.hqyj.model;
​
public class Person {
​
    public void enter(){
        System.out.println("enter()方法被调用...");
    }
}

2.DoorAdvice.java

package com.hqyj.model;
​
public class DoorAdvice {
    void open(){
        System.out.println("开门");
    }
    void close(){
        System.out.println("关门");
    }
}

3.Application-context.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop.xsd
​
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
​
    <bean class="com.hqyj.model.Person"></bean>
    <bean id="doorAdvice" class="com.hqyj.model.DoorAdvice"></bean>
​
<!-- 做切面编程的配置-->
    <aop:config>
        <aop:pointcut id="enter" expression="execution(public void com.hqyj.model.Person.enter())"/>
        <aop:aspect ref="doorAdvice">
            <aop:before method="open"  pointcut-ref="enter"></aop:before>
            <aop:after method="close" pointcut-ref="enter"></aop:after>
        </aop:aspect>
    </aop:config>
</beans>

4.MyTestDoor.java

package com.hqyj;
​
import com.hqyj.model.Person;
import org.springframework.context.support.ClassPathXmlApplicationContext;
​
public class MyTestDoor {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
        Person person = context.getBean(Person.class);
​
        person.enter();
​
    }
}

结果

 

2.2.3.对比结果

 

 

3.面向切面编程的方式

3.1.配置文件xml方式

3.1.1 解释

Before() 前置通知

After() 后置通知

After-returning() //后置通知,出现异常不调用

After_throwing() /后置通知,发生了异常才执行,否则不执行

Around() 环绕

特殊功能:有过滤性质,会过滤掉目标方法

3.1.2 代码

package com.hqyj.model;
​
import org.aspectj.lang.ProceedingJoinPoint;
​
public class DoorAdvice {
    void before(){  //前置通知
        System.out.println("before()");
    }
    void after(){     //后置通知
        System.out.println("after()");
    }
​
    void after_returning(){   //异常通知,出现异常不调用
        System.out.println("after_returning()");
    }
​
    void after_throwing(){    //发生了异常才执行,否则不执行
        System.out.println("发生了异常");
    }
​
    Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知1");   //前置环绕
        Object proceed = point.proceed();   //调用目标方法
        System.out.println("环绕通知2");   //后置环绕
        return proceed;   //返回去
​
    }
}
​
<!-- 做切面编程的配置-->
 <aop:config>
        <aop:pointcut id="enter" expression="execution(public void com.hqyj.model.Person.enter())"/>
        <aop:aspect ref="doorAdvice">
            <aop:before method="before"  pointcut-ref="enter"></aop:before>
​
            <aop:after method="after" pointcut-ref="enter"></aop:after>
            <aop:after-returning method="after_returning" pointcut-ref="enter"></aop:after-returning>
            <aop:after-throwing method="after_throwing" pointcut-ref="enter"></aop:after-throwing>
            <aop:around method="around" pointcut-ref="enter" ></aop:around>
​
​
       </aop:aspect>
 </aop:config>

3.2.使用注解的方式

xml中  声明了通知类和被切入的person
    <aop:config>     
        通知类 door
        被切入的 person 
注解:     
    @Aspect:放在通知类的上面   
    Pointcut:切入点

3.2.1.加入aop自动代理

<!--    开启aop自动代理:注解-->
    <aop:aspectj-autoproxy/>

3.2.2.代码

DoorAdvice.java:

​
package com.hqyj.model;
​
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
​
@Aspect
 class DoorAdvice {
    @Pointcut("execution(public void com.hqyj.model.Person.enter())")
    void point(){   //代表切点,空方法
    }
​
    @Before("DoorAdvice.point()")
    void before(){  //开始方法
        System.out.println("before()");
    }
    @After("DoorAdvice.point()")
    void after(){     //结束方法
        System.out.println("after()");
    }
​
    @AfterReturning("DoorAdvice.point()")
    void after_returning(){   //异常
        System.out.println("after_returning()");
    }
​
    @AfterThrowing("DoorAdvice.point()")
    void after_throwing(){    //发生了异常才执行,否则不执行
        System.out.println("发生了异常");
    }
​
    @Around("DoorAdvice.point()")
    Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知1");   //前环绕
        Object proceed = point.proceed();   //调用目标方法
        System.out.println("环绕通知2");   //后环绕
        return proceed;   //返回去
​
    }
}
​
Person.java
​
package com.hqyj.model;
​
public class Person {
​
    public void enter(){
​
        System.out.println("enter()方法被调用...");
    }
}
​

2.3.注解执行的顺序

 

4、面试题

友情提示:

面向切面编程,面试要问哈,AOP是在OOP基础之上的一种更高级的设计思想。 java这个方向,IOC/DI/、AOP不问的话没有什么问的了,重要的框架都是基于这些思想设计的

1.around和过滤器filter的区别

        只有@Around方法能够达到“拦截住而不放行”的效果。

        @Around会强制要求所修饰的方法含有参数(ProceedingJoinPoint point),因为这个参数就是用于控制是否放行的。

        point.proceed()代表放行,有点类似Servlet规范中的Filter的Chain.doFilter(req,resp)。下表来对比一下写法

@Around@Around("TransactionAdvice.pointCut()")*public* Object around(ProceedingJoinPoint point) *throws* Throwable { System.*out***.println("环绕 前通知被执行"); Object proceed = point.proceed();//放行,实际是它可以调用目标方法 System.*out***.println("环绕 后通知被执行"); *return* proceed;}
过滤器Filter*public* *class* AllFilter *implements* Filter{ @Override*public* *void* doFilter(ServletRequest request, ServletResponse response, FilterChain chain) *throws* IOException, ServletException { System.*out***.println("时间1=" + System.currentTimeMillis()); chain.doFilter(request, response); //放行 将请求传递下去 System.*out***.println("时间2=" + System.currentTimeMillis());}}

五、事务

一般指的是数据库操作

也指的是不可分割的操作(要么都完成,要么都不完成)

一条sql语句 是不是一个事务?

是一个事务。单条sql相当于自动提交了。

1.原生—事务步骤

开启事务(关闭自动提交):

connection.set()
connection.begin.Transaction()
conn.setAutoCommit(false);
  1. 操作1 sql1

  2. 操作2 sql2

  3. 操作3 sql3

  4. 操作4 sql4

提交事务:submit()

2.代码

package com.hqyj;
​
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
​
public class MyTest1 {
​
    private static final String DIRVER = "com.mysql.jdbc.Driver";
    private static final String URL = "jdbc:mysql://localhost:3306/shop";
    private static final String USER = "root";
    private static final String PASSWORD = "123456";
​
    public static void main(String[] args)  throws Exception{
        Class.forName(DIRVER);
        Connection conn = DriverManager.getConnection(URL,USER,PASSWORD);
        conn.setAutoCommit(false);   //关闭自动提交
        Statement stmt = conn.createStatement();
​
        try {
            int  num1= stmt.executeUpdate("update book set  price = price-100 where id = 1");
            System.out.println("num1=" + num1);
​
            int  a = 5/0; //异常
​
            int  num2= stmt.executeUpdate("update book set  price = price+100 where id = 2");
            System.out.println("num2=" + num2);
​
            conn.commit();    //提交事务
        } catch (Exception throwables) {
            conn.rollback();   //事务发生异常,数据要回滚
            throwables.printStackTrace();
            System.out.println("发生了运行时异常");
        } finally {
            stmt.close();
            conn.close();
        }
    }
}
​

3.代码繁琐,化简

解决办法,切入事务,利用AOP

需要用到c3p0数据源来用,需要写成一个bean。

切入点:只支持方法

3.1导包

 

3.2代码

package com.hqyj.Teansaction;
​
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
​
public class MyTest2 {
​
    public static void main(String[] args) throws Exception {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/shop");
        dataSource.setUser("root");
        dataSource.setPassword("123456");
​
        //spring有一个轻量级的数据 访问框架jdbc Template
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        int num1 = jdbcTemplate.update("Update book  set price  = price-100  where id=1");
        int num2 = jdbcTemplate.update("Update book  set price  = price+100  where id=2");
​
        System.out.println("num1="+num1);
        System.out.println("num2="+num2);
    }
}

4、切入事务,xml文件方式

4.1新建一个bean对象—Account.java

application-context.xml:
​
<bean id="dataSource"  class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/shop?useSSL=false&amp;Timezone=GMT"></property>
            <property name="user" value="root"></property>
            <property name="password" value="123456"></property>
        </bean>
​
        <bean class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    <context:component-scan base-package="com.hqyj.model"></context:component-scan>
Account类:
    
package com.hqyj.model;
​
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
​
import javax.sql.DataSource;
​
@Component
public class Account {
@Autowired
    DataSource dataSource;
@Autowired
    JdbcTemplate jdbcTemplate;
​
    //转账
    public void teansfer() throws Exception {
        System.out.println(dataSource);
​
        //spring有一个轻量级的数据 访问框架jdbc Template
        int num1 = jdbcTemplate.update("Update book  set price  = price-100  where id=1");
        int num2 = jdbcTemplate.update("Update book  set price  = price+100  where id=2");
​
        System.out.println("num1="+num1);
        System.out.println("num2="+num2);
    }
}
​
测试类:
    
package com.hqyj.Teansaction;
​
import com.hqyj.model.Account;
import org.springframework.context.support.ClassPathXmlApplicationContext;
​
public class MyTest2 {
​
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Application-context.xml");
        Account account = context.getBean(Account.class);
        account.teansfer();
    }
}
​

4.2 通知配置

 

4.3 事务的传递性

read-only = "true"

性能1:读
性能2:写
​
1.读 2.可以改
        1000  ,   1500          
1.改 2.不能改
        1000  ,   500

​
配置文件:
​
<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
​
​
​
<!--    通知管理-->
<!--        <bean class="com.hqyj.model.AccountService"></bean>-->
​
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="add**" propagation="REQUIRED" />
                <tx:method name="delete**" propagation="REQUIRED" />
                <tx:method name="transfer**" propagation="REQUIRED"/>
​
                <tx:method name="select**" propagation="SUPPORTS" read-only="true"/>
            </tx:attributes>
​
        </tx:advice>
        <aop:config>
            <aop:pointcut id="serviceMethod" expression="execution(* com.hqyj.service..*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"></aop:advisor>
        </aop:config>
<!--    事务管理器-->
        <bean  id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
​
        <bean id="dataSource"  class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/shop?useSSL=false&amp;Timezone=GMT"></property>
            <property name="user" value="root"></property>
            <property name="password" value="123456"></property>
        </bean>
​
        <bean class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    <context:component-scan base-package="com.hqyj.service"></context:component-scan>
​
</beans>
​
AccountService.java
​

package com.hqyj.service;
​
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
​
import javax.sql.DataSource;
​
@Component
public class AccountService {
@Autowired()
@Qualifier("dataSource")
    DataSource dataSource;
@Autowired
    JdbcTemplate jdbcTemplate;
​
    //转账
    public void teansfer() throws Exception {
        System.out.println(dataSource);
​
        //spring有一个轻量级的数据 访问框架jdbc Template
        int num1 = jdbcTemplate.update("Update book  set price  = price-100  where id=1");
//        int i = 5/0;
        int num2 = jdbcTemplate.update("Update book  set price  = price+100  where id=2");
​
        System.out.println("num1="+num1);
        System.out.println("num2="+num2);
    }
}
​
测试类:
​

package com.hqyj.Teansaction;
​
import com.hqyj.service.AccountService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
​
public class MyTest2 {
​
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Application-context.xml");
​
        AccountService account = context.getBean(AccountService.class);
​
        account.teansfer();
    }
}

 

#####

5.切入,注解方式

 

@Transactional标在方法上,如果每一个方法都是一样的直接标在类上
package com.hqyj.service;
​
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
​
import javax.sql.DataSource;
​
@Component
public class AccountService {
@Autowired()
    DataSource dataSource;
@Autowired
    JdbcTemplate jdbcTemplate;
​
    //转账
    @Transactional(propagation = Propagation.REQUIRED,readOnly = false)
    public void teansfer() throws Exception {
        System.out.println(dataSource);
​
        //spring有一个轻量级的数据 访问框架jdbc Template
        int num1 = jdbcTemplate.update("Update book  set price  = price-100  where id=1");
        int i = 5/0;
        int num2 = jdbcTemplate.update("Update book  set price  = price+100  where id=2");
​
        System.out.println("num1="+num1);
        System.out.println("num2="+num2);
    }
}
​


web开发:servlet + jsp (html,css,js) ajax

六、建立web项目

1.MVC

1.1.MVC思想

C : controller 控制器 接收用户的请求(Tomcat)

M: model 多个模型 数据库

V : view 视图 用户看到的内容(jsp)

@Reposiary

@controller

@service

@Repository


1.2.java项目结构

1.2.1一般的Java项目:idea支持多模块的

src: 源代码

out: (bin) 编译后的字节码文件

1.2.2web项目

web项目要放到tomcat中执行

maven:

src: 源代码

web: 里面的东西会发布到tomcat中

WEB-INF

class: 编译后的字节码文件

lib: jar包(spring...)

web.xml: 描述了整个项目

METE-INF

任意文件: jsp文件、HTML文件、css文件、js文件

2、建立web项目

2.1.idea建web项目

创建web项目

 

部署tomcat服务器

 

 

 

 

解释:

Deployment:部署

war:添加需要运行的项目,war包----->war exploded

Artifacts:

一个目录

一个jar包

一个war包

apk文件

Application context : 访问项目的路径 http://localhost:8080/项目名/index.jsp

部署到tomcat上,以什么名字访问

2.2.idea建maven项目

3.控制器类

3.1.接口分析

Servlet1 /abc

Servlet2 z

Servlet3 /mn

Servlet4

ServletN

安全性??? 单入口

    单个Servlet
​
                case  '/aaa'
                调用      功能1
​
                case  'b'
                调用      功能2
​
                case  '/ccc'
                调用·     功能3
​
                case  '/ddd'
                调用      功能4
​
                case  'e'
                调用      功能5

3.2.控制器——url路径

url-------方法

发送过来的请求都被DispatcherServlet接收了,DispatcherServlet可以去查找控制器,需要去指定对应的文件

@Controller
public class BookController {
​
    @RequestMapping("/abc")
    String work(){
        System.out.println("work----干活");
        return "/index.jsp";
    }
}
​
<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
​
       xsi:schemaLocation="
​
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.3.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
​
<!--    扫描主键,控制器是主键的一种-->
    <context:component-scan base-package="com.hqyj.controller"/>
</beans>
<?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">
​
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
​
<!--   单入口-->
    <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:config/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>

使用注解时,如果不起作用

<!--用于注解起作用,注解驱动-->
    <mvc:annotation-driven/>

3.3.静态资源

3.3.1常见的静态资源

图片

html文件

Css文件

用来spring框架后静态资源直接访问时访问不了的,原因:

DispatcheServlet接收所有的请求,/,都走RequestMapping

所以走RequestMapping指定的文件才能访问,唯一特殊的时index.jsp文件,因为时单入口y.

3.3.2 静态资源访问解决方式

法一:

使用给mvc:resource,对静态资源进行配置,不被deispatcher按默认方式处理。可以直接访问

<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/img/**" location="/img/"/>
<mvc:resources mapping="/html/**" location="/html/"/>
<mvc:resources mapping="/**" location="/"/>
​
<!--用于注解起作用,注解驱动-->
<mvc:annotation-driven/>

法二:

静态资源同一放在static目录下

 
<mvc:resources mapping="/static/**" location="/static/"/>
<mvc:resources mapping="/**" location="/"/>
​
<!--用于注解起作用,注解驱动-->
<mvc:annotation-driven/>

 

 

3.4.视图解析器

3.4.1方式1 直接写

因为直接访问视图文件会导致报错或者不完整,所有要隐藏视图文件

将视图文件藏起来——藏在WEB-INF,黑客访问的话,就不会访问到。

 

package com.hqyj.controller;
​
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
​
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.RequestWrapper;
​
@Controller
public class BookController {
​
    @RequestMapping("/abc")
    String work(HttpServletRequest request){
        System.out.println("work----干活");
        String name = "安其拉";
        request.setAttribute("name",name);
        return "/WEB-INF/abc.jsp";    //那视图文件
    }
}
​

3.4.2 简化管理

然后为了方便管理,在WEB-INF下建立一个jsp文件夹,里面再建立一个用来表示时哪一个项目的文件,此项目是Book的。book里面存放jsp文件,记得要改动return的路径哟

 

 

3.4.3 设置视图解析器

return "/WEB-INF/jsp/book/abc.jsp"; 
太复杂,有公共的部分,所以运用视图解析器更方便

设置视图解析器前缀和后缀

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"></property>
    <property name="suffix" value=".jsp"></property>
</bean>

 

 

 

3.5.缓解控制冲突

因为如果路径就设置为/add的话,有很多个添加操作,就会冲突,所以需要在控制器上使用RequestMapping("/book")

 

 

@Controller
@RequestMapping("/book")
public class BookController {
​
    @RequestMapping("/work")
    String work(HttpServletRequest request){
        System.out.println("work----干活");
        String name = "安其拉";
        request.setAttribute("name",name);
        return "book/abc";    //那视图文件
    }
​
    @RequestMapping("/add")
    String add(){
        return "book/add";
    }
}

3.6.设置addAttribute属性

3.6.1 request.setAttribute

 

3.6.2 model.addAttribute

 

3.6.3当两个都存在时,model起作用

 

 

package com.hqyj.controller;
​
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
​
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.RequestWrapper;
​
@Controller
@RequestMapping("/book")
public class BookController {
​
    @RequestMapping("/work")
    String work(HttpServletRequest request, Model model){
        System.out.println("work----干活");
        String name = "潘江";
        model.addAttribute("name","tom");
        request.setAttribute("name",name);
        return "book/abc";    //那视图文件
    }
​
    @RequestMapping("/add")
    String add(){
        return "book/add";
    }
}
​

3.7.控制器类

3.7.1控制器类型

 

3.7.2 控制器的返回值

http 状态码

200 运行成功,正常

301,302,303 资源转移了,重定向

404 资源不存在

500 服务器运行出错

405 资源不存在

3.7.2.1.String

返回的String类型 ,其中只要含有redirect,就是一个重定向

重定向:分为相对定位和绝对定位,详看7.3重定向

3.7.2.2.ModelAndersonView

new ModelAndView(页面的地址,传递的数据名,传递的数据)

 @RequestMapping("sleep")
    ModelAndView sleep(Model model){
        
        String nick = "张三";
        return new ModelAndView("book/sleep","nick",nick);     //拿页面
    }

 

也可以传递对象Book

@RequestMapping("/sleep")
ModelAndView sleep(Model model){
​
    Book book = new Book(1,"成都的街头","爱尔华斯",200);
    return new ModelAndView("book/sleep","book",book);     //拿页面
}
package com.hqyj.model;
​
public class Book {
    private int id;
    private String name;
    private String author;
    private double price;
​
    public Book() {
    }
​
    public Book(int id, String name, String author, double price) {
        this.id = id;
        this.name = name;
        this.author = author;
        this.price = price;
    }
​
    public int getId() {
        return id;
    }
​
    public void setId(int id) {
        this.id = id;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public String getAuthor() {
        return author;
    }
​
    public void setAuthor(String author) {
        this.author = author;
    }
​
    public double getPrice() {
        return price;
    }
​
    public void setPrice(double price) {
        this.price = price;
    }
​
    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                '}';
    }
}
​
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    sleep----ModelAndView  <br>
    ${book.id}
    ${book.name}
    ${book.author}
    ${book.price}
​
</body>
</html>

 

3.7.2.3.Object对象

Object对象默认拿取jsp界面

object对象添加@ResponseBody表示不拿jsp页面,纯数据,可以用js插入到html页面

浏览器就直接看到了对象转变成的字符串

Convertor:如 Gson,Jackson,FastJson

@RequestMapping("/data")
    @ResponseBody      //不拿页面
    Object data(){
        //拿页面
        System.out.println("data-------调用");
         return new Book(2,"物语","尼科尔",200);
​
    }

book对象转换成字符串:

1.tostring()

2.json

 @RequestMapping("/data")
    @ResponseBody      //不拿页面
    Object data(){
        //拿页面
        System.out.println("data-------调用");
        Book book = new Book(2, "物语", "尼科尔", 200);
        System.out.println(book);
        return book;
    }

######

3.7.3 重定向

涉及面试题:

重定向:服务器叫浏览器去访问另外一个url

response.sendRedirect("另一个url");

3.7.3.1.相对路径

相对于浏览器地址栏

 

package com.hqyj.controller;
​
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
​
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.ws.RequestWrapper;
​
@Controller
@RequestMapping("/book")
public class BookController {
​
    @RequestMapping("/work")
    String work(HttpServletRequest request, Model model, HttpServletResponse response, HttpSession session){
        System.out.println("work----干活");
        String name = "潘江";
        model.addAttribute("name",name);
        return "redirect:add";     //重定向
           //相对路径,相对于浏览器当前路径的地址栏
    }
​
    @RequestMapping("/add")
    String add(){
        System.out.println("add----访问");
        return "book/add";
    }
}

3.7.3.2 根路径

根路径方式,spring项目会帮我们加上项目虚拟路径

从当前路径来看

根路径为:

http://localhost:8080/studyWebproject_war_exploded/book/work

根路径重定向为: 抹掉项目名

http://localhost:8080/book/add

 

4. conbertor转换器

conbertor 转换器:jackson(三个jar,版本配对)、gson谷歌(一个jar包)、fasthson阿里

有接口,spring会自动再jar中去寻找实现类

这里使用了gson谷歌

 

    @RequestMapping("/data")
    @ResponseBody      //不拿页面
    Book data(){
        //拿页面
        System.out.println("data-------调用");
        Book book = new Book(2, "物语", "尼科尔", 200);
        System.out.println(book);
        return book;
    }

 

5.全分离开发方式

5.1.不分离开发方式

 

转变为:

5.2.全分离开发方式

 

6、日志

6.1.动态查找机制

mybatis:log4j

不好用,不会输出提示,原因是

spring:

一旦有log4j的jar包,spring就用的是log4j的jar包,但是现在找不到log4j的配置文件,所以控制台没有输出

解决方法:

6.2.spring使用common-logging

1.强制让spring使用common-logging 加两个文件

 

 

 

6.3.log4j

2.把log4j的配置文件拷贝进来(不建议用这个,不好排错)

拷贝一个log4j.properties拷贝进来

 

 

 

6.4.logback

spring5使用logback日志系统

7、分层

A------------>B(B封装分层为B和C)

A------------>B------------>C

A------------>B------------>C------------>D

这种情况容易出现可读性的问题:可读性不能太深

7.1.三层结构

A------------>B------------>C (可读性稍微要好一点,可读性客观)

Controller层-------->service层---------->mapper/Dao

Controller:控制层

service层: 业务逻辑层

需要接口实现

为了松耦合(vehicle,car)

mapper/Dao: 数据访问层

例如:

x-----调用------> T

y-----调用------> T

z-----调用------> T

如果将来T发生改变,x\y\z也会发生变化,改动就发生了变化,需要维护

 

 

 发生了乱码

7.2.多层结构

 

7.3.中文乱码问题

 

 

 

 

解决方法:

7.3.1.解决 POST 请求乱码问题:

(1)在 web.xml 中配置⼀个 CharacterEncodingFilter 过滤器,设置成 utf-8;

   
 <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>endcoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
​
<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

(2)再方法上放加上生成器和字符集,json格式,只能单个设置

@RequestMapping(value = "/a2",produces = "application/json;charset=utf-8")
    @ResponseBody
    String a2(){   //返回字符串,默认,消息转换器MeessageConvertor
        return "a2字符串";
    }

(3)使用mvc:message-converters

    <!-- SpringMVC注解驱动 -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/plain;charset=utf-8</value>
                        <value>text/html;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

7.3.2 GET 请求中⽂参数出现乱码解决⽅法有两个:

(1)修改 tomcat 配置⽂件添加编码与⼯程编码⼀致,如下:

<ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1"
redirectPort

2)对参数进⾏重新编码:

String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值