Spring MVC学习笔记 | 字数总计: 4.6k | 阅读时长: 19分钟 | 阅读量:
Spring MVC学习笔记 视频:黑马 学习时间:2021年3月14日
1 三层架构 1.1 介绍 服务器端分成三层架构:
1.2 MVC模型 MVC的全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,达到减少编码的时间。
V即View
视图是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操纵的方式。
M即Model
模型是指模型,表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
C即Controller
控制器是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。
1.3 SpringMVC概述 SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于 Spring FrameWork 的后续产品,已经融合在 Spring Web Flow 里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用 Spring 进行 WEB 开发时,可以选择使用Spring 的 Spring MVC 框架或集成其他 MVC 开发框架,如 Struts1(现在一般不用),Struts2 等。
SpringMVC 已经成为目前最主流的 MVC 框架之一,并且随着 Spring3.0 的发布,全面超越 Struts2,成为最优秀的 MVC 框架。它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful 编程风格的请求。
2 SpringMVC入门程序 2.1 需求分析
搭建开发环境
编写入门程序
2.2 搭建环境
导入坐标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <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 >
前端拦截器
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 <web-app > <display-name > Archetype Created Web Application</display-name > <servlet > <servlet-name > dispatcherServlet</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > </servlet > <servlet-mapping > <servlet-name > dispatcherServlet</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > </web-app >
配置Tomcat服务器
2.3 代码编写
项目结构
前端代码
index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html > <head > <title > Title</title > </head > <body > <h3 > 入门程序</h3 > <a href ="/hello" > 入门程序</a > </body > </html >
success.jsp
1 2 3 4 5 6 7 8 9 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html > <head > <title > Title</title > </head > <body > <h3 > 入门成功</h3 > </body > </html >
后端代码
HelloController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 @Controller public class HelloController { @RequestMapping(path = "/hello") public String sayHello () { System.out.println("Hello SpringMVC!" ); return "success" ; } }
配置文件
SpringMVC框架的配置文件springmvc.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <context:component-scan base-package ="com.hongyi" > </context:component-scan > <bean id ="internalResourceViewResolver" class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/pages/" > </property > <property name ="suffix" value =".jsp" > </property > </bean > <mvc:annotation-driven > </mvc:annotation-driven > </beans >
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <web-app > <display-name > Archetype Created Web Application</display-name > <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:springmvc.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 > </web-app >
2.4 入门程序流程分析
启动服务器,加载一些配置文件
DispatcherServlet
对象
springmvc.xml
被加载了
HelloController
,InternalResourceViewResolver
被spring创建成单例对象,被Spring的ioc容器管理
发送请求,后台处理请求
流程图如下:
总结:
服务器启动,应用被加载。读取到 web.xml 中的配置创建 spring 容器并且初始化容器中的对象。
浏览器发送请求,被 DispatherServlet
捕获,该 Servlet 并不处理请求,而是把请求转发出去。转发的路径是根据请求 URL,匹配@RequestMapping
中的内容。
匹配到了后,执行对应方法。该方法有一个返回值。
根据方法的返回值,借助 nternalResourceViewResolver
找到对应的结果视图。
渲染结果视图,响应浏览器。
2.5 涉及的组件
DispatcherServlet :前端控制器
用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。
HandlerMapping :处理器映射器
HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
Handler :处理器
它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。
HandlAdapter :处理器适配器
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
View Resolver :视图解析器
View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
View :视图
SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是 jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
<mvc:annotation-driven>
说明
在 SpringMVC 的各个组件中,==处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件==。使 用 <mvc:annotation-driven>
自动加载 RequestMappingHandlerMapping
(处理映射器) 和RequestMappingHandlerAdapter
( 处 理 适 配 器 ) , 可 用 在 SpringMVC.xml
配 置 文 件 中 使 用<mvc:annotation-driven>
替代注解处理器和适配器的配置。
它就相当于在 xml 中配置了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <bean class ="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" > </bean > <bean class ="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" ></bean > <bean class ="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerA dapter" ></bean > <bean class ="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" ></bean > <bean class ="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" ></bean > <bean class ="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExcept ionResolver" ></bean > <bean class ="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolv er" ></bean > <bean class ="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver" > </bean >
2.6 RequestMapping注解
源码
1 2 3 4 5 6 7 @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface RequestMapping { }
作用
用于建立请求 URL 和处理请求方法之间的对应关系。
出现位置
类上:请求 URL 的第一级访问目录。此处不写的话,就相当于应用的根目录。写的话需要以/开头。它出现的目的是为了使我们的 URL 可以按照模块化管理:例如:
1 2 3 4 5 6 7 8 9 账户模块: /account/add /account/update /account/delete ... 订单模块: /order/add /order/update /order/delete
前面的部分就是把RequsetMappding
写在类上,使我们的 URL 更加精细。
方法上:请求 URL 的第二级访问目录。
代码演示:
1 <a href="/user/testRequestMapping" >RequestMapping注解</a>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Controller @RequestMapping(path = "/user") public class HelloController { @RequestMapping(path = "/hello") public String sayHello () { System.out.println("Hello SpringMVC!" ); return "success" ; } @RequestMapping(path = "/testRequestMapping") public String testRequestMapping () { System.out.println("测试RequestMapping注解..." ); return "success" ; } }
RequestMapping
注解的属性
value
:用于指定请求的 URL。它和 path 属性的作用是一样的。当只有一个value或path属性时可以省略,否则不能省略。
1 @RequestMapping("/hello")
1 @RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})
params
:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。例如:
1 2 params = {"accountName" } params = {"moeny!100" }
注意:以上4个属性只要出现 2 个或以上时,他们的关系是与的关系。
3 请求参数的绑定 3.1 绑定机制 表单中请求参数都是基于 key=value 键值对的。SpringMVC 绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。例如:
1 2 <!--请求参数是:accountId=10 --> <a href="account/findAccount?accountId=10" >查询账户</a>
1 2 3 4 5 6 7 8 9 @RequestMapping("/findAccount") public String findAccount (Integer accountId) { System.out.println("查询了账户。。。。" +accountId); return "success" ; }
3.2 支持的数据类型
说明:SpringMVC 绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求。
3.3 基本类型和String类型作为参数
使用要求:要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)
代码演示
jsp代码:
1 <a href="param/testParam?username=hehe&password=123456" >请求参数绑定</a>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Controller @RequestMapping("/param") public class ParamController { @RequestMapping("/testParam") public String testParam (String username,String password) { System.out.println("执行了..." ); System.out.println("你的用户名是:" +username); System.out.println("你的密码是:" +password); return "success" ; } }
执行结果:
3.4 POJO类型作为参数 3.4.1 要求 要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。
代码演示
Account.java
1 2 3 4 5 6 7 8 public class Account implements Serializable { private String username; private String password; private double money; private User user; }
User.java
1 2 3 4 5 public class User implements Serializable { private String uname; private Integer age; }
jsp
代码
1 2 3 4 5 6 7 8 <form action="/param/saveAccount" method="post" > 姓名:<input type="text" name="username" /><br/> 密码:<input type="text" name="password" /><br/> 金额:<input type="text" name="money" /><br/> 用户姓名:<input type="text" name="user.uname" /><br/> 用户年龄:<input type="text" name="user.age" /><br/> <input type="submit" value="提交" /> </form>
控制层代码
1 2 3 4 5 6 7 8 9 10 @RequestMapping("/saveAccount") public String saveAccount (Account account) { System.out.println("执行了..." ); System.out.println(account); return "success" ; }
执行结果
3.4.2 配置解决中文乱码的过滤器 web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 <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 >
3.5 集合类型作为参数
要求
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 <!--类中存在list和map的集合--> <form action="/param/saveAccount" method="post" > 姓名:<input type="text" name="username" /><br/> 密码:<input type="text" name="password" /><br/> 金额:<input type="text" name="money" /><br/> 用户姓名:<input type="text" name="list[0].uname" /><br/> 用户年龄:<input type="text" name="list[0].age" /><br/> 用户姓名:<input type="text" name="map['one'].uname" /><br/> 用户年龄:<input type="text" name="map['one'].age" /><br/> <input type="submit" value="提交" /> </form>
Account类属性:
1 2 3 4 5 6 private String username;private String password;private double money;private List<User> list;private Map<String,User> map;
执行结果:
3.6 自定义类型转换器 3.6.1 演示异常 1 2 3 4 5 6 7 <!--自定义类型转换器--> <form action="/param/saveUser" method="post" > 用户姓名:<input type="text" name="uname" /><br/> 用户年龄:<input type="text" name="age" /><br/> 用户生日:<input type="text" name="date" /><br/> <input type="submit" value="提交" /> </form>
1 2 3 4 5 public class User implements Serializable { private String uname; private Integer age; private Date date; }
1 2 3 4 5 6 7 8 9 10 11 @RequestMapping("/saveUser") public String saveUser (User user) { System.out.println("执行了..." ); System.out.println(user); return "success" ; }
正常情况:
异常情况:
3.6.2 转换器代码编写 字符串转日期的工具类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class StringToDateConverter implements Converter <String , Date > { @Override public Date convert (String s) { if (s == null ){ throw new RuntimeException("请传入数据" ); } DateFormat df = new SimpleDateFormat("yyyy-MM-dd" ); try { return df.parse(s); } catch (Exception e) { throw new RuntimeException("数据类型转换异常" ); } } }
springmvc.xml
配置
1 2 3 4 5 6 7 8 9 10 11 <bean id ="conversionService" class ="org.springframework.context.support.ConversionServiceFactoryBean" > <property name ="converters" > <set > <bean class ="com.hongyi.utils.StringToDateConverter" > </bean > </set > </property > </bean > <mvc:annotation-driven conversion-service ="conversionService" > </mvc:annotation-driven >
执行结果
3.7 获取Servlet原生的API SpringMVC
还支持使用原始 ServletAPI
对象作为控制器方法的参数。可以把上述对象,直接写在控制的方法参数中使用。
代码演示
1 <a href="param/testServlet" >测试Servlet原生API</a>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @RequestMapping("/testServlet") public String testServlet (HttpServletRequest request, HttpServletResponse response) { System.out.println("执行了..." ); System.out.println(request); HttpSession session = request.getSession(); System.out.println(session); ServletContext servletContext = session.getServletContext(); System.out.println(servletContext); System.out.println(response); return "success" ; }
执行结果
4 常用注解