注:本文不包含怎么配置 idea ssm 项目,仅做个人向配置好之后,对于各个文件的分析及跳转之间的的浅解析(之前照着配的文章找不到了qwq)。
叠甲:新手,刚学,不太会,如有错请指出,谢谢!
目录



先逐段分析,最后会给出我的配置文件。
注意:jdk 不要用 17.0.2 版本的,spring 会报错(版本太高的锅,不过现在是 2022 年 11 月 24 日,可能以后就能用了)
注意*2:我的数据库连接池用的是 c3p0(只用知道是数据库连接池的一种,了解到这里就行了)
仔细看看这个配置文件,应该没有什么看不懂的配置包吧 然后结合代码说一下那个 resources 标签:配置的时候会加载你列出来的 directory 里的 xml,properties 文件 ,你看那个
- "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.0modelVersion>
-
- <groupId>org.examplegroupId>
- <artifactId>spring_demoartifactId>
- <version>1.0-SNAPSHOTversion>
- <build>
- <resources>
- <resource>
- <directory>src/main/javadirectory>
- <includes>
- <include>**/*.propertiesinclude>
- <include>**/*.xmlinclude>
- includes>
- <filtering>falsefiltering>
- resource>
- <resource>
- <directory>src/main/resourcesdirectory>
- <includes>
- <include>**/*.propertiesinclude>
- <include>**/*.xmlinclude>
- includes>
- <filtering>falsefiltering>
- resource>
- resources>
- build>
-
- <dependencies>
-
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.12version>
- dependency>
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>5.1.47version>
- dependency>
-
- <dependency>
- <groupId>com.mchangegroupId>
- <artifactId>c3p0artifactId>
- <version>0.9.5.2version>
- dependency>
-
-
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>servlet-apiartifactId>
- <version>2.5version>
- dependency>
- <dependency>
- <groupId>javax.servlet.jspgroupId>
- <artifactId>jsp-apiartifactId>
- <version>2.2version>
- dependency>
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>jstlartifactId>
- <version>1.2version>
- dependency>
-
-
- <dependency>
- <groupId>org.mybatisgroupId>
- <artifactId>mybatisartifactId>
- <version>3.5.2version>
- dependency>
- <dependency>
- <groupId>org.mybatisgroupId>
- <artifactId>mybatis-springartifactId>
- <version>2.0.2version>
- dependency>
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-webmvcartifactId>
- <version>5.3.20version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-jdbcartifactId>
- <version>5.3.20version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-coreartifactId>
- <version>5.3.20version>
- dependency>
- dependencies>
-
- project>
这个项目应该是创建时直接选择的 maven + spring mvc 架构。
先从 web.xml 看起,这是整个项目的入口,因为是 ssm 项目,所以在 web.xml 里配置的是 spring 相关的环境。而mybatis,view 之类的都交给 spring 去管,这个后面再说。
带有
看
- <servlet>
- <servlet-name>dispatcherservlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
- <init-param>
- <param-name>contextConfigLocationparam-name>
-
- <param-value>classpath:applicationContext.xmlparam-value>
- init-param>
- <load-on-startup>1load-on-startup>
- servlet>
这样,
首先是名字。这个名字一定要是上面你配过的 servlet 的名字之一(你可能配好多 servlet),而且这个 mapping 和 servlet 的先后顺序不能颠倒,得先有东西,再有东西的使用范围吧?
- <servlet-mapping>
- <servlet-name>dispatcherservlet-name>
- <url-pattern>*.dourl-pattern>
- <url-pattern>*.inurl-pattern>
- servlet-mapping>
-
- <filter>
- <filter-name>encodingFilterfilter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
- <init-param>
- <param-name>encodingparam-name>
- <param-value>utf-8param-value>
- init-param>
- <init-param>
- <param-name>forceEncodingparam-name>
- <param-value>trueparam-value>
- init-param>
- filter>
过滤器对应的转发器,可以看到它的作用对象是刚才的转发器名,这里根据自己的也要配好。
- <filter-mapping>
- <filter-name>encodingFilterfilter-name>
- <servlet-name>dispatcherservlet-name>
- filter-mapping>
web.xml 文件:
- "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">
-
-
- <filter>
- <filter-name>encodingFilterfilter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
- <init-param>
- <param-name>encodingparam-name>
- <param-value>utf-8param-value>
- init-param>
- <init-param>
- <param-name>forceEncodingparam-name>
- <param-value>trueparam-value>
- init-param>
- filter>
- <filter-mapping>
- <filter-name>encodingFilterfilter-name>
- <servlet-name>dispatcherservlet-name>
- filter-mapping>
- <servlet>
- <servlet-name>dispatcherservlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
- <init-param>
- <param-name>contextConfigLocationparam-name>
-
- <param-value>classpath:applicationContext.xmlparam-value>
- init-param>
- <load-on-startup>1load-on-startup>
- servlet>
- <servlet-mapping>
- <servlet-name>dispatcherservlet-name>
- <url-pattern>*.dourl-pattern>
- <url-pattern>*.inurl-pattern>
- servlet-mapping>
- web-app>
web.xml配置好了,接下来的配置文件就都放在 resources 目录下了。
前面也说了,web.xml 是对整个项目的配置,而 spring 相关的文件是资源文件,自然放到资源目录下。
接下来看 application.xml ,曾记否?它首次出现是在配置 spring 的转发器 distacher 中,作为它的初始化文件路径出现的,现在我们来看看它的结构。
我这里使用的是
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd">
-
- <import resource="spring/spring-dao.xml"/>
- <import resource="spring/spring-service.xml"/>
- <import resource="spring/spring-mvc.xml"/>
-
- beans>
DAO(Data Access Object)是一个数据访问接口,数据访问:顾名思义就是与数据库打交道。
所以这个配置文件就相当于 mybatis 中的 mybatis-config.xml,用来配置与数据库的连接。
使用的是配置文件的方式来决定数据库,所以这样写。
数据库连接池的部分我也是抄的,结合注释能看个89不离10,也不解释了;
直接看 sqlSessionFactory 部分。这个在学 mybatis 的时候应该有印象,当时好像还要手动在 Java 类里获取 sqlSessionFactory 吧,你看现在在这里配置即可。我放在 mybatis-config.xml 文件里写了,想想 sqlSessionFactory 也就是要获取对象的位置和映射文件的位置,对不对?
下面那个获得映射文件是我报错找不到之后加上去的,现在想想,是不是可以直接修改 mybatis-config.xml 里的数值呢。
第四点就是将这个 mybatis 的设置统合到 spring 的管理之下啦。
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- https://www.springframework.org/schema/context/spring-context.xsd">
-
-
-
- <context:property-placeholder location="classpath:db.properties"/>
-
-
-
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
-
- <property name="driverClass" value="${jdbc.driver}"/>
- <property name="jdbcUrl" value="${jdbc.url}"/>
- <property name="user" value="${jdbc.username}"/>
- <property name="password" value="${jdbc.password}"/>
-
-
- <property name="maxPoolSize" value="30"/>
- <property name="minPoolSize" value="10"/>
-
- <property name="autoCommitOnClose" value="false"/>
-
- <property name="checkoutTimeout" value="10000"/>
-
- <property name="acquireRetryAttempts" value="2"/>
- bean>
-
-
- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
-
- <property name="dataSource" ref="dataSource"/>
-
- <property name="configLocation" value="classpath:mybatis-config.xml"/>
- <property name="mapperLocations" value="classpath:/com/test/**/*.xml"/>
- bean>
-
-
-
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
-
- <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
-
- <property name="basePackage" value="com.test.dao"/>
- bean>
- beans>
- "1.0" encoding="UTF-8" ?>
- configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <typeAliases>
- <package name="com.test.pojo"/>
- typeAliases>
-
- <mappers>
- <package name="com.test.dao"/>
- mappers>
-
- configuration>
useSSL=false 是因为我配置 MySQL 的时候就开启了免密登录,你如果也开启了的话这里一定要写 false,不然后面会报错~
因为配了免密登录,所以密码随便写了
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/(你的数据库名)?useSSL=false&useUnicode=true&characterEncoding=utf8
- jdbc.username=root
- jdbc.password=root
mvc mvc,就是要处理视图层!
1.注解就算不会用也见别人用过吧,@RequestMapping 什么的
2.注解的意思能看个大概后,照抄即可
3.这个就是到时候一个请求结束后,可能会跳到一个界面,那这个界面在哪找?就按这里的规则找:prefix 是前缀,也就是返回界面的目录,这里我直接写到 web 主目录下了,所以可以不写,有的是 WEB/INF,就是说页面在 WEB/INF 这个路径下。
suffix 是后缀,就是到时候如果我返回一个以 loginOK 为文件名的字符串,再加上这个后缀就是 loginOK.jsp 了,这个系统给你组装好之后,就是说在 prefix 指定的目录下,结合你自己返回的文件名再加上 suffix 找文件。
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/mvc
- https://www.springframework.org/schema/mvc/spring-mvc.xsd">
-
-
-
- <mvc:annotation-driven />
-
- <mvc:default-servlet-handler/>
-
-
- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
- <property name="prefix" value=""/>
- <property name="suffix" value=".jsp" />
- bean>
-
-
- <context:component-scan base-package="com.nxn.controller" />
-
- beans>
service 是什么的 service?想想结合数据库后就是增删改查,那肯定是针对数据库的操作。所以service 是对数据库的服务。
再想想纯用 mybatis 的时候,是不是先定义一个接口,由接口对应 xml 映射文件,再写一个接口实现类写具体的逻辑?这里就是那个意思,只不过这次不用你自己去调用 sqlSessionFactory 初始化接口了,你在这里配好,spring 帮你初始化,这就是所谓的 service。
事务管理器和数据库连接池那个看个大概然后 CTRL CV 就行了(狗头)
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd">
-
-
- <context:component-scan base-package="com.test.service" />
-
-
- <bean id="userServiceImpl" class="com.test.service.UserServiceImpl">
- <property name="UserDao" ref="userDao"/>
- bean>
- <bean id="messageServiceImpl" class="com.test.service.MessageServiceImpl">
- <property name="MessageDao" ref="messageDao"/>
- bean>
-
-
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
-
- <property name="dataSource" ref="dataSource" />
- bean>
-
- beans>
先剧透一下,bean id 那里不是胡写的,要和 controller 里的注解名对应上才行。
- @Autowired
- @Qualifier("userServiceImpl")
- private UserService userService;
你看,和 mybatis 那里无差,这个就略过了。



这里你可能就有点迷糊了,怎么这个 userService 类和上面数据库操作的 dao 类是一样的呢?还有实现类,这不是重复了吗?听我讲完,这是有逻辑在里面的。
首先 userService 这个接口要实现登录功能,所以这么写是没问题的,代码重复的问题先放一下;其次你看接口的实现类。它的确是实现了接口的方法,但是你看它的成员变量是什么?虽然代码一样,但是它是 dao 层控制数据库的 userDao 而不是 userService,而方法是怎么实现的?是使用在配置文件中注入的 userDao,借助它调用的 dao 层的方法,从而使用 xml 映射完成的对数据库的操作!
还记得吗?spring-service.xml 文件里,你在这里让 spring 帮你注入 userDao
在 spring-mvc.xml 里,你配置的 controller
说白了,userService 就是 mybatis 里接口实现类的套皮。因为按 mvc 的转发规则, controller 就是把请求的操作转给 service 处理,service 虽然不得不处理,但是它哪儿会啊?它一个 service 层怎么控制数据库呢?这时候就要交给能接触到数据库层的 userDao 了。service不会,但是 service 可以 new 一个 dao 的对象,用 dao 的对象调用 dao 的方法,获得数据库那边返回的结果,然后就当是它自己的结果(有点鸠占鹊巢那味了),之后把这个结果返回 controller,让 controller 根据结果再做决定。
所以差别就在这里,service 里的代码虽然和 dao 层有重复,但是就只是调用了下数据库的操作,之后就去处理了下自己的逻辑了,因为转发规则让他不得不处理数据库的东西,所以这部分代码虽然有点重复,还真不能删。
userController 类,@Controller 注解表示它的身份接收 service 返回的结果并做处理,根据不同的情况选择不同的文件名返回。
目录和后缀在 prefix 和 suffix 中配了,所以没事;userServiceImpl 也在之前的 xml 文件里配好了。
requestMapping 里的值和 login.jsp 里的 form action 保持一致,就能找到该方法。
- package com.test.controller;
-
- import org.apache.ibatis.annotations.Param;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Qualifier;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import com.test.service.UserService;
-
- @Controller
- public class UserController
- {
- @Autowired
- @Qualifier("userServiceImpl")
- private UserService userService;
- @RequestMapping("/login.in")
- public String login(@Param("userName") String userName, @Param("password") String password)
- {
- if (userService.login(userName, password) != null) {
- return "leaveMessage";
- }
- return "login";
- }
- }
到此为止,全部文件就都解析了一遍了,接下来以具体的请求为例,看看请求是怎么走的。
逻辑:用户尝试登录,若数据库里有这个用户就跳转到留言界面,留言后将留言插入到数据库中并返回留言界面,否则就回到登录界面...
启动 tomcat,如图
login.jsp提交逻辑(注意看,在配置转发器的时候标注了拦截.in 结尾的类型的请求):
![]()
所以该请求会被处理,输入用户名和密码后跳转到 controller里(假设用户名和密码是正确的,其实无所谓,逻辑处理是类似的),看到这个方法上的值和 login 里的是一样的,所以好的,确认是这个方法来处理这个表单的请求。
controller 调用 userService 来处理这个请求,而 userService 是接口,调用它的方法就是调用接口实现类的方法,所以调用的是这个方法。(userDao)是在spring-mvc.xml 中 spring 注入的,有点多态的感觉:
userService 的实现类里,为了访问数据库,它让自己的 userDao 查下数据库,查到一个 user 对象,返回之(因为是正确的用户名和密码,所以能查到对应的实体类);
现在再回到 userService,看代码,我们拿到了非空的对象,所以返回“leaveMessage”。
mvc 视图层给我们加上前后缀,找到一个文件:
然后在相应的页面上也跳转了过来,此时显示的是 leaveMessage.jsp,form action 如下:
输入数据(夹带私货是吧:
点提交,就会走相似的路,这次把这条留言插到数据库里。
查看数据库,发现的确进去了。
好了,这个项目我解析完了。