当前位置: 首页 > backend >正文

SpringMVC框架

一、什么是三层架构和MVC模式?

在开始学习SpringMVC之前,我们需要先了解两个基本概念:三层架构和MVC模式。

三层架构

当我们开发服务器端程序时,通常会采用两种形式:C/S架构(客户端/服务器)和B/S架构(浏览器/服务器)。使用Java语言主要开发的是B/S架构程序,而B/S架构又分为三层:

  1. 表现层:WEB层,负责与客户端进行数据交互。表现层一般采用MVC设计模型。

  2. 业务层:处理具体的业务逻辑。

  3. 持久层:负责操作数据库。(增删改查)

MVC模型

MVC全称是Model View Controller(模型-视图-控制器),每个部分各司其职:

  • Model:数据模型,通常是JavaBean类,用于数据封装。

  • View:视图层,如JSP、HTML页面,用于展示数据给用户。

  • Controller:控制器,接收用户请求,控制整个流程,进行数据校验等。

 📌 关系:MVC是表现层的实现方案,三层架构是整个程序的分层。

二、SpringMVC是啥? 

  • 本质:一个帮我们简化Servlet开发的框架(不用写一堆if-else判断请求路径)。

  • 优点:通过注解配置路由,整合Spring容器,开发更高效。

三、SpringMVC入门案例 

 让我们一步步创建一个简单的SpringMVC应用:

创建WEB工程,引入开发的jar包

具体的坐标如下

 <!-- 版本锁定 --><properties><spring.version>5.0.2.RELEASE</spring.version></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency>
​<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency>
​<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency>
​<dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency>
​<dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope></dependency></dependencies>

 编写index.jsp页面

 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>入门程序</title>
</head>
<body>
​<%--超链接--%>
​<h3>入门</h3>
​<a href="/hello.do" >入门程序</a>
​
</body>
</html>

编写suc.jsp页面,路径为:/WEB-INF/pages/suc.jsp

 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>成功</title>
</head>
<body><h3>入门成功了2...</h3></body>
</html>
​

 编写Controller类和方法

package cn.tx.demo1;
​
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
​
/***  * * 控制器类,处理用户的请求*/
// 把当前类交给IOC容器进行管理
@Controller
public class HelloController {
​/*** 处理超链接发送出来的请求* @return*/// 配置映射的配置@RequestMapping(path = "/hello.do")public String sayHello(){
​System.out.println("入门方法执行了2...");
​// 跳转的JSP页面的路径,默认使用的是请求的转发// return "/WEB-INF/pages/suc.jsp";
​// 配置了视图解析器后,写法return "suc";}
​
}

配置核心的控制器(配置DispatcherServlet)

在web.xml配置文件中核心控制器DispatcherServlet


<!--配置前端控制器--><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--加载springmvc.xml配置文件,配置的是Spring配置--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!--配置启动加载--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping>

编写springmvc.xml的配置文件

 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 配置spring创建容器时要扫描的包 --><context:component-scan base-package="com.qcbyjy"></context:component-scan><!-- 配置视图解析器 --><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/pages/"></property><property name="suffix" value=".jsp"></property></bean><!-- 配置spring开启注解mvc的支持 <mvc:annotation-driven></mvc:annotation-driven>-->
</beans>

启动Tomcat服务器,进行测试

执行流程分析

  1. 用户点击链接 → http://localhost:8080/hello.do

  2. Tomcat收到请求,交给DispatcherServlet处理。

  3. DispatcherServlet查地图(@RequestMapping)找到HelloControllersayHello()方法。

  4. 方法执行后返回"suc" → 视图解析器拼接成/WEB-INF/pages/suc.jsp

  5. JSP渲染后返回给用户。

SpringMVC官方提供图形

入门案例中的组件分析

  1. 前端控制器(DispatcherServlet)
  2. 处理器映射器(HandlerMapping)
  3. 处理器(Handler)
  4. 处理器适配器(HandlAdapter)
  5. 视图解析器(View Resolver)
  6. 视图(View)

 

 四、RequestMapping注解

RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系

RequestMapping注解可以作用在方法和类上

  1. 作用在类上:第一级的访问目录
  2. 作用在方法上:第二级的访问目录
  3. 细节:路径可以不编写 / 表示应用的根目录开始

RequestMapping的属性

  1. path 指定请求路径的url
  2. value value属性和path属性是一样的
  3. mthod 指定该方法的请求方式
  4. params 指定限制请求参数的条件
 
package cn.tx.demo1;
​
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
​
/***  * 7* 角色模块的类*/
@Controller
@RequestMapping(path = "/role")        // 一级请求路径
public class RoleController {
​/*** /role/save.do* method="当前方法允许请求方式能访问"* params="请求路径上传参数"* @return*/@RequestMapping(path = "/save.do",method = {RequestMethod.GET},params = "username")public String save(){System.out.println("保存角色...");return "suc";}
​@RequestMapping(value = "/delete.do")public String delete(){System.out.println("删除角色...");return "suc";}
​
}

 五、请求参数的绑定

 SpringMVC提供了强大的请求参数绑定功能,可以将请求参数自动绑定到方法参数上。

请求参数的绑定说明

  1. 绑定机制

    1. 表单提交的数据都是k=v格式的 username=haha&password=123
    2. SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
    3. 要求:提交表单的name和参数的名称是相同的
  2. 支持的数据类型

    1. 基本数据类型和字符串类型
    2. 实体类型(JavaBean)
    3. 集合数据类型(List、map集合等)

基本数据类型和字符串类型

  1. 提交表单的name和参数的名称是相同的
  2. 区分大小写

实体类型(JavaBean)

  1. 提交表单的name和JavaBean中的属性名称需要一致
  2. 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如:address.name

给集合属性数据封装

  1. JSP页面编写方式:list[0].属性

 1. 基本数据类型和字符串类型

@RequestMapping("/save1.do")
public String save(String username, Integer age) {System.out.println("姓名:"+username);System.out.println("年龄:"+age);return "suc";
}

表单的name属性需要与方法参数名称一致。

 2. 绑定到JavaBean对象

@RequestMapping("/save2.do")
public String save2(User user) {System.out.println("user对象:"+user);return "suc";
}

表单的name属性需要与JavaBean中的属性名称一致。如果JavaBean包含其他引用类型,可以使用"对象.属性"的形式,如address.money。

3. 绑定到集合类型 

 对于集合类型,可以使用以下形式:

<input type="text" name="list[0].money" />
<input type="text" name="list[1].money" />
<input type="text" name="addressMap['home'].province" /><br/>
<input type="text" name="addressMap['home'].city" /><br/>

完整的案例如下:

jsp代码

<%--Created by IntelliJ IDEA.User: DellDate: 2025/4/27Time: 16:46To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>请求参数绑定</title>
</head>
<body><h3>请求参数绑定入门</h3><form action="/user/save1.do" method="post">姓名:<input type="text" name="username" /><br/>年龄:<input type="text" name="age" /><br/><input type="submit" value="提交" /></form><h3>请求参数绑定(封装到实体类)</h3>​<form action="/user/save2.do" method="post">姓名:<input type="text" name="username" /><br/>年龄:<input type="text" name="age" /><br/><input type="submit" value="提交" /></form><h3>请求参数绑定(封装到实体类)</h3>​<form action="/user/save3.do" method="post">姓名:<input type="text" name="username" /><br/>年龄:<input type="text" name="age" /><br/>金额:<input type="text" name="address.money" /><br/><input type="submit" value="提交" /></form><h3>请求参数绑定(封装到实体类,存在list集合)</h3>​<form action="/user/save4.do" method="post">姓名:<input type="text" name="username" /><br/>年龄:<input type="text" name="age" /><br/>金额:<input type="text" name="address.money" /><br/>​集合:<input type="text" name="list[0].money" /><br/>集合:<input type="text" name="list[1].money" /><br/><input type="submit" value="提交" /></form><h3>请求参数绑定</h3><form action="/user/save5.do" method="post">姓名:<input type="text" name="username" /><br/>年龄:<input type="text" name="age" /><br/>日期:<input type="text" name="birthday"><br/><input type="submit" value="提交" /></form><h3>请求参数绑定(封装到实体类,包含 Map)</h3><form action="/user/save7.do" method="post">姓名:<input type="text" name="username" /><br/>年龄:<input type="text" name="age" /><br/>日期:<input type="text" name="birthday"><br/>家庭地址-省份:<input type="text" name="addressMap['home'].province" /><br/>家庭地址-城市:<input type="text" name="addressMap['home'].city" /><br/>公司地址-省份:<input type="text" name="addressMap['company'].province" /><br/>公司地址-城市:<input type="text" name="addressMap['company'].city" /><br/><input type="submit" value="提交" /></form><h3>使用Servlet原生的API</h3><a href="/user/save6.do">Servlet原生的API</a></body>
</html>

Javabean代码

package cn.tx.demo2;import org.springframework.format.annotation.DateTimeFormat;import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;public class User implements Serializable {private String username;private  Integer age;//日期// 2000-11-11 格式的日期不能进行转换了,开发使用还是比较多,比较简单
//    @DateTimeFormat(pattern = "yyyy-MM-dd")private Date birthday;//引用对象private Address address;private List<Address> list;//mapprivate Map<String,Address> addressMap;@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", age=" + age +", birthday=" + birthday +", address=" + address +", list=" + list +", addressMap=" + addressMap +'}';}public Map<String, Address> getAddressMap() {return addressMap;}public void setAddressMap(Map<String, Address> addressMap) {this.addressMap = addressMap;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}public List<Address> getList() {return list;}public void setList(List<Address> list) {this.list = list;}
}package cn.tx.demo2;import java.io.Serializable;public class Address implements Serializable {private String city;private String province;private Double money;public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}@Overridepublic String toString() {return "Address{" +"city='" + city + '\'' +", province='" + province + '\'' +", money=" + money +'}';}
}

controller代码

package cn.tx.demo2;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;@Controller
@RequestMapping("/user")
public class UserController {/*** 请求参数的绑定* @return*/@RequestMapping("/save1.do")public String save(String username,Integer age){System.out.println("姓名"+username);System.out.println("年龄:"+age);return "suc";}/*** 请求参数的绑定* @return*/@RequestMapping("/save2.do")public String save2(User user){System.out.println("user对象:"+user);return "suc";}/*** 请求参数的绑定* @return*/@RequestMapping("/save3.do")public String save3(User user){System.out.println("user对象:"+user);return "suc";}/*** 请求参数的绑定* @return*/@RequestMapping("/save4.do")public String save4(User user){System.out.println("user对象:"+user);return "suc";}/*** 请求参数的绑定* @return*/@RequestMapping("/save5.do")public String save5(User user){System.out.println("user对象:"+user);return "suc";}/*** 测试map参数绑定* @return*/@RequestMapping("/save7.do")public String save7(User user){System.out.println("User with map:" +user);return "suc";}/*** 原生的API* @return*/@RequestMapping("/save6.do")public String save6(HttpServletRequest request, HttpServletResponse response){System.out.println(request);// 获取到HttpSession对象HttpSession session = request.getSession();System.out.println(session);System.out.println(response);return "suc";}}

请求参数中文乱码的解决

在web.xml中配置Spring提供的过滤器类

   <!-- 配置过滤器,解决中文乱码的问题 --><filter><filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

自定义类型转换器

第一种方式使用DateTimeFormat注解的方式
package cn.tx.demo2;import org.springframework.format.annotation.DateTimeFormat;import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;public class User implements Serializable {private String username;private  Integer age;//日期// 2000-11-11 格式的日期不能进行转换了,开发使用还是比较多,比较简单@DateTimeFormat(pattern = "yyyy-MM-dd")private Date birthday;//引用对象private Address address;private List<Address> list;//mapprivate Map<String,Address> addressMap;@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", age=" + age +", birthday=" + birthday +", address=" + address +", list=" + list +", addressMap=" + addressMap +'}';}public Map<String, Address> getAddressMap() {return addressMap;}public void setAddressMap(Map<String, Address> addressMap) {this.addressMap = addressMap;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}public List<Address> getList() {return list;}public void setList(List<Address> list) {this.list = list;}
}
第二种方式,自定义类型转换器。如果想自定义数据类型转换,可以实现Converter的接口

自定义类型转换器 

package cn.tx.demo2;import org.springframework.core.convert.converter.Converter;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class StringToDate implements Converter<String,Date> {public Date convert(String s) {// 判断if (s == null) {throw new RuntimeException("请输入内容");}// 进行转换SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");try {// 进行转换return sdf.parse(s);} catch (ParseException e) {throw new RuntimeException(e);}}
}

注册自定义类型转换器,在springmvc.xml配置文件中编写配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 配置spring创建容器时要扫描的包 --><context:component-scan base-package="cn.tx"></context:component-scan><!-- 配置视图解析器 --><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/pages/"></property><property name="suffix" value=".jsp"></property></bean><!--配置日期类型转换器,类型转换器的组件,把日期类型转换注入到组件对象中--><bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"><property name="converters"><set><bean class="cn.tx.demo2.StringToDate" /></set></property></bean><!--让映射器、适配器和处理器生效(默认不配置也是可以的)--><mvc:annotation-driven conversion-service="conversionService"/><!--配置spring开启注解mvc的支持--><!--<mvc:annotation-driven></mvc:annotation-driven>-->
</beans>

在控制器中使用原生的ServletAPI对象

只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象
 /*** 原生的API* @return*/@RequestMapping("/save6.do")public String save6(HttpServletRequest request, HttpServletResponse response){System.out.println(request);// 获取到HttpSession对象HttpSession session = request.getSession();System.out.println(session);System.out.println(response);return "suc";}

测试

 

http://www.xdnf.cn/news/2413.html

相关文章:

  • 二、Web服务常用的I/O操作
  • HTML5 新特性详解:语义化标签、表单与音视频嵌入
  • pytorch写张量pt文件,libtorch读张量pt文件
  • 网络基础概念
  • HCIP知识点总结思维导图
  • Redis远程链接应用案例
  • 【计算机网络物理层】从信号传输到介质选型的核心技术解析
  • Web服务器技术选型指南:主流方案、核心对比与策略选择
  • 数据可视化 —— 饼图
  • 《MySQL 技术内幕-innoDB 存储引擎》笔记
  • 简述删除一个Pod流程?
  • HTTP:十二.HTTPS
  • UE 新建一个自带光照的场景
  • Git常用命令简明教程
  • 【每日随笔】文化属性 ① ( 天机 | 强势文化与弱势文化 | 文化属性的形成与改变 | 强势文化 具备的特点 )
  • 有源晶振输出匹配电阻选择与作用详解
  • AUTOSAR_Feature_Model_Analysis
  • 近期有哪些断链危机?如何提升供应链风险管理能力?
  • 头歌实训之游标触发器
  • 【Jupyter 启动时如何指定目录】
  • Android开机动画资源包制作(测试使用)
  • 数据库3,
  • 使用wavesurferJs实现录音音波效果
  • 突破常规:探索无 get 方法类设计的独特魅力
  • 1、Linux操作系统下,ubuntu22.04版本切换中英文界面
  • Spring security详细上手教学(三)密码管理
  • 基于STM32、HAL库的HX710A模数转换器ADC驱动程序设计
  • 【PyCharm- Python- ArcGIS】:安装一个和 ArcGIS 不冲突的独立 Python让PyCharm 使用 (解决全过程记录)
  • 树莓派超全系列教程文档--(44)如何在树莓派上编译树莓派内核
  • 详解 Unreal Engine(虚幻引擎)