MVC是一种设计思想,不是一种框架。它将一个应用分成3个基本部分,分别代表着Web应用程序中的3种职责:
Model(模型):用于存储数据和完成业务逻辑处理
View(视图):用于显示数据和向控制器提交数据请求
Controller(控制器):根据视图请求调用Model完成业务处理,将处理后的结果交由View进行展示
而SpringMVC是Spring框架提供的构建Web应用程序的全功能MVC模块。
一、SpringMVC入门
首先要搭建web项目,导入相应依赖。其中搭建web项目的方式有很多种,以下简单演示其中一种
确保红框里选择的是对应的选项,然后选择本地的Tomcat
创建完的项目目录:
导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
创建完之后可以开始搭建SpringMVC框架了,这里有基于XML和注解两种方式
1.XML方式
(1)在webapp>WEB-INF目录下创建一个JSP hello.jsp
(2)在java目录下创建controller包,在该包下创建helloController,加上@Controller注解,写一个hello方法,为其添加映射路径,因为WEB-INF目录下的JSP不能直接访问
这里的return “hello”,hello为创建的JSP去掉.jsp后缀
(3)在resources文件夹下创建SpringMVC核心文件spring-mvc.xml,修改文件头,并添加注解扫描和视图解析器
这里的视图解析器为controller类返回的视图加上了前缀(prefix)和后缀(suffix),这样controller类里写的视图路径就不会太长太臃肿
(4)web.xml中配置SpringMVC核心控制器DispathcerServlet
(5)运行时在地址栏输入刚刚HelloControll类写的hello方法的映射路径,运行结果如下
2.注解方式
(1)在java目录下创建config包,在该包下创建配置类SpringMvcConfig替换spring-mvc.xml
(2)在config包下创建配置类ServletContainersInitConfig替换web.xml
(3)重新启动tomcat,再次运行即可
二、SpringMVC的数据响应方式
1.返回字符串跳转视图
直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转(有则拼接,无则直接跳转)
比如上述的helloController种的hello方法返回的字符串
返回带有前缀的字符串:
转发:forward:/WEB-INF/hello.jsp
重定向:redirect:/hello(这里可以重定向到helloController类中映射路径为“hello”的方法)
2.返回字符串不跳转某一视图
在helloController中编写以下方法
返回的结果皆为:
此时地址栏上并没有跳转到某一视图,而是对应方法中的映射路径
3.返回ModelAndView对象
编写控制器中处理请求的方法,以下展示不同的方式,统一返回的视图为上面写的hello.jsp
在hello.jsp添加如下内容
执行效果统一为以下运行结果
4.返回对象或集合
此方式要导入json依赖,上述已经导过了
(1)开启mvc的注解驱动
xml方式:spring核心配置文件(spring-mvc.xml)中加以下配置
注解方式:spring配置类(springMvcConfig.java)上加以下注解
在java目录下创建entity包,在该包下创建实体类Phone,这里可以加上@Data注解,就省去了生成get、set、toString方法,不过要另外导入一个依赖
在controller中编写一个方法如下,注意返回类型不再为String,而是实体类对象
运行结果
5.通过HttpSession传输数据
如果需要跨请求、跨页面共享数据,就需要将数据存储到session域中,即存储到HttpSession对象中,有以下两种方式
(1)使用HttpSession对象
运行结果
(2)使用@SessionAttributes注解
该注解可以使得数据模型(Model)中的数据存储一份到session域中,只能在类上使用,不能在方法上使用
在controller类上添加注解@SessionAttributes,此注解可以自动将数据模型中相同键名的数据存储到HttpSession对象中
编写以下方法
运行结果
三、SpringMVC获取不同参数类型
1.获取基本类型
(1)Controller中的业务方法的参数名称要与请求参数的name一致,参数值会自动映射匹配
在地址栏上输入内容(下述只展示输入的内容)
内部控制台输出以下内容
(2)当请求的参数名称与controller的方法的参数名称不一致时,就需要通过@RequestParam注解显示的绑定。
param2?phoneId=1&mNumber=mate60
(3)注解@RequestParam还有如下参数可以使用:
-
value::请求参数名称
-
required::指定的请求参数是否必须包括,默认是true,提交时如果没有此参数则报错
-
defaultValue:当没有指定请求参数时,则使用指定的默认值赋值
2.获取POJO类型参数
controller中的业务方法的POJO参数的属性名与请求参数的name一致,参数值会自动映射匹配。
param4?phoneId=1&modelNumber=mate60
3.获取数组类型参数
controller中的业务方法数组名称与请求参数的name一致,参数值会自动映射匹配。
4.获得Restful风格的参数
Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
上述url地址/user/1中的1就是要获得的请求参数,在SpringMVC中可以使用占位符进行参数绑定。地址/user/1可以写成/user/{id},占位符{id}对应的就是1的值。在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取工作。
param9/7
5.获取请求头
(1)@RequestHeader
使用@RequestHeader可以获得请求头信息,相当于web阶段学习的request.getHeader(name)
@RequestHeader注解的属性如下:
-
value:请求头的名称
-
required:是否必须携带此请求头
这里获取的是网页上的user-Agent
运行结果
(2)@CookieValue
使用@CookieValue可以获得指定Cookie的值
@CookieValue注解的属性如下:
-
value:指定cookie的名称
-
required:是否必须携带此cookie
这里获取的对应网页上的元素为
运行结果
5.文件上传
要实现文件上传,首先要导入的依赖如下:
在spring配置类中配置文件上传解析器
在controller中处理文件上传的方法
写完以上内容就可以在postman中进行测试了,测试流程如下
选择post->输入路径->选择Headers->输入Content-Type键值对
选择body->在“key”列输入file->选择file->选择图片,最后点击发送(send)
四、拦截器
1.拦截器的作用
Spring MVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(Interceptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。
2.拦截器和过滤器的区别
区别 | 过滤器 | 拦截器 |
---|---|---|
使用范围 | 是servlet规范中的一部分,任何Java Web工程都可以使用 | 是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用 |
拦截范围 | 在url-pattern中配置了/*之后,可以对所有要访问的资源拦截 | 只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或者js 是不会进行拦截的 |
3.拦截器方法说明
方法名 | 说明 |
---|---|
preHandle | 该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回true表示继续向下执行,返回false表示中断后续操作,可以进行编码、安全控制、权限校验等处理。 |
postHandle | 该方法在控制器的处理请求方法调用之后,解析视图之前执行,可以通过此方法对模型和视图做进一步的修改。 |
afterCompletion | 该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行,可以通过此方法实现一些资源清理、记录日志等工作。 |
4.拦截器的实现
(1)创建一个拦截器,这里只写了预处理
(2)在spring配置类中配置拦截器
(3)创建一个控制器模拟登录
(4)测试拦截器
在网页上输入任意一个控制器方法的映射路径,这时没有登录,没有通过验证,所以显示权限不足
此外,也可以通过postman测试
五、统一异常处理
统一异常处理的目的为:用户在使用程序期间,如果出现错误了,会有一个友好的页面显示,而不是出现大堆的异常错误信息(比如404、400等)。
统一异常处理两种实现方式: 实现HandlerExceptionResolver接口 、@ExceptionHandler注解
以下以@ExceptionHandler注解的方式示例
(1)首先需要引入依赖如下
(2)以下为@ControllerAdvice 配合 @ExceptionHandler 实现全局异常处理
(3)创建一个error.jsp,里面的内容写要显示的友好错误提示
(4)编写一个测试的controller类
(5)结果如下