在 Web 开发的世界里,SpringMVC 是一个极为重要的框架,它能够帮助我们构建高效、灵活的 Web 应用程序。
一、MVC 设计理念
MVC,即 Model - View - Controller,是一种将软件系统划分为三个主要部分的设计模式。它的出现旨在实现各部分之间的解耦,提高代码的可维护性和可扩展性。
(一)Model(模型层)
模型层负责处理数据逻辑,包括数据的存储、检索和更新。在 Java Web 开发中,通常使用 JavaBean 来实现模型层,这些 JavaBean 可以是实体类,用于映射数据库中的表结构,也可以是业务逻辑类,包含了与业务相关的数据处理方法。例如,在一个用户管理系统中,可能会有一个 User 实体类,用于存储用户的信息,如用户名、密码、邮箱等,同时还可能会有一个 UserService 类,用于处理用户的注册、登录、查询等业务逻辑。
(二)View(视图层)
视图层主要负责与用户进行交互,展示数据给用户,并接收用户的输入。常见的视图技术包括 JSP、HTML、Thymeleaf 等。视图层只关注数据的展示,不涉及业务逻辑的处理,它通过与控制器的交互来获取需要展示的数据,并将用户的输入传递给控制器。例如,在一个 Web 应用中,用户登录页面就是视图层的一部分,它接收用户输入的用户名和密码,并将这些信息提交给控制器进行处理。
(三)Controller(控制层)
控制层作为模型层和视图层之间的桥梁,负责接收用户的请求,调用模型层的业务逻辑方法进行数据处理,并根据处理结果选择合适的视图进行展示。在 SpringMVC 中,控制器通常是一个简单的 Java 类,使用注解来定义请求映射和处理方法。例如,当用户在登录页面提交登录请求时,控制器会接收到该请求,调用用户服务层的登录方法进行验证,如果验证成功,可能会跳转到用户主页视图,否则可能会返回登录页面并显示错误信息。
二、SpringMVC 框架概述
SpringMVC 是 Spring 框架的一个重要模块,它基于 MVC 设计模式,提供了一种优雅、灵活的方式来构建 Web 应用程序。它的主要作用是处理 HTTP 请求,将请求映射到相应的控制器方法,并处理方法的返回结果,最终将响应返回给客户端。
(一)SpringMVC 的优势
- 清晰的角色划分:SpringMVC 严格遵循 MVC 设计模式,使得模型、视图和控制器之间的职责明确,易于理解和维护。
- 强大的配置灵活性:可以通过 XML 配置或注解的方式进行配置,适应不同的开发需求和风格。
- 高效的请求处理:采用了前端控制器模式,能够统一处理请求,提高了处理效率。
- 丰富的功能支持:支持数据验证、数据绑定、文件上传、国际化等多种功能,大大减少了开发工作量。
(二)SpringMVC 的核心组件
- DispatcherServlet(前端控制器):作为整个 SpringMVC 框架的核心,它负责接收所有的 HTTP 请求,并将请求分发给相应的控制器进行处理。
- HandlerMapping(处理器映射器):根据请求的 URL 路径,将请求映射到对应的控制器方法上。
- Controller(控制器):处理具体的业务逻辑,调用模型层的方法进行数据处理,并返回视图名称或模型数据。
- ModelAndView(模型和视图):用于封装控制器处理后的模型数据和视图名称,以便视图解析器进行视图渲染。
- ViewResolver(视图解析器):根据视图名称解析出对应的视图对象,如 JSP 页面、HTML 页面等。
三、SpringMVC 的使用步骤
(一)创建 Maven 项目并引入依赖
在项目的 pom.xml 文件中,添加 SpringMVC 的相关依赖,例如:
<dependencies>
<!--springmvc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
</dependencies>
(二)创建 SpringMVC 配置文件
配置文件中主要包含以下内容:
- 包扫描:指定需要扫描的控制器类所在的包,以便 Spring 能够自动发现并注册控制器。
<context:component-scan base-package="com.lyk.controller"/>
- 开启注解驱动:启用 SpringMVC 的注解功能,如 @RequestMapping 等注解。
<mvc:annotation-driven/>
- 视图解析器配置:设置视图的前缀和后缀,方便视图解析器根据控制器返回的视图名称找到对应的视图文件。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/views/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
(三)注册 DispatcherServlet
在 web.xml 文件中注册 DispatcherServlet,并指定其加载的配置文件路径。
<?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">
<servlet>
<servlet-name>spring01</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载spring配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring01.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring01</servlet-name>
<!--访问任何路径都会经过servlet-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
(四)编写控制器类
控制器类使用 @Controller 注解进行标识,并通过 @RequestMapping 注解定义请求映射路径。
@Controller
@RequestMapping("/book")
public class BookController {
@RequestMapping("/index")
public String index() {
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~");
return "hello";
}
@RequestMapping("/add")
public String add() {
System.out.println("************************");
return "add";
}
}
四、SpringMVC 的工作流程
- 客户端发起 HTTP 请求,请求到达 Tomcat 服务器。
- SpringMVC 的前端控制器 DispatcherServlet 接收到所有请求。
- DispatcherServlet 根据请求的 URL 路径,通过 HandlerMapping 查找对应的控制器方法。
- 执行找到的控制器方法,方法执行完毕后返回一个视图名称或模型数据。
- 如果返回的是视图名称,视图解析器会根据视图名称和配置的前缀、后缀拼接出完整的视图路径,找到对应的视图文件(如 JSP 页面)。
- 将视图进行渲染,将模型数据填充到视图中,最终将渲染后的页面响应给客户端。
五、处理静态资源
在 Web 应用中,静态资源(如 JavaScript、CSS、图片等)的正确加载非常重要。默认情况下,SpringMVC 会拦截所有请求,包括静态资源路径,这可能导致静态资源无法正常访问。为了解决这个问题,需要在 SpringMVC 配置文件中添加以下配置来放行静态资源:
<mvc:default-servlet-handler/>
六、接受请求参数
(一)接受少量参数
对于少量简单参数,可以直接在控制器方法的参数列表中定义,参数名必须与请求参数名一致。例如:
@RequestMapping("/index")
public String index(int id, String name) {
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("id===>" + id + ";name====>" + name);
return "hello";
}
(二)接受大量参数
当需要接受大量参数时,建议封装一个实体类,实体类的属性名要与请求参数名一致。例如:
@RequestMapping("/add")
public String add(User user) {
System.out.println("user===>" + user);
return "add";
}
(三)解决乱码问题
在处理请求参数时,可能会遇到中文乱码问题。解决方法是使用过滤器,在过滤器中设置请求和响应的字符编码为 UTF - 8。例如:
@WebFilter(urlPatterns = "/*")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
(四)处理日期参数
如果请求参数中包含日期类型,需要使用 @DateTimeFormat 注解进行格式化,指定日期的格式。例如:
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;