视频链接:
【狂神说Java】SpringMVC最新教程IDEA版通俗易懂
什么是Spring MVC?
是Spring框架的一部分,是一个基于Java的Web开发框架,遵循经典的MVC设计模式。它通过分离应用程序的输入逻辑、业务逻辑和显示逻辑,帮助开发者构建灵活、可扩展且易于维护的Web应用程序。
MVC模式:
- Model(模型):负责处理数据和业务逻辑,通常由JavaBean或POJO(Plain Old Java Object)组成,可能涉及服务层(Service)和数据访问层(DAO)。
- View(视图):负责展示数据,支持多种视图技术(如JSP、Thymeleaf、FreeMarker等),通过逻辑视图名称与具体模板关联。
- Controller(控制器):处理用户请求,协调模型和视图。通过注解(如@Controller)标识,并使用@RequestMapping等注解映射HTTP请求到具体方法。
核心组件:
- DispatcherServlet:前端控制器,接收所有请求并分发给对应的处理器(Handler),是Spring MVC的入口。
- HandlerMapping:根据请求URL找到对应的Controller方法(处理器)。
- HandlerAdapter:调用处理器方法,并将结果封装为ModelAndView对象(模型数据+视图名称)。
- ViewResolver:解析逻辑视图名称为具体的视图对象(如JSP页面),并渲染模型数据。
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!--1.注册DispatcherServlet--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!--启动级别-1--><load-on-startup>1</load-on-startup></servlet><!--/ 匹配所有的请求;(不包括.jsp)--><!--/* 匹配所有的请求;(包括.jsp)--><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping><welcome-file-list><welcome-file>/WEB-INF/jsp/welcome.jsp</welcome-file></welcome-file-list><!-- 对请求进行过滤,防止乱码 --><filter><filter-name>encoding</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param></filter><filter-mapping><filter-name>encoding</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>
springmvc-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 处理器映射器 --><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/><!-- 处理器适配器 -->
<!-- <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>--><!-- 替换原来的处理器适配器 --><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/><!-- 启用组件扫描(扫描Service、DAO等包) --><context:component-scan base-package="com.itcast.controller"/><!-- 启用注解驱动(支持@RestController、@RequestBody等) --><mvc:annotation-driven/><!-- 配置静态资源处理 --><mvc:resources mapping="/resources/**" location="/resources/"/><!--视图解析器:DispatcherServlet给他的ModelAndView--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"><!--前缀--><property name="prefix" value="/WEB-INF/jsp/"/><!--后缀--><property name="suffix" value=".jsp"/></bean></beans>
使用Spring MVC框架的流程:
1.用户发送HTTP请求到DispatcherServlet。
<!--1.注册DispatcherServlet-->
<servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!--启动级别-1--><load-on-startup>1</load-on-startup>
</servlet>
<!--/ 匹配所有的请求;(不包括.jsp)-->
<!--/* 匹配所有的请求;(包括.jsp)-->
<servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>
2.DispatcherServlet通过HandlerMapping找到对应的Controller方法(处理器)。
<!-- 处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
/*** 根据bean名称确定处理器的URL路径列表。* 该方法主要用于将bean名称映射到一个或多个URL路径,从而实现请求到正确处理器的路由功能。* * @param beanName bean的名称,可能是以"/"开头的路径* @return 包含所有对应处理器URL路径的字符串数组*/
@Override
protected String[] determineUrlsForHandler(String beanName) {// 初始化用于存储URL路径的集合List<String> urls = new ArrayList<>();// 如果bean名称以"/"开头,则直接将其作为URL路径添加if (beanName.startsWith("/")) {urls.add(beanName);}// 获取bean名称的所有别名,这些别名也可能表示额外的URL路径String[] aliases = obtainApplicationContext().getAliases(beanName);for (String alias : aliases) {// 如果别名以"/"开头,则将其作为URL路径添加if (alias.startsWith("/")) {urls.add(alias);}}// 将URL路径集合转换为数组并返回return StringUtils.toStringArray(urls);
}
3.HandlerAdapter调用处理器方法,处理业务逻辑并返回ModelAndView。
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
/*** 简单的控制器处理器适配器类,实现了HandlerAdapter接口* 该适配器用于处理符合Controller接口的处理器*/
public class SimpleControllerHandlerAdapter implements HandlerAdapter {/*** 检查当前适配器是否支持给定的处理器* * @param handler 需要检查的处理器对象* @return 如果处理器是Controller的实例,则返回true,否则返回false*/@Overridepublic boolean supports(Object handler) {return (handler instanceof Controller);}/*** 处理HTTP请求,并返回ModelAndView对象* * @param request HTTP请求对象,包含请求数据* @param response HTTP响应对象,用于生成响应* @param handler 处理请求的控制器对象* @return ModelAndView对象,包含模型数据和视图信息* @throws Exception 如果处理请求时发生错误,则抛出异常*/@Override@Nullablepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 调用Controller类型处理器的handleRequest方法处理请求,返回ModelAndViewreturn ((Controller) handler).handleRequest(request, response);}/*** 获取处理器的最后修改时间* * @param request HTTP请求对象* @param handler 处理请求的处理器对象* @return 如果处理器实现了LastModified接口,则返回最后修改时间,否则返回-1L*/@Overridepublic long getLastModified(HttpServletRequest request, Object handler) {// 检查处理器是否实现了LastModified接口if (handler instanceof LastModified) {// 调用处理器的getLastModified方法获取最后修改时间return ((LastModified) handler).getLastModified(request);}// 如果处理器未实现LastModified接口,则返回-1Lreturn -1L;}}
4.ViewResolver根据视图名称解析具体的视图资源(如JSP页面)。
5.视图渲染模型数据,生成HTML等响应内容返回给用户。
SSM整合(登录案例)
项目结构
1.配置文件
1.1 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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.itcast</groupId><artifactId>ssm</artifactId><version>1.0-SNAPSHOT</version><name>ssm</name><packaging>war</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.source>1.8</maven.compiler.source><junit.version>5.9.2</junit.version></properties><dependencies><!--Junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><!--数据库驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version> <!-- 根据实际需求选择版本 --></dependency><!-- 数据库连接池 --><!-- 基础依赖 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version> <!-- 根据需要选择版本 --></dependency><!--Servlet - JSP --><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><!--Mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.2</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.2</version></dependency><!--Spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.9.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.1.9.RELEASE</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>RELEASE</version><scope>provided</scope></dependency></dependencies><build><resources><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources></build>
</project>
1.2 web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!--DispatcherServlet--><servlet><servlet-name>DispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>DispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!--encodingFilter--><filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!--Session过期时间--><session-config><session-timeout>15</session-timeout></session-config><welcome-file-list><welcome-file>/WEB-INF/jsp/login.jsp</welcome-file></welcome-file-list>
</web-app>
1.3 applicationContext.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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><import resource="spring-dao.xml"/><import resource="spring-bean.xml"/><import resource="spring-mvc.xml"/>
</beans>
1.4 spring-dao.xml(Spring和MyBatis整合):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!-- 配置整合mybatis --><!-- 1.关联数据库文件 --><context:property-placeholder location="classpath:database.properties"/><!-- 2.数据库连接池 --><!--数据库连接池 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><property name="initialSize" value="1"/><property name="maxActive" value="10"/><property name="minIdle" value="1"/><property name="maxWait" value="6000"/><property name="timeBetweenEvictionRunsMillis" value="6000"/></bean><!-- 3.配置SqlSessionFactory对象 --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 注入数据库连接池 --><property name="dataSource" ref="dataSource"/><!-- 配置MyBaties全局配置文件:mybatis-config.xml --><property name="configLocation" value="classpath:mybatis-config.xml"/></bean><!-- 4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!-- 注入sqlSessionFactory --><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><!-- 给出需要扫描Dao接口包 --><property name="basePackage" value="com.itcast.dao"/></bean>
</beans>
mybatis-config.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><typeAliases><package name="com.itcast.pojo"/></typeAliases><mappers><mapper resource="com/itcast/dao/UserMapper.xml"/></mappers>
</configuration>
database.properties:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
1.5 spring-mvc.xml(Spring和SpringMVC整合):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 1.开启SpringMVC注解驱动 --><mvc:annotation-driven /><!-- 2.静态资源默认servlet配置--><mvc:default-servlet-handler/><!-- 3.配置jsp 显示ViewResolver视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /><property name="prefix" value="/WEB-INF/jsp/" /><property name="suffix" value=".jsp" /></bean><!-- 4.扫描web相关的bean --><context:component-scan base-package="com.itcast.controller" />
</beans>
1.6 spring-bean.xml(Spring配置bean)
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 扫描service相关的bean --><context:component-scan base-package="com.itcast.service" /><!--UserServiceImpl注入到IOC容器中--><bean id="UserServiceImpl" class="com.itcast.service.UserServiceImpl"><property name="userMapper" ref="userMapper"/></bean><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 注入数据库连接池 --><property name="dataSource" ref="dataSource" /></bean>
</beans>
1.7 user表:
create table if not exists user
(id varchar(50) not nullprimary key,username varchar(50) null,password varchar(50) null
);
2.编写pojo实体类层:
package com.itcast.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private String id;private String username;private String password;public User(String username, String password) {this.username = username;this.password = password;}
}
3.编写Dao层
数据库交互层
UserMapper.class:
package com.itcast.dao;import com.itcast.pojo.User;public interface UserMapper {User getUserById(Integer id);User getUserByName(String name);void addUser(User user);User login(User user);
}
UserMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itcast.dao.UserMapper"><select id="getUserById" parameterType="int" resultType="com.itcast.pojo.User">select * from user where id = #{id}</select><select id="getUserByName" parameterType="java.lang.String" resultType="com.itcast.pojo.User">select * from user where username = #{username}</select><select id="login" resultType="com.itcast.pojo.User" parameterType="com.itcast.pojo.User">select * from user where username = #{username} and password = #{password}</select><insert id="addUser" parameterType="com.itcast.pojo.User">insert into user values (#{id},#{username},#{password})</insert>
</mapper>
4.编写Service层:
UserService.interface
package com.itcast.service;import com.itcast.pojo.User;
import org.springframework.ui.Model;public interface UserService {User getUserById(Integer id);User getUserByName(String name);void addUser(User user);String login(Model model, User user);String register(Model model, String username, String password, String confirm);
}
UserServiceImpl.class:
package com.itcast.service;import com.itcast.dao.UserMapper;
import com.itcast.pojo.User;
import org.springframework.ui.Model;import java.util.UUID;public class UserServiceImpl implements UserService{private UserMapper userMapper;public void setUserMapper(UserMapper userMapper) {this.userMapper = userMapper;}/*** 登录* @param model* @param user* @return*/@Overridepublic String login(Model model, User user) {User user1 = userMapper.login(user);if (user1 != null){return "success";}else {model.addAttribute("msg", "用户名或密码错误");return "fail";}}/*** 注册* @param model* @param username* @param password* @param confirm* @return*/@Overridepublic String register(Model model, String username, String password, String confirm) {if (password.equals(confirm)){User user = userMapper.getUserByName(username);if (user == null) {User register = new User(username, password);UUID uuid = UUID.randomUUID();register.setId(uuid.toString());userMapper.addUser(register);return "login";}else {model.addAttribute("msg", "该用户已经注册");return "fail";}}else {model.addAttribute("msg", "两次密码不一致");return "fail";}}
}
6.编写Controller层:
UserController.class
package com.itcast.controller;import com.itcast.pojo.User;
import com.itcast.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/login")public String login(Model model, String username, String password){model.addAttribute("username",username);return userService.login(model, new User(username,password));}@RequestMapping("/register")public String register(Model model, String username, String password, String confirm){return userService.register(model, username, password, confirm);}@RequestMapping("/register_forward")public String forwardRegisterPage() {return "register";}
}
7.Web层界面
login.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登录</title><style>body {font-family: Arial, sans-serif;background-color: #f4f4f9;display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;}form {background-color: #fff;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);}input[type="text"], input[type="password"] {width: 100%;padding: 10px;margin: 10px 0;border: 1px solid #ccc;border-radius: 5px;}input[type="submit"] {background-color: #007bff;color: white;padding: 10px 15px;border: none;border-radius: 5px;cursor: pointer;}input[type="submit"]:hover {background-color: #0056b3;}a {display: block;text-align: center;margin-top: 10px;color: #007bff;text-decoration: none;}a:hover {text-decoration: underline;}</style>
</head>
<body>
<form action="/login" method="post"><div><label for="username">用户名:</label><input type="text" id="username" name="username" required></div><div><label for="password">密码:</label><input type="password" id="password" name="password" required></div><input type="submit" value="登录"><button onclick="window.location.href='/register_forward'">注册</button>
</form></body>
</html>
register.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>注册</title><style>body {font-family: Arial, sans-serif;background-color: #f4f4f9;display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;}form {background-color: #fff;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);width: 300px;}input[type="text"], input[type="email"], input[type="password"], input[type="confirm"] {width: 100%;padding: 10px;margin: 10px 0;border: 1px solid #ccc;border-radius: 5px;}input[type="submit"] {background-color: #28a745;color: white;padding: 10px 15px;border: none;border-radius: 5px;cursor: pointer;width: 100%;}input[type="submit"]:hover {background-color: #218838;}label {display: block;margin-bottom: 5px;font-weight: bold;}</style>
</head>
<body>
<form action="/register" method="post"><div><label for="username">用户名:</label><input type="text" id="username" name="username" required></div><div><label for="password">密码:</label><input type="password" id="password" name="password" required></div><div><label for="confirm">确认密码:</label><input type="confirm" id="confirm" name="confirm" required></div><input type="submit" value="注册">
</form>
</body>
</html>
fail.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Error</title>
</head>
<body>${msg}
</body>
</html>
success.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Success</title>
</head>
<body>登录成功,${username}
</body>
</html>
— Xuan