SSM中的MVC结构分析,SSM框架的响应流程

今天头一次配置成功一个SSM框架,兴奋之余,还应该从使用的角度,将整个ssm配置的方法,配置的原因,认真的分析一下。在结束了对SSM框架简单的分析之后,就要开始回归基础,全面的认真复习。所以这个文档,要尽量的完整,目标就是,这个文档是是对SSM框架的学习,也是一个将来复习的资料。

  这个版本中的代码貌似无法复制,我将可以也可复制版也发布了,在我的博客中,但是没有很好的样式。

1 resources 配置文件

1.1 配置文件简介

这个部分用来解读在resources文件夹下的配置信息。这一部分是整个ssm框架中,最难的一部分,也是最复杂的一部分。在配置这个部分的时候,尽管是不停的肤质粘贴,偶尔改一改路径。但是这样的一个 过程要比写业务逻辑代码麻烦的多。

1.1.1 jdbc.properties

这个文件是用来保存和数据库连击的相关的信息,比如JDBC驱动器、数据库户名、数据库密码等等,和数据库相关的静态信息,都会以KV的形式,保存在这个文件中。这样在需要对数据库的信息进行改变时,只需要打开这个文件,就可以对数据库的配置进行改变。与之前传统数据库连接方式相比,在修改时,不用改变多处的信息。

1.1.2 spring-mvc.xml

和名字显示的显示的一样,这是一个对MVC配置的一个文件。简单来讲有下面的几点功能:

1 设定用来存放controller的包的位置。

2 以文件前缀、后缀的方式,设定存放JSP文件的路径。

我对这个文件的理解为,从controller获取执行哪一个文件的信息,在将这个信息,通过前缀和后缀的包装,传递给下一级。

1.1.3 spring-mybatis.xml

这个配置也常常叫做:applicationContext.xml,但是其实是一个东西,都是用来配置mybatis。

1 将标注Spring注解的类自动转化成Bean,并且完成Bean的注入。

2 配置数据库相关的资源。

3 配置数据库的sessionFactory

4 配置需要被扫描的用来存放DAO接口的接口包。

5 配置事务管理器。

1.1.4 UserDAO.xml

mapper.xml稍微好理解一些。就是使用DAO接口的全限定地址,和DAO中的操作数据库的sql方法,封装起来,那么调用DAO接口的某个方法的时候,就可以使用mapper.xml中封装的sql语句操作数据库。

通常在这个文件也叫做mapper.xml文件.

1.1.5 web.xml

53

1

<?xml version="1.0" encoding="UTF-8"?>

2

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"

3

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4

         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

5

         version="3.1">

6

?

7

    <display-name>SSM</display-name>

8

    <description>SSM_test</description>

9

?

10

    <!-- 编码过滤器 -->

11

    <filter>

12

        <filter-name>encodingFilter</filter-name>

13

        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

14

        <init-param>

15

            <param-name>encoding</param-name>

16

            <param-value>UTF-8</param-value>

17

        </init-param>

18

    </filter>

19

?

20

    <filter-mapping>

21

        <filter-name>encodingFilter</filter-name>

22

        <url-pattern>/*</url-pattern>

23

    </filter-mapping>

24

?

25

    <!-- 配置前端控制器Spring MVC DispatcherServlet -->

26

    <servlet>

27

        <servlet-name>SpringMVC</servlet-name>

28

        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

29

        <!-- 配置两个文件 -->

30

        <init-param>

31

            <param-name>contextConfigLocation</param-name>

32

            <param-value>classpath:spring-*.xml</param-value>

33

        </init-param>

34

?

35

        <load-on-startup>1</load-on-startup>

36

        <async-supported>true</async-supported>

37

    </servlet>

38

?

39

?

40

    <!--将所有的请求使用上面配置的 DispatcherServlet 分发器分发-->

41

    <servlet-mapping>

42

        <servlet-name>SpringMVC</servlet-name>

43

        <!-- 匹配所有请求,此处也可以配置成 *.do 形式 -->

44

        <url-pattern>/</url-pattern>

45

    </servlet-mapping>

46

?

47

?

48

    <welcome-file-list>

49

        <welcome-file>index.html</welcome-file>

50

    </welcome-file-list>

51

?

52

</web-app>

53

?

1.1.6 其他

Logback是一个关于log日志的配置文件,并没有使用sql文件夹。还有就是pom.xml文件,看起来很多,其实也就是添加了几个依赖罢了。

175

1

<?xml version="1.0" encoding="UTF-8"?>

2

?

3

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4

  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

5

  <modelVersion>4.0.0</modelVersion>

6

?

7

  <groupId>com.xzj</groupId>

8

  <artifactId>ssmSecondTry</artifactId>

9

  <version>1.0-SNAPSHOT</version>

10

  <packaging>war</packaging>

11

?

12

  <name>ssmSecondTry Maven Webapp</name>

13

  <!-- FIXME change it to the project‘s website -->

14

  <url>http://www.example.com</url>

15

?

16

  <properties>

17

    <!-- 设置项目编码编码 -->

18

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

19

    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

20

    <!-- spring版本号 -->

21

    <spring.version>4.3.5.RELEASE</spring.version>

22

    <!-- mybatis版本号 -->

23

    <mybatis.version>3.4.1</mybatis.version>

24

  </properties>

25

?

26

  <dependencies>

27

?

28

    <!-- java ee -->

29

    <dependency>

30

      <groupId>javax</groupId>

31

      <artifactId>javaee-api</artifactId>

32

      <version>7.0</version>

33

    </dependency>

34

?

35

    <!-- 单元测试 -->

36

    <dependency>

37

      <groupId>junit</groupId>

38

      <artifactId>junit</artifactId>

39

      <version>4.12</version>

40

    </dependency>

41

?

42

    <!-- 实现slf4j接口并整合 -->

43

    <dependency>

44

      <groupId>ch.qos.logback</groupId>

45

      <artifactId>logback-classic</artifactId>

46

      <version>1.2.2</version>

47

    </dependency>

48

?

49

    <!-- JSON -->

50

    <dependency>

51

      <groupId>com.fasterxml.jackson.core</groupId>

52

      <artifactId>jackson-databind</artifactId>

53

      <version>2.8.7</version>

54

    </dependency>

55

?

56

?

57

    <!-- 数据库 -->

58

    <dependency>

59

      <groupId>mysql</groupId>

60

      <artifactId>mysql-connector-java</artifactId>

61

      <version>5.1.41</version>

62

      <scope>runtime</scope>

63

    </dependency>

64

?

65

    <!-- 数据库连接池 -->

66

    <dependency>

67

      <groupId>com.mchange</groupId>

68

      <artifactId>c3p0</artifactId>

69

      <version>0.9.5.2</version>

70

    </dependency>

71

?

72

    <!-- MyBatis -->

73

    <dependency>

74

      <groupId>org.mybatis</groupId>

75

      <artifactId>mybatis</artifactId>

76

      <version>${mybatis.version}</version>

77

    </dependency>

78

?

79

    <!-- mybatis/spring整合包 -->

80

    <dependency>

81

      <groupId>org.mybatis</groupId>

82

      <artifactId>mybatis-spring</artifactId>

83

      <version>1.3.1</version>

84

    </dependency>

85

?

86

    <!-- Spring -->

87

    <dependency>

88

      <groupId>org.springframework</groupId>

89

      <artifactId>spring-core</artifactId>

90

      <version>${spring.version}</version>

91

    </dependency>

92

    <dependency>

93

      <groupId>org.springframework</groupId>

94

      <artifactId>spring-beans</artifactId>

95

      <version>${spring.version}</version>

96

    </dependency>

97

    <dependency>

98

      <groupId>org.springframework</groupId>

99

      <artifactId>spring-context</artifactId>

100

      <version>${spring.version}</version>

101

    </dependency>

102

    <dependency>

103

      <groupId>org.springframework</groupId>

104

      <artifactId>spring-jdbc</artifactId>

105

      <version>${spring.version}</version>

106

    </dependency>

107

    <dependency>

108

      <groupId>org.springframework</groupId>

109

      <artifactId>spring-tx</artifactId>

110

      <version>${spring.version}</version>

111

    </dependency>

112

    <dependency>

113

      <groupId>org.springframework</groupId>

114

      <artifactId>spring-web</artifactId>

115

      <version>${spring.version}</version>

116

    </dependency>

117

    <dependency>

118

      <groupId>org.springframework</groupId>

119

      <artifactId>spring-webmvc</artifactId>

120

      <version>${spring.version}</version>

121

    </dependency>

122

    <dependency>

123

      <groupId>org.springframework</groupId>

124

      <artifactId>spring-test</artifactId>

125

      <version>${spring.version}</version>

126

    </dependency>

127

?

128

  </dependencies>

129

  <build>

130

    <finalName>ssmSecondTry</finalName>

131

    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->

132

      <plugins>

133

        <plugin>

134

          <groupId>org.apache.maven.plugins</groupId>

135

          <artifactId>maven-compiler-plugin</artifactId>

136

          <configuration>

137

            <!-- 设置JDK版本 -->

138

            <source>1.8</source>

139

            <target>1.8</target>

140

          </configuration>

141

        </plugin>

142

        <plugin>

143

          <artifactId>maven-clean-plugin</artifactId>

144

          <version>3.1.0</version>

145

        </plugin>

146

        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->

147

        <plugin>

148

          <artifactId>maven-resources-plugin</artifactId>

149

          <version>3.0.2</version>

150

        </plugin>

151

        <plugin>

152

          <artifactId>maven-compiler-plugin</artifactId>

153

          <version>3.8.0</version>

154

        </plugin>

155

        <plugin>

156

          <artifactId>maven-surefire-plugin</artifactId>

157

          <version>2.22.1</version>

158

        </plugin>

159

        <plugin>

160

          <artifactId>maven-war-plugin</artifactId>

161

          <version>3.2.2</version>

162

        </plugin>

163

        <plugin>

164

          <artifactId>maven-install-plugin</artifactId>

165

          <version>2.5.2</version>

166

        </plugin>

167

        <plugin>

168

          <artifactId>maven-deploy-plugin</artifactId>

169

          <version>2.8.2</version>

170

        </plugin>

171

      </plugins>

172

    </pluginManagement>

173

  </build>

174

</project>

175

?

1.2 jdbc.properties

1.2.1 代码

11

1

driver = com.mysql.jdbc.Driver

2

url = jdbc:mysql://localhost:3306/mySSM

3

username = root

4

password = admin97

5

?

6

?

7

maxPoolSize = 30

8

minPoolSize = 10

9

autoCommitOnClose = false

10

checkoutTimeout = 10000

11

acquireRetryAttempts = 2

1.2.2 代码解析

前面四行是我们在操作JDBC的时候,常常操作的四项,分别是:驱动器、地址、用户名、密码。

第7行设定最大连接数为30。最大连接数是连接池能申请的最大连接数。如果数据连接请求超过此数,后面的数据连接请求将被加入到等待队列中,这会影响之后的数据库操作。

第8行设定最小连接数为10。最小连接数是连接池一直保持的数据连接。如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费掉。

第9行设定在关闭之后,不会自动执行commit。如果设置为true,那么在数据库的连接状态关闭的时候,会将没有commit的数据库操作,执行commit。

第10行设定连接超时时间。

第11行设定失败后尝试的次数。

这一个文件的设置十分明确。并且在它被读取的时候,也是以键值对的形式被读取的。

1.2 spring-mvc.xml

1.2.1 代码

28

1

<?xml version="1.0" encoding="UTF-8"?>

2

<beans xmlns="http://www.springframework.org/schema/beans"

3

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4

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

5

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

6

       xsi:schemaLocation="http://www.springframework.org/schema/beans

7

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

8

       http://www.springframework.org/schema/context

9

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

10

       http://www.springframework.org/schema/mvc

11

       http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

12

?

13

    <!-- 扫描web相关的bean -->

14

    <context:component-scan base-package="com.xzj.controller"/>

15

?

16

    <!-- 开启SpringMVC注解模式 -->

17

    <mvc:annotation-driven/>

18

?

19

    <!-- 静态资源默认servlet配置 -->

20

    <mvc:default-servlet-handler/>

21

?

22

    <!-- 配置jsp 显示ViewResolver -->

23

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

24

        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>

25

        <property name="prefix" value="/WEB-INF/views/"/>

26

        <property name="suffix" value=".jsp"/>

27

    </bean>

28

</beans>

1.2.2 代码解析

在这样的一个文件中,第1~11行都是环境。

第14行设置存放controller的目录,在这个目录下的类都会被扫描。

第17行将设定模式为注解模式,解析base-package目录下面带有@Controller注解的类。

第23~27行设定这个解析的前缀和后缀,前缀设定这个文件的目录,后缀设定这个文件的拓展名。

1.2.3 功能简析

SpringMVC是View层的一部分,来自于页面的信息由SpringMVC控制的Controller将请求发送到Model层中的Service中,然后再Model中处理业务逻辑。从Model返回的model,添加上前缀和后缀,传递到View层中。

所以,具体的细分的话,这是一个介于页面和Model层之间的模块:

1 将来自页面的请求,传递到合适的controller。

2 将从controller返回的一个jsp文件名的字符串,在这里包装之后,的到下一个jsp文件的全限定路径,然后显示出来。当然并不是所有的controller都有返回值,如果没有,那就是在当前的页面修改。

1.3 spring-mybatis.xml

1.3.1 代码

61

1

<?xml version="1.0" encoding="UTF-8"?>

2

<beans xmlns="http://www.springframework.org/schema/beans"

3

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4

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

5

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

6

       xsi:schemaLocation="http://www.springframework.org/schema/beans

7

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

8

       http://www.springframework.org/schema/context

9

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

10

       http://www.springframework.org/schema/tx

11

       http://www.springframework.org/schema/tx/spring-tx.xsd">

12

?

13

    <!-- 设定扫描路径 -->

14

    <context:component-scan base-package="com.xzj.service"/>

15

?

16

    <!-- 导入数据库配置文件 -->

17

    <context:property-placeholder location="classpath:jdbc.properties"/>

18

?

19

    <!-- 数据库连接池 -->

20

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

21

        <property name="driverClass" value="${driver}"/>

22

        <property name="jdbcUrl" value="${url}"/>

23

        <property name="user" value="${username}"/>

24

        <property name="password" value="${password}"/>

25

        <property name="maxPoolSize" value="${maxPoolSize}"/>

26

        <property name="minPoolSize" value="${minPoolSize}"/>

27

        <property name="autoCommitOnClose" value="${autoCommitOnClose}"/>

28

        <property name="checkoutTimeout" value="${checkoutTimeout}"/>

29

        <property name="acquireRetryAttempts" value="${acquireRetryAttempts}"/>

30

    </bean>

31

?

32

    <!-- 配置SqlSessionFactory -->

33

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

34

        <!-- 注入数据库连接池 -->

35

        <property name="dataSource" ref="dataSource"/>

36

?

37

        <!-- 扫描model包 使用别名 -->

38

        <property name="typeAliasesPackage" value="com.xzj.model"/>

39

?

40

        <!-- 扫描sql配置文件:mapper需要的xml文件 -->

41

        <property name="mapperLocations" value="classpath:mapper/*.xml"/>

42

    </bean>

43

?

44

    <!-- 配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->

45

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

46

        <!-- 注入sqlSessionFactory -->

47

        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>

48

?

49

        <!-- 给出需要扫描Dao接口包 -->

50

        <property name="basePackage" value="com.xzj.DAO"/>

51

    </bean>

52

?

53

    <!-- 配置事务管理器 -->

54

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

55

        <!-- 注入数据库连接池 -->

56

        <property name="dataSource" ref="dataSource"/>

57

    </bean>

58

?

59

    <!-- 配置基于注解的声明式事务 -->

60

    <tx:annotation-driven transaction-manager="transactionManager"/>

61

</beans>

1.3.2 代码解析

第14行:加上这一行以后,将自动扫描路径下面的包,如果一个类带了@Service注解,将自动注册到Spring容器,不需要在spring-mybatis.xml文件定义bean了。类似的注解还有Component、Repository、Controller。

例如:有下面一个类位于com.xzj.service或其子目录中:

5

1

@Service("xxx")

2

@Scope("yyy")

3

public class test extends A implements B{

4

······

5

}

那么就相当于在spring-mybatis.xml添加了一段这样的。

3

1

<bean id="xxx" class="com.xzj.service.test" scope="yyy">

2

         ......    

3

</bean>    

简而言之,这是一个将带有注解的类添加到Spring容器的语句。

第20~30行,创建数据库连接池,读取jdbc.properties文件中的有关于数据库的设置,按照这样的设置,设定数据库连接池的属性。

1.3.3 功能简析

纵观整个项目,就是这一块是最复杂的,在上面的代码中:

第50行和第38行的bean将DAO接口和mapper连接起来。这样的配置,使得在使用DAO接口的时候,直接调用接口方法,就可以直接调用DAO.xml中的sql语句。

另外的一点就是注册了service的目录,将service的内容注册到了Spring的容器中。也就是说,这个这个文件配置了两个方面的内容:一个是以service代表的业务逻辑,一个是以DAO及其映射mapper代表的数据访问,这两者共同组成了Model层。

1.4 web.xml

1.4.1 web.xml的代码

50

1

<?xml version="1.0" encoding="UTF-8"?>

2

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"

3

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4

         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

5

         version="3.1">

6

?

7

    <display-name>SSM</display-name>

8

    <description>SSM_test</description>

9

?

10

?

11

    <!-- 编码过滤器 -->

12

    <filter>

13

        <filter-name>encodingFilter</filter-name>

14

        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

15

        <init-param>

16

            <param-name>encoding</param-name>

17

            <param-value>UTF-8</param-value>

18

        </init-param>

19

    </filter>

20

    <filter-mapping>

21

        <filter-name>encodingFilter</filter-name>

22

        <url-pattern>/*</url-pattern>

23

    </filter-mapping>

24

?

25

?

26

    <!-- 配置前端控制器Spring MVC DispatcherServlet -->

27

    <servlet>

28

        <servlet-name>SpringMVC</servlet-name>

29

        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

30

        <!-- 配置两个文件 -->

31

        <init-param>

32

            <param-name>contextConfigLocation</param-name>

33

            <param-value>classpath:spring-*.xml</param-value>

34

        </init-param>

35

?

36

        <load-on-startup>1</load-on-startup>

37

        <async-supported>true</async-supported>

38

    </servlet>

39

    <servlet-mapping>

40

        <servlet-name>SpringMVC</servlet-name>

41

        <!-- 匹配所有请求,此处也可以配置成 *.do 形式 -->

42

        <url-pattern>/</url-pattern>

43

    </servlet-mapping>

44

?

45

    <welcome-file-list>

46

        <welcome-file>index.html</welcome-file>

47

    </welcome-file-list>

48

?

49

</web-app>

50

?

1.4.2 代码解析

配置编码过滤器。

配置分发器,并且这里的分发器中,注入了两个xml文件。

配置welcome页面。

2 MVC三层结构的简析

2.1 MVC的构成

2.1.1 M层

M层表示Model层,模型层。用来实现业务逻辑、对数据进行访问。

这一层大概分为三个部分,Model、Service、DAO这样的三块,以我创建的这个工程来讲三个部分分别是:

1 User类,这个类中有三个属性,分别有他们的get、set方法。

2 Service接口及其实现类。在spring-mybatis.xml中配置,从而被扫描。

3 UserDAO接口,在spring-mybatis.xml中配置,与UserDAO.xml配对,被动态实现。

即:这层的三个模块都是在spring-mybatis.xml中被配置的。

2.1.2 V层

V层表示View层,显示层。是用来和用户交互的可视化界面,如html和jsp文件在浏览器中的显示。同样,在这些显示页面中,可以设定不同的请求,根据不同的前端动作,提交给分发器。那么这样的到的响应也不同。

2.1.3 C层

C层表示Controller控制器。C层大致上有两种功能:

1 根据不同的请求,调用M层中不同业务逻辑处理。

2 得到了来自M层处理结果的返回,给予V层的显示结果也不相同。

这一块是在spring-mvc.xml配置的。

2.2 M层的具体构成

2.2.1 简述

M层是Model层,负责业务逻辑和数据访问。以这个项目为例子,除了controller 以外的Java类和接口都是属于Model层的的,除此之外还有UserDAO.xml也是属于Model层的。

2.2.2 User类

User的代码如下:

53

1

package com.xzj.model;

2

?

3

//   @ author :zjxu     time:2018/12/31

4

public class User {

5

    private int userID;

6

    private String userName;

7

    private String userPassword;

8

    private String comments;

9

?

10

    public int getUserID() {

11

        return userID;

12

    }

13

?

14

    public String getUserName() {

15

        return userName;

16

    }

17

?

18

    public String getUserPassword() {

19

        return userPassword;

20

    }

21

?

22

    public String getComments() {

23

        return comments;

24

    }

25

?

26

?

27

    public void setUserID(int userID) {

28

        this.userID = userID;

29

    }

30

?

31

    public void setUserName(String userName) {

32

        this.userName = userName;

33

    }

34

?

35

    public void setUserPassword(String userPassword) {

36

        this.userPassword = userPassword;

37

    }

38

?

39

    public void setComments(String comments) {

40

        this.comments = comments;

41

    }

42

?

43

    @Override

44

    public String toString() {

45

        return "User{" +

46

                "userID=" + userID +

47

                ", userName=‘" + userName + ‘\‘‘ +

48

                ", userPassword=‘" + userPassword + ‘\‘‘ +

49

                ", comments=‘" + comments + ‘\‘‘ +

50

                ‘}‘;

51

    }

52

}

53

?

言简意赅,这一段代码就是定义一个User类,并且定义了几个域。id、name、password、comments。设定了它们的getter和setter。

2.2.3 UserService接口

8

1

package com.xzj.service;

2

import com.xzj.model.User;

3

?

4

//   @ author :zjxu     time:2018/12/31

5

?

6

public interface UserService {

7

    public User selectUser(long userID);

8

}

申明一个接口,这个接口是Model层中的service的接口。它的实现类,必须实现在这个类中定义的方法。其实这个接口并不是必须的,在spring-mybatis.xml中,配置的com.xzj.service目录中直接写UserServiceImple类,即可将这个类配置进spring中。但是有这个过接口可以将Model层中的service服务的结构更加清晰。所以在这个工程中,就使用了UserService接口。

2.2.4 UserServiceImple 类

21

1

package com.xzj.service.imple;

2

?

3

//   @ author :zjxu     time:2018/12/31

4

?

5

import com.xzj.DAO.UserDAO;

6

import com.xzj.model.User;

7

import com.xzj.service.UserService;

8

import org.springframework.stereotype.Service;

9

import javax.annotation.Resource;

10

?

11

@Service("userService")

12

public class UserServiceImple implements UserService {

13

?

14

    @Resource

15

    private UserDAO userDAO;

16


17

    public User selectUser(long UserID) {

18

        return this.userDAO.selectUser(UserID);

19

    }

20

}

21

?

UserService的实现类,其中两个很重要的是两个注解11和14行的两个注解。 ?第11行的注解@Service("userService”),表示是为userService服务的,这个userService是controller的userService类。

2.2.5 UserDAO 接口

9

1

package com.xzj.DAO;

2

?

3

//   @ author :zjxu     time:2018/12/31

4

?

5

import com.xzj.model.User;

6

?

7

public interface UserDAO {

8

    User selectUser(long id);

9

}

2.2.5 UserDAO.xml

10

1

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

2

?

3

<!-- 设置为UserDao接口方法提供sql语句配置 -->

4

<mapper namespace="com.xzj.DAO.UserDAO">

5

?

6

    <select id="selectUser" resultType="User" parameterType="long">

7

        SELECT * FROM userList WHERE userID = #{id}

8

    </select>

9

?

10

</mapper>

2.3 C层的具体构成

2.3.1 简述

C层就是 controller,位于Model层和View层之间的一层。

2.3.2 Controller 类

50

1

package com.xzj.controller;

2

?

3

//   @ author :zjxu     time:2018/12/31

4

?

5

import com.fasterxml.jackson.databind.ObjectMapper;

6

import com.xzj.model.User;

7

import com.xzj.service.UserService;

8

import org.springframework.stereotype.Controller;

9

import org.springframework.web.bind.annotation.RequestMapping;

10

import org.springframework.web.servlet.ModelAndView;

11

?

12

import javax.annotation.Resource;

13

import javax.servlet.http.HttpServletRequest;

14

import javax.servlet.http.HttpServletResponse;

15

import java.io.IOException;

16

?

17

@Controller

18

public class UserController {

19

?

20

    @Resource

21

    private UserService userService;

22

?

23

    @RequestMapping("/showUser.do")

24

    public void selectUser(HttpServletRequest request,HttpServletResponse response,ModelAndView mav) throws IOException {

25


26

        request.setCharacterEncoding("UTF-8");

27

        response.setCharacterEncoding("UTF-8");

28

?

29

        long userId = Long.parseLong(request.getParameter("id"));

30

        User user = this.userService.selectUser(userId);

31

        System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n" + userId + "\n\n\n\n\n\n\n\n\n\n\n\n");

32

?

33

        ObjectMapper mapper = new ObjectMapper();

34

        response.getWriter().write(mapper.writeValueAsString(user));

35

        response.getWriter().close();

36

    }

37

?

38

    @RequestMapping("/test")

39

    public ModelAndView test(HttpServletRequest request,HttpServletResponse response)throws IOException {

40

?

41

        ModelAndView mav = new ModelAndView();

42

        mav.addObject("name", "SpringMVC");

43

        mav.setViewName("test");

44

        return mav;

45

?

46

    }

47

?

48

}

49

?

50

?

2.3.3 Controller层注解的详细分析

在controller中,重要的地方在于这几个注解。controller、Resource、RequestMapping这单个注解。

1 注解@Controller。

表明这是一个Controller类,spring-mvc.xml文件设定的扫描目录下被扫描。

2 注解@Resource。

这个注解放在UserService的申明的前一行。它声明一个名为userService的对象,并且这个对象的类型为UserService接口的实现类。

通过@Resource注解,可以在service目录下UserServiceImple类中找到带有一个@Service("userService”)的注解,找到的注解中的变量名和这个注解下一行声明的对象的变量名是一致的。

在service目录下找到的那个类前面的注解表明在controller中的申明的对象的具体类型的UserServiceImple,它实现了UserService这个接口。

也就是说,@Service(“userService”)注解的类,为@Resource下一行的名为userService的对象服务。而它们一个位于service目录下,一个位于controller目录下。这两个目录都被添加到了spring-*.xml中。这样的对应关系,是属于两个层的

3 注解@RequestMapping

参数类型为一个字符串。这个参数的意义是从controller来的除了项目以外的三级及以下的URL地址。比如:

1

1

http://localhost:8080/ssm/test

这样的一个地址,经过分发器,来到了controller,controller会根据除了localhost/ssm/之外的地址,调用不同的方法。在controller这端,就会将后面的这段url地址通过注解,标记在方法上,或者是类上面。以这个url来看,它就会调用UserController.test(request,response)方法。

注解的位置的区别在于:

<1> 类的上方没有注解的时候,这个类的下面所有的方法的注解都需要添加参数。当然,也不是所有的方法都需要有注解。

但是只要是存在的注解都需要有参数。否则这样写的controller方法,作出的效果将会是“localhost:8080/ssm”的结果,这样welcome页面将会失效。

<2> 类的上方存在注解,那么这个注解会成为这个一个上级字符串加在类中的方法上的字符串上。就如同java的package的目录一样。com.xzj.test这样子,只不过在这里是用’/’来连接。

2.4 V层的具体构成

V层是直接面对用户的页面。所以在V层中,写的代码都是面向用户的操作的,尽管有一部分和请求相关,但是绝大部分还是于页面的展示相关的。

2.4.1 index.html文件

27

1

<!DOCTYPE html>

2

<html>

3

<head>

4

    <meta charset="UTF-8">

5

    <title>test</title>

6

</head>

7

<script>

8

    function selectUser() {

9

        var xmlhttp = new XMLHttpRequest();

10

        xmlhttp.onreadystatechange = function () {

11

            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {

12

                document.getElementById("test").innerHTML = xmlhttp.responseText;

13

            }

14

        }

15

        xmlhttp.open("POST", "showUser.do", true);

16

        xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

17

        xmlhttp.send("id=100");

18

    }

19

</script>

20

<body>

21

<p id="test">Hello World!</p>

22

<button type="button" onclick="selectUser()">onclick test</button>

23

<br/>

24

<a href="test">ThisIsALinkForTest</a>

25

<br/>

26

</body>

27

</html>

这段html代码,其中的重点在于javascript代码中的Ajax掌握。

这段短短的javascript,发起请求,获得响应,设定显示,完成这三个工作。

按钮-响应,这一块非常基础的前端应用,主要的问题来自于响应方法中的Http请求。关于javascript的代码逻辑,虽然一眼就能明了,但是,还是要仔细研究一下ajax如何在html文件中,更加精巧的应用。

对于这个连接,就是在点击之后,会跳转到显示/WEB-INF/views/test.jsp相当于一个请求controller,并通过controller的到一个“test”的字符串,将其包装成为了一个完整的路径,在View层显示。

2.4.2 jsp目录及其下的test.jsp文件

17

1

<%--

2

  Created by IntelliJ IDEA.

3

  User: thisxzj

4

  Date: 2019/1/1

5

  Time: 23:45

6

  To change this template use File | Settings | File Templates.

7

--%>

8

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

9

<html>

10

<head>

11

    <title>xxx</title>

12

</head>

13

<body>

14

<h>test</h>

15

<p>我新建的项目是${name}</p>

16

</body>

17

</html>

这个jsp的路径是/WEB-INF/views/test.jsp,在从controller中返回一个字符串,比如一个“test”串,或者是modelAndView.setViewName("test”),并将其返回。

就会通过spring-mvc.xml中的下两行,将其包装成/WEB-INF/views/test.jsp。并将其显示到页面中。

2

1

        <property name="prefix" value="/WEB-INF/views/"/>

2

        <property name="suffix" value=".jsp"/>

在这样一个jsp页面中,${name}这个变量,是通过controller类中以返回modealAndView的方式,在modelAndView对象:

1

1

modelAndView.addObject("name", "SpringMVC");

那么在jsp页面中,将会读取这个KV,将name显示为成“SpringMVC”。这样就完成了一个从后台向前台的传输的过程。

响应过程

1 用户在浏览器窗口输入一个URL地址,以localhost:8080/ssm/为例子,由于这个URL是直接localhost/ssm/后面并没有接更多的信息,就会直接显示在web.xml中设定的welcome页面index.html。?这个过程发生在View层。

2 于是在浏览器页面上就会显示index.html的内容。用户按下显示onclick test的按钮,通过javascript的ajax发送一个包含一个字符串“showUser.do”和一个KV对“id = 1”的一个请求到controller,controller再根据请求中的“showUser.do”调用对应的controller方法。?这个过程从View层到Controller层。

3 请求来到Cotroller,通过扫描在Spring-MVC.xml中配置的目录下的所有的Java类。找到这个目录下所有带有@Controller的类。在这些类中寻找“showUser.do”对应的方法。在Controller类的第24行找到了一个selectUser方法。那么就会执行这个方法,对来自View层的请求进行响应。这个过程发生在Controller层

4 找到这个方法了,开始执行。这个方法的核心在于,使用了userService这个对象以及它的的方法。关于如何使用的,在2.3.3中有详细的解释。在在这个类中,使用这个对象以及它的seclectUser方法,就是工作从Controller层到Model层的转移。

5 来到Model层,映入眼帘的就是Service接口的实现类ServiceImple。我们不关注Service接口,经过我的测试,去掉这个接口对程序的运行也没有影响。但是这个接口的存在,可以使Service方法更加规范化。在大型工程中,有一个这样的接口可以更加规范。在这个ServiceImple类中,申明了一个UserDAO的对象,这个对象并没有实体。通过注解,将UserDAO.xml作为这个接口的实体,使用定义在UserDAO.xml中的sql语句操作数据库。

sql语句和UserDAO的对应,通过在spring-mybatis.xml中,将mapper的目录和DAO接口的目录配置进去。这样在mapper的xml中,声明是对哪一个DAO接口的实现,并且在每一个sql方法的标签内,设置id为对应的DAO接口中的方法名,就可以视作将DAO的方法在mapper的xml中实现了。

通过目录、接口名、方法名的一系列配置,在调用UserDAO接口的方法的时候,就可以直接使用对应的sql语句。以:

1

1

   User user = this.userService.selectUser(userId);

然后在UserServiceImple中,调用UserDAO的方法:

1

1

this.userDAO.selectUser(UserID);

在通过DAO的配置,使用UserDAO.xml中的sql语句操作数据库。

这个部分的操作都是在Model层。但是将Model层分为两个模块:service和DAO的话,那么这个部分是在Model层中是从service到DAO的转移

6 我们忽略mapper的xml文件中具体执行了什么。只考虑对数据库操作之后有没有数据的返回。

如果没有,那么一个从前到后的SSM请求到响应就已经结束了。

大多数时候是有返回的。通过mapper的xml文件中的result设定的返回值类型,将从数据库中获取的数值,包装成一个返回类型,返回给UserServiceImple的对象。

在这个例子中是从数据库中获取指定id处的,一个User对象的所有信息,将其包装成一个User对象,返回给UserServiceImple。

这个部分的操作都是在Model层,细分的话那么这个部分是在Model层中是从DAO到service的转移

7 UserServiceImple对象将从DAO获得了一个User对象的返回值,返回给Controller层。

这一个操作是从Model层返回到Controller层

8 这样的一个User对象从DAO、Service传递了Controller层中由“showUser.do”对应的那个方法中继续着下一步的操作。

通过下面两行语句,将获取的User对象转换成一个字符串,然后传送到javascript代码中请求所对应的响应码responseText中。

2

1

ObjectMapper mapper = new ObjectMapper();

2

response.getWriter().write(mapper.writeValueAsString(user);

然后通过DOM操作,将html中的某个字段修改成User对象的字符串形式。完成了获取内容在页面上的显示。这一步是从Controller层到View层的传递

html { }
:root { }
html { font-size: 14px; background-color: var(--bg-color); color: var(--text-color); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif }
body { margin: 0px; padding: 0px; height: auto; bottom: 0px; top: 0px; left: 0px; right: 0px; font-size: 1rem; line-height: 1.42857143; background-image: inherit; background-attachment: inherit; background-color: inherit; background-position: inherit inherit; background-repeat: inherit inherit }
iframe { margin: auto }
a.url { }
a:active,a:hover { outline: 0px }
.in-text-selection,::selection { background: var(--select-text-bg-color); color: var(--select-text-font-color) }
#write { margin: 0px auto; height: auto; width: inherit; position: relative; white-space: normal }
#write.first-line-indent p { text-indent: 2em }
#write.first-line-indent li p,#write.first-line-indent p * { text-indent: 0px }
#write.first-line-indent li { margin-left: 2em }
.for-image #write { padding-left: 8px; padding-right: 8px }
body.typora-export { padding-left: 30px; padding-right: 30px }
.typora-export .footnote-line,.typora-export p { white-space: pre-wrap }
#write li>figure:first-child { margin-top: -20px }
#write ol,#write ul { position: relative }
img { max-width: 100%; vertical-align: middle }
button,input,select,textarea { color: inherit; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; line-height: inherit }
input[type="checkbox"],input[type="radio"] { line-height: normal; padding: 0px }
*,::after,::before { }
#write h1,#write h2,#write h3,#write h4,#write h5,#write h6,#write p,#write pre { width: inherit }
#write h1,#write h2,#write h3,#write h4,#write h5,#write h6,#write p { position: relative }
h1,h2,h3,h4,h5,h6 { orphans: 2 }
p { orphans: 4 }
h1 { font-size: 2rem }
h2 { font-size: 1.8rem }
h3 { font-size: 1.6rem }
h4 { font-size: 1.4rem }
h5 { font-size: 1.2rem }
h6 { font-size: 1rem }
.md-math-block,.md-rawblock,h1,h2,h3,h4,h5,h6,p { margin-top: 1rem; margin-bottom: 1rem }
.hidden { display: none }
.md-blockmeta { color: rgb(204, 204, 204); font-weight: 700; font-style: italic }
a { cursor: pointer }
sup.md-footnote { padding: 2px 4px; background-color: rgba(238, 238, 238, 0.701961); color: rgb(85, 85, 85); cursor: pointer }
sup.md-footnote a,sup.md-footnote a:hover { color: inherit; text-transform: inherit; text-decoration: inherit }
#write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit }
figure { margin: 1.2em 0px; max-width: calc(100% + 16px); padding: 0px }
figure>table { margin: 0px !important }
tr { }
thead { display: table-header-group }
table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; text-align: left }
table.md-table td { min-width: 80px }
.CodeMirror-gutters { border-right-width: 0px; background-color: inherit }
.CodeMirror { text-align: left }
.CodeMirror-placeholder { opacity: 0.3 }
.CodeMirror pre { padding: 0px 4px }
.CodeMirror-lines { padding: 0px }
div.hr:focus { cursor: none }
#write pre { white-space: pre-wrap }
#write.fences-no-line-wrapping pre { white-space: pre }
#write pre.ty-contain-cm { white-space: normal }
.CodeMirror-gutters { margin-right: 4px }
.md-fences { font-size: 0.9rem; display: block; text-align: left; overflow: visible; white-space: pre; background-image: inherit; background-attachment: inherit; background-color: inherit; position: relative !important; background-position: inherit inherit; background-repeat: inherit inherit }
.md-diagram-panel { width: 100%; margin-top: 10px; text-align: center; padding-top: 0px; padding-bottom: 8px }
#write .md-fences.mock-cm { white-space: pre-wrap }
.md-fences.md-fences-with-lineno { padding-left: 0px }
#write.fences-no-line-wrapping .md-fences.mock-cm { white-space: pre }
.md-fences.mock-cm.md-fences-with-lineno { padding-left: 8px }
.CodeMirror-line,twitterwidget { }
.footnotes { opacity: 0.8; font-size: 0.9rem; margin-top: 1em; margin-bottom: 1em }
.footnotes+.footnotes { margin-top: 0px }
.md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; text-decoration: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; line-height: normal; font-weight: 400; text-align: left; direction: ltr; background-position: 0px 0px; background-repeat: initial initial }
li div { padding-top: 0px }
blockquote { margin: 1rem 0px }
li .mathjax-block,li p { margin: 0.5rem 0px }
li { margin: 0px; position: relative }
blockquote>:last-child { margin-bottom: 0px }
blockquote>:first-child,li>:first-child { margin-top: 0px }
.footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; white-space: normal }
#write .footnote-line { white-space: pre-wrap }
.footnote-line { margin-top: 0.714em; font-size: 0.7em }
a img,img a { cursor: pointer }
pre.md-meta-block { font-size: 0.8rem; min-height: 0.8rem; white-space: pre-wrap; background-color: rgb(204, 204, 204); display: block; background-position: initial initial; background-repeat: initial initial }
p>.md-image:only-child:not(.md-img-error) img,p>img:only-child { display: block; margin: auto }
p>.md-image:only-child { display: inline-block; width: 100% }
#write .MathJax_Display { margin: 0.8em 0px 0px }
.md-math-block { width: 100% }
.md-math-block:not(:empty)::after { display: none }
[contenteditable="true"]:active,[contenteditable="true"]:focus { outline: 0px }
.md-task-list-item { position: relative; list-style-type: none }
.task-list-item.md-task-list-item { padding-left: 0px }
.md-task-list-item>input { position: absolute; top: 0px; left: 0px; margin-left: -1.2em; margin-top: calc(1em - 10px) }
.math { font-size: 1rem }
.md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem }
.md-toc-content { position: relative; margin-left: 0px }
.md-toc-content::after,.md-toc::after { display: none }
.md-toc-item { display: block; color: rgb(65, 131, 196) }
.md-toc-item a { text-decoration: none }
.md-toc-inner:hover { text-decoration: underline }
.md-toc-inner { display: inline-block; cursor: pointer }
.md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: 700 }
.md-toc-h2 .md-toc-inner { margin-left: 2em }
.md-toc-h3 .md-toc-inner { margin-left: 4em }
.md-toc-h4 .md-toc-inner { margin-left: 6em }
.md-toc-h5 .md-toc-inner { margin-left: 8em }
.md-toc-h6 .md-toc-inner { margin-left: 10em }
a.md-toc-inner { font-size: inherit; font-style: inherit; font-weight: inherit; line-height: inherit }
.footnote-line a:not(.reversefootnote) { color: inherit }
.md-attr { display: none }
.md-fn-count::after { content: "." }
code,pre,samp,tt { font-family: var(--monospace) }
kbd { margin: 0px 0.1em; padding: 0.1em 0.6em; font-size: 0.8em; color: rgb(36, 39, 41); background-color: rgb(255, 255, 255); border: 1px solid rgb(173, 179, 185); white-space: nowrap; vertical-align: middle; background-position: initial initial; background-repeat: initial initial }
.md-comment { color: rgb(162, 127, 3); opacity: 0.8; font-family: var(--monospace) }
code { text-align: left }
a.md-print-anchor { white-space: pre !important; border: none !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: 0px !important; background-position: 0px 0px !important; background-repeat: initial initial !important }
.md-inline-math .MathJax_SVG .noError { display: none !important }
.md-math-block .MathJax_SVG_Display { text-align: center; margin: 0px; position: relative; text-indent: 0px; max-width: none; max-height: none; min-height: 0px; min-width: 100%; width: auto; display: block !important }
.MathJax_SVG_Display,.md-inline-math .MathJax_SVG_Display { width: auto; margin: inherit; display: inline-block !important }
.MathJax_SVG .MJX-monospace { font-family: var(--monospace) }
.MathJax_SVG .MJX-sans-serif { font-family: sans-serif }
.MathJax_SVG { display: inline; font-style: normal; font-weight: 400; line-height: normal; text-indent: 0px; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border: 0px; padding: 0px; margin: 0px }
.MathJax_SVG * { }
.MathJax_SVG_Display svg { vertical-align: middle !important; margin-bottom: 0px !important }
.os-windows.monocolor-emoji .md-emoji { font-family: "Segoe UI Symbol", sans-serif }
.md-diagram-panel>svg { max-width: 100% }
[lang="mermaid"] svg,[lang="flow"] svg { max-width: 100% }
[lang="mermaid"] .node text { font-size: 1rem }
table tr th { border-bottom-width: 0px }
video { max-width: 100%; display: block; margin: 0px auto }
iframe { max-width: 100%; width: 100%; border: none }
.highlight td,.highlight tr { border: 0px }
.CodeMirror { height: auto }
.CodeMirror.cm-s-inner { background-image: inherit; background-attachment: inherit; background-color: inherit; background-position: inherit inherit; background-repeat: inherit inherit }
.CodeMirror-scroll { z-index: 3 }
.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler { background-color: rgb(255, 255, 255) }
.CodeMirror-gutters { border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); background-image: inherit; background-attachment: inherit; background-color: inherit; white-space: nowrap; background-position: inherit inherit; background-repeat: inherit inherit }
.CodeMirror-linenumber { padding: 0px 3px 0px 5px; text-align: right; color: rgb(153, 153, 153) }
.cm-s-inner .cm-keyword { color: rgb(119, 0, 136) }
.cm-s-inner .cm-atom,.cm-s-inner.cm-atom { color: rgb(34, 17, 153) }
.cm-s-inner .cm-number { color: rgb(17, 102, 68) }
.cm-s-inner .cm-def { color: rgb(0, 0, 255) }
.cm-s-inner .cm-variable { color: rgb(0, 0, 0) }
.cm-s-inner .cm-variable-2 { color: rgb(0, 85, 170) }
.cm-s-inner .cm-variable-3 { color: rgb(0, 136, 85) }
.cm-s-inner .cm-string { color: rgb(170, 17, 17) }
.cm-s-inner .cm-property { color: rgb(0, 0, 0) }
.cm-s-inner .cm-operator { color: rgb(152, 26, 26) }
.cm-s-inner .cm-comment,.cm-s-inner.cm-comment { color: rgb(170, 85, 0) }
.cm-s-inner .cm-string-2 { color: rgb(255, 85, 0) }
.cm-s-inner .cm-meta { color: rgb(85, 85, 85) }
.cm-s-inner .cm-qualifier { color: rgb(85, 85, 85) }
.cm-s-inner .cm-builtin { color: rgb(51, 0, 170) }
.cm-s-inner .cm-bracket { color: rgb(153, 153, 119) }
.cm-s-inner .cm-tag { color: rgb(17, 119, 0) }
.cm-s-inner .cm-attribute { color: rgb(0, 0, 204) }
.cm-s-inner .cm-header,.cm-s-inner.cm-header { color: rgb(0, 0, 255) }
.cm-s-inner .cm-quote,.cm-s-inner.cm-quote { color: rgb(0, 153, 0) }
.cm-s-inner .cm-hr,.cm-s-inner.cm-hr { color: rgb(153, 153, 153) }
.cm-s-inner .cm-link,.cm-s-inner.cm-link { color: rgb(0, 0, 204) }
.cm-negative { color: rgb(221, 68, 68) }
.cm-positive { color: rgb(34, 153, 34) }
.cm-header,.cm-strong { font-weight: 700 }
.cm-del { text-decoration: line-through }
.cm-em { font-style: italic }
.cm-link { text-decoration: underline }
.cm-error { color: red }
.cm-invalidchar { color: red }
.cm-constant { color: rgb(38, 139, 210) }
.cm-defined { color: rgb(181, 137, 0) }
div.CodeMirror span.CodeMirror-matchingbracket { color: rgb(0, 255, 0) }
div.CodeMirror span.CodeMirror-nonmatchingbracket { color: rgb(255, 34, 34) }
.cm-s-inner .CodeMirror-activeline-background { background-image: inherit; background-attachment: inherit; background-color: inherit; background-position: inherit inherit; background-repeat: inherit inherit }
.CodeMirror { position: relative; overflow: hidden }
.CodeMirror-scroll { height: 100%; outline: 0px; position: relative; background-image: inherit; background-attachment: inherit; background-color: inherit; background-position: inherit inherit; background-repeat: inherit inherit }
.CodeMirror-sizer { position: relative }
.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar { position: absolute; z-index: 6; display: none }
.CodeMirror-vscrollbar { right: 0px; top: 0px; overflow: hidden }
.CodeMirror-hscrollbar { bottom: 0px; left: 0px; overflow: hidden }
.CodeMirror-scrollbar-filler { right: 0px; bottom: 0px }
.CodeMirror-gutter-filler { left: 0px; bottom: 0px }
.CodeMirror-gutters { position: absolute; left: 0px; top: 0px; padding-bottom: 30px; z-index: 3 }
.CodeMirror-gutter { white-space: normal; height: 100%; padding-bottom: 30px; margin-bottom: -32px; display: inline-block }
.CodeMirror-gutter-wrapper { position: absolute; z-index: 4; border: none !important; background-position: 0px 0px !important; background-repeat: initial initial !important }
.CodeMirror-gutter-background { position: absolute; top: 0px; bottom: 0px; z-index: 4 }
.CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4 }
.CodeMirror-lines { cursor: text }
.CodeMirror pre { border-width: 0px; font-family: inherit; font-size: inherit; margin: 0px; white-space: pre; color: inherit; z-index: 2; position: relative; overflow: visible; background-position: 0px 0px; background-repeat: initial initial }
.CodeMirror-wrap pre { white-space: pre-wrap }
.CodeMirror-code pre { border-right-width: 30px; border-right-style: solid; border-right-color: transparent; width: fit-content }
.CodeMirror-wrap .CodeMirror-code pre { border-right-style: none; width: auto }
.CodeMirror-linebackground { position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; z-index: 0 }
.CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto }
.CodeMirror-wrap .CodeMirror-scroll { }
.CodeMirror-measure { position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden }
.CodeMirror-measure pre { position: static }
.CodeMirror div.CodeMirror-cursor { position: absolute; visibility: hidden; border-right-style: none; width: 0px }
.CodeMirror div.CodeMirror-cursor { visibility: hidden }
.CodeMirror-focused div.CodeMirror-cursor { visibility: inherit }
.cm-searching { background-color: rgba(255, 255, 0, 0.4); background-position: initial initial; background-repeat: initial initial }
:root { }
.mac-seamless-mode #typora-sidebar { top: 20px; padding-top: 0; height: auto }
html,body,#write { background: var(--bg-color); font-family: "TeXGyreAdventor", "Century Gothic", "Yu Gothic", "Raleway", sans-serif; font-weight: 300 }
h1,h2,h3,h4,h5,h6 { color: #111; font-family: "TeXGyreAdventor", "Century Gothic", "Yu Gothic", "Ubuntu", sans-serif }
html { font-size: 16px }
#write { max-width: 914px; text-align: justify }
#write>h1:first-child { margin-top: 2.75rem }
#write>h2:first-child { margin-top: 1.75rem }
#write>h3:first-child { margin-top: 1rem }
#write>h4:first-child { margin-top: 0.5rem }
h1 { font-weight: normal; line-height: 4rem; margin: 0 0 1.75rem; padding: 20px 30px; text-align: center; text-transform: uppercase; margin-top: 4rem }
h2 { font-weight: normal; line-height: 3rem; margin: 0 0 1.9375rem; padding: 0 30px; text-align: center; text-transform: uppercase; margin-top: 3rem }
h3 { font-weight: normal }
h4 { font-weight: normal }
h5 { font-size: 1.125rem; font-weight: normal }
h6 { font-size: 1rem; font-weight: bold }
p { color: #111; font-size: 1rem; line-height: 1.75rem; margin: 0 0 1.25rem }
#write>h3.md-focus::before { left: -1.875rem; top: 0.5rem; padding: 2px }
#write>h4.md-focus::before { left: -1.875rem; top: 0.3125rem; padding: 2px }
#write>h5.md-focus::before { left: -1.875rem; top: 0.25rem; padding: 2px }
#write>h6.md-focus::before { left: -1.875rem; top: .125rem; padding: 2px }
a,.md-def-url { color: #990000; text-decoration: none }
a:hover { text-decoration: underline }
table { margin-bottom: 20px }
table th,table td { padding: 8px; line-height: 1.25rem; vertical-align: top; border-top: 1px solid #ddd }
table th { font-weight: bold }
table thead th { vertical-align: bottom }
table caption+thead tr:first-child th,table caption+thead tr:first-child td,table colgroup+thead tr:first-child th,table colgroup+thead tr:first-child td,table thead:first-child tr:first-child th,table thead:first-child tr:first-child td { border-top: 0 }
table tbody+tbody { border-top: 2px solid #ddd }
code,.md-fences { border: 1px solid #ccc; padding: .1em; font-size: 0.9em; margin-left: 0.2em; margin-right: 0.2em }
.md-fences { margin: 0 0 20px; font-size: 1em; padding: 0.3em 1em; padding-top: 0.4em }
.task-list { padding-left: 0 }
.task-list-item { padding-left: 2.125rem }
.task-list-item input { top: 3px }
.md-task-list-item input { margin-left: -1.5em }
.task-list-item input::before { content: ""; display: inline-block; width: 1rem; height: 1rem; vertical-align: middle; text-align: center; border: 1px solid gray; background-color: #fdfdfd; margin-left: 0; margin-top: -1rem }
.typora-node .task-list-item input::before { top: 0.3ex; position: absolute }
.task-list-item input:checked::before,.task-list-item input[checked]::before { content: "?"; font-size: 0.8125rem; line-height: 0.9375rem }
blockquote { margin: 0 0 1.11111rem; padding: 0.5rem 1.11111rem 0 1.05556rem; border-left: 1px solid gray }
blockquote,blockquote p { line-height: 1.6; color: #6f6f6f }
#write pre.md-meta-block { min-height: 30px; background: #f8f8f8; padding: 1.5em; font-weight: 300; font-size: 1em; padding-bottom: 1.5em; padding-top: 3em; margin-top: -1.5em; color: #999; width: 100vw; max-width: calc(100% + 60px); margin-left: -30px; border-left: 30px #f8f8f8 solid; border-right: 30px #f8f8f8 solid }
.MathJax_Display { font-size: 0.9em; margin-top: 0.5em; margin-bottom: 0 }
p.mathjax-block,.mathjax-block { padding-bottom: 0 }
.mathjax-block>.code-tooltip { bottom: 5px }
.md-image>.md-meta { padding-left: 0.5em; padding-right: 0.5em }
.md-image>img { margin-top: 2px }
.md-image>.md-meta:first-of-type::before { padding-left: 4px }
#typora-source { color: #555 }
#md-searchpanel { border-bottom: 1px solid #ccc }
#md-searchpanel .btn { border: 1px solid #ccc }
#md-notification::before { top: 14px }
#md-notification { background: #eee }
.megamenu-menu-panel .btn { border: 1px solid #ccc }
#typora-sidebar { }
.file-list-item,.show-folder-name .file-list-item { padding-top: 20px; padding-bottom: 20px; line-height: 20px }
.file-list-item-summary { height: 40px; line-height: 20px }
.ty-table-edit { background: #ededed }
.dropdown-menu .divider { border-color: #e5e5e5 }
.typora-export p,.typora-export .footnote-line { white-space: normal }

原文地址:https://www.cnblogs.com/zjxu97/p/10211203.html

时间: 2024-08-10 21:52:18

SSM中的MVC结构分析,SSM框架的响应流程的相关文章

maven/eclipse搭建ssm(spring+spring mvc+mybatis)

maven/eclipse搭建ssm(spring+spring mvc+mybatis) 前言 本文旨在利用maven搭建ssm环境,而关于maven的具体内容,大家可以去阅读<Maven 实战>.其实园内这方面文章已有不少,那么为什么我还要重复造轮子呢?我只是想记录自己的实践过程罢了,附带着给别人以参考.对于别人的博文,看了固然好,要是能付之实践,那就更好了! maven安装 安装过程挺简单的,去apache下载apache-maven的zip包,解压到一个目录下,如下图 接下来配置win

SSM三大框架详细整合流程

1.基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途不仅限于服务器端的开发.从简单性.可测试性和松耦合的角度而言,任何Java

MVC在Web框架中的应用

MVC三个主要部分的定义大致如下: 模型:模型是描述程序设计人员感兴趣问题域的一些类,这些类通常封装存储在数据库中的数据,以及操作这些数据和执行特定域业务逻辑的代码. 在ASP.NET MVC中,模型就像使用了某种工具的数据访问层(Data Access Layer),这种工具包括实体框架(Entity Framework)或者包含 特定域逻辑的自定义代码组合在一起的NHibernate. 视图:一个动态生成HTML页面的模板 控制器:一个协调视图和模型之间关系的特殊类.它响应用户输入,与模型进

二十七、EFW框架BS系统开发中的MVC模式探讨

回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://pan.baidu.com/s/1eQCc69G 上一章<EFW框架破茧成蝶>通过讲叙自己的一些编程经验,有对系统架构的认识,也有EFW框架中MVC模式的由来.整个过程分为五个阶段: asp网站:做asp网站的时候根本没有什么系统的概念,就是几段代码复制粘贴拼装成外表不一样,功能就是那么几个的企业网

在Spring MVC中使用Apache Shiro安全框架

我们在这里将对一个集成了Spring MVC+Hibernate+Apache Shiro的项目进行了一个简单说明.这个项目将展示如何在Spring MVC 中使用Apache Shiro来构建我们的安全框架. [TOC] 阅读文章前,您需要做以下准备: Maven 3环境Mysql-5.6+JDK1.7+git环境git.oschina.net帐号Apache Tomcat 7+您熟练掌握的编辑工具,推荐使用InterlliJ IDEA 14+开始项目地址git.oschina.net 项目地

SSM(Spring+SpringMVC+Mybatis)框架整合

1.数据准备 SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `admin` -- ---------------------------- DROP TABLE IF EXISTS `admin`; CREATE TABLE `admin` ( `a_id` int(11) NOT NULL AUTO_INCREMENT, `a_name` varchar(20) NOT NULL

【干货理解】理解javascript中实现MVC的原理

理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程序的业务逻辑相关的数据以及对数据处理的方法.模型有对数据直接访问的权利.模型不依赖 "视图" 和 "控制器", 也就是说 模型它不关心页面如何显示及如何被操作. 视图:视图层最主要的是监听模型层上的数据改变,并且实时的更新html页面.当然也包括一些事件的注册或者aja

简单谈谈js中的MVC

MVC是什么? MVC是一种架构模式,它将应用抽象为3个部分:模型(数据).视图.控制器(分发器). 本文将用一个经典的例子todoList来展开(代码在最后). 一个事件发生的过程(通信单向流动): 1.用户在视图 V 上与应用程序交互 2.控制器 C 触发相应的事件,要求模型 M 改变状态(读写数据) 3.模型 M 将数据发送到视图 V ,更新数据,展现给用户 在js的传统开发模式中,大多基于事件驱动的: 1.hash驱动 2.DOM事件,用来驱动视图 3.模型事件(业务模型事件和数据模型事

MVC 插件化框架支持原生MVC的Area和路由特性

.NET MVC 插件化框架支持原生MVC的Area和路由特性 前面开放的源码只是简单的Plugin的实现,支持了插件的热插拔,最近晚上偶然想到,原生的MVC提供Areas和RouteAtrribute等路由特性标签,按照先前的做法,无法解析插件的路由特性和Areas,所以花费了两个晚上的时间,把插件给改进到支持Areas和路由特性,但同时也放弃了Web类插件的热插拔,Func类的插件依然支持热插拔. 下面是实现支持插件使用Areas和路由特性标签的流程: 原生的MVC在启动的时候需要执行两条代