基础概念、项目结构和配置




1 – 实现简单三层架构单体应用(登入)

项目架构

注意

不使用新建项目,而采用单独新建文件夹架构项目的方式.

  1. Mark Directory src/main/java as Sources Root
  2. Mark Directory src/main/resources as Resources Root
  3. 将webapp设置为web目录

宏观流程

即不深入运行过程,仅从简单逻辑层面来判断.

xml配置以及基本框架

对于servlet的配置

WEB-INF下web.xml -> 将Controller映射到某一个Uri上

pom.xml

Maven配置依赖项

spring-context.xml

控制反转,将bean交给SpringIoC容器

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">
</web-app>

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.funtl</groupId>
    <artifactId>spring-demo</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.17.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>
    </dependencies>
</project>

spring-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 http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

代码

https://github.com/834930269/Spring_demo/tree/master/demo/login-demo


2 – 理解依赖注入和控制反转

项目结构

Tip: 如果文件名显示,而没有任何错误,大抵是开了版本控制,比如Git.在.idea的vcs.xml文件中将git删掉即可

依赖注入

背景

DI: Dependency injection

From Spring实战(第四版) P5

背景: 任何一个实际意义的应用,都会由两个或者更多的类组成.这些类相互协作形成应用.

这样子导致的直接结果是耦合度过高.

DI: 为了解决这一问题,Spring提供了依赖注入这一解决方案.

什么叫依赖注入?

举个栗子:

我们想要实现骑士探险这一类,可以自由的为骑士选择探险任务.

Knight.java

package DI;

public interface Knights {
    public void embarkOnQuest();
}

探险任务

package DI;

public class RescueDamselQuest {
    public void embark(){
        System.out.println("已接收");
    }
}

骑士接受任务

package DI;

public class DamselRescuingKnight implements Knights {
    private RescueDamselQuest quest;

    public DamselRescuingKnight() {
        quest=new RescueDamselQuest();
    }

    @Override
    public void embarkOnQuest() {
        quest.embark();
    }
}

我们会发现这样写代码使得探险和骑士的耦合度达到了密不可分的地步,写一个探险就要新建一个结合类.

改进措施,提出了依赖注入:

构造器注入

这个比较简单,即将探险类作为构造参数传递进来,但这样依然没有达到代码层面的解耦.

public class DamselRescuingKnight implements Knights {
    private RescueDamselQuest quest;

    public DamselRescuingKnight(Quest quest) {
        this.quest=quest;
    }

    @Override
    public void embarkOnQuest() {
        quest.embark();
    }
}

mock注入

和Spring的依赖注入很像.

Spring的依赖注入

接上本小节一开始的那张项目结构图.

Spring是这样做的.你将需要解耦的类交给Spring的容器去保管,需要使用时直接从Spring中取出来即可,而不需要有任何new出来的类.

比如Service,Bean等,都可以交给Spring保管.

举个栗子:

UserService.java(接口)

package com.funtl.spring.service;

public interface UserService {
    public void sayhi();
}

UserServiceImpl.java

package com.funtl.spring.service.impl;

import com.funtl.spring.service.UserService;

public class UserServiceImpl implements UserService {
    public void sayhi() {
        System.out.println("hello");
    }
}

resources/spring-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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userService" class="com.funtl.spring.service.impl.UserServiceImpl" />
</beans>

OK,前序工作做完了,我们在运行时就已经将这个类托管给了Spring容器.
那么我们该如何取出来呢?

MyTest.java

package com.funtl.spring;

import com.funtl.spring.service.UserService;
import com.funtl.spring.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args){
        //获取Spring容器
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-context.xml");

        //从Spring容器中获取对象
        UserService userService= (UserService) applicationContext.getBean("userService");
        userService.sayhi();

    }
}

我们可以看到,上面的代码并没有new一个Service,而是从Spring上下文中取出了userService这个对象.
仔细想想,这样是不是就类似于调用静态的工具类那样轻松了呢?

依赖注入的魅力就在于此.

而将类的加载交给容器时,这个容器的模式就叫做 IoC(控制反转)

最终架构

One Reply to “基础概念、项目结构和配置”

发表评论