ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

springMVC02-视图解析器、RESTful设计风格,静态资源访问配置

springMVC02-视图解析器、RESTful设计风格,静态资源访问配置

一、SpringMVC 的视图

在 SpringMVC 中,视图的作用渲染数据,将模型 Model (将控制器(Controller))中的数据展示给用户。

在 Java 代码中,视图由接口 org.springframework.web.servlet.View 表示

SpringMVC 视图的种类很多,默认转发视图InternalResourceView重定向视图RedirectView

当工程引入 Jstl 的依赖,转发视图会自动转换为 JstlView;

若使用的视图技术为 Thymeleaf,在 SpringMVC 的配置文件中配置了 Thymeleaf 的视图解析器,由此视图解析器解析之后所得到的是 ThymeleafView。

1-1、视图解析流程(基本原理)

当你在控制器中 return "success",SpringMVC 会做以下几步:

  1. "success" 当作视图名(ViewName)

  2. 使用 视图解析器(ViewResolver) 解析这个视图名

  3. 返回一个实现了 View 接口的视图对象(如 InternalResourceView, JstlView, ThymeleafView

  4. 调用 view.render(...) 渲染模型数据(model)+ 转发或重定向

 

1-2、SpringMVC 支持的视图类型

类型说明关键类或说明
转发视图默认是 InternalResourceView,通过 RequestDispatcher.forward() 转发不改变地址栏,可共享 request 域
重定向视图RedirectView,使用 response.sendRedirect()地址栏改变,不能共享 request 域
JSTL 视图加了 JSTL 依赖后,转发视图会自动变成 JstlView支持 <c:forEach> 等标签
Thymeleaf 视图配置了 Thymeleaf 解析器后使用 ThymeleafView支持 Thymeleaf 模板语法
其他VelocityView、FreeMarkerView 等可扩展视图技术

 

1-3、Thymeleaf

若是视图是由Thymeleaf解析器解析之后得到的,获取到的视图就是ThymeleafView,但是不是左右的情况,获取的都是ThymeleafView。

当控制方法中返回的视图名称以“forword:”为前缀的时候,创建的是InternalResourceView

当控制方法中返回的视图名称以“redirect:”为前缀的时候,创建的是RedirectView

只有视图名称没有任何前缀的时候,创建的才是ThymeleafView。

当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被 SpringMVC 配置文件中所配置的视图解析器解析,视图名称拼接视图前缀视图后缀所得到的最终路径,会通过转发的方式实现跳转。

1-4、转发视图

1、浏览器发送一次请求,浏览器中的URL不会变!能获取到请求域中的数据!

2、web-inf下的资源不能通过浏览器获取到,但是可以通过服务器转发获取到!

3、不能跨域

SpringMVC 中默认的转发视图是 InternalResourceView

SpringMVC 中创建转发视图的情况:

当控制器方法中所设置的视图名称以 "forward:" 为前缀时,创建 InternalResourceView 视图,此时的视图名称不会被 SpringMVC 配置文件中所配置的视图解析器解析,而是会将前缀 "forward:" 去掉,剩余部分作为最终路径通过转发的方式实现跳转。

例如 "forward:/", "forward:/employee"

用的比较少,因为Thymeleaf视图解析器,默认就是转发视图!

1-5、重定向视图

1、浏览器发送两次请求,浏览器中的URL会变!不能获取到请求域中的数据!

2、可以跨域!

SpringMVC 中默认的重定向视图是 RedirectView。

当控制器方法中所设置的视图名称以 "redirect:" 为前缀时,创建 RedirectView 视图,此时的视图名称不会被 SpringMVC 配置文件中所配置的视图解析器解析,而是会将前缀 "redirect:" 去掉,剩余部分作为最终路径通过重定向的方式实现跳转。

例如 "redirect:/", "redirect:/employee"

1-6、视图控制器:view-controller

没有其他控制方法的处理,只需要通过请求映射,返回一个视图名称的时候。

此时控制中的所有的请求映射将全部失效!

<mvc:view-controller> 是 Spring XML 配置中的简洁写法,专门用于静态页面跳转,适合“无业务逻辑”的场景现在依然常用,尤其在配置登录页、首页等时非常实用

Spring Boot 中,不再使用 XML 配置 <mvc:view-controller>,而是使用 Java 配置(基于代码的方式)来实现相同功能。


目标:实现“请求路径直接跳转到某个页面”,不写 Controller 方法

比如我们希望:

  • 访问 /login → 显示 login.html

  • 访问 / → 显示 index.html


1、Spring Boot Java 配置方式(推荐写法)

你只需创建一个配置类,实现 WebMvcConfigurer 接口,重写 addViewControllers() 方法

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MyMvcConfig implements WebMvcConfigurer {@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/login").setViewName("login");registry.addViewController("/").setViewName("index");}
}

2、视图位置说明(默认)

Spring Boot 默认使用的是 Thymeleaf,默认的视图位置是:

src/main/resources/templates/

所以你要在这里放:

src/main/resources/templates/login.html
src/main/resources/templates/index.html

(如果你用的是 JSP,需要特殊配置)


3、等价于 Spring XML 中的写法:

<mvc:view-controller path="/login" view-name="login"/>

总结一句话:

在 Spring Boot 中,你可以通过实现 WebMvcConfigurer 接口的 Java 配置类,用 addViewControllers() 实现和 XML 中 <mvc:view-controller> 一样的功能 —— 页面跳转,无需写 Controller,简单又优雅。

二、RESTful设计风格

2-1、什么是 RESTful?

RESTful 是一种 Web 设计风格,不是技术,是一种“使用 URL + HTTP 方法 表达资源操作”的设计规范,常用于 Web API 接口开发。


 

2-2、RESTful 的核心特点

要素示例含义
URL 表示资源/user/1表示用户 ID 为 1 的用户
HTTP 方法表示动作GET、POST、PUT、DELETE分别对应:查、增、、删

【注意】:

请求参数以/xxxx的方式拼接在URL中! 


 

2-3、传统 VS RESTful 路径对比

功能传统风格 URLRESTful 风格 URL
查询用户/user/get?id=1GET /user/1
添加用户/user/addPOST /user
修改用户/user/update?id=1PUT /user/1
删除用户/user/delete?id=1DELETE /user/1

 

2-4、Spring MVC 实现 RESTful:案例说明

我们现在用一个简单的 Spring MVC 项目说明 RESTful 怎么落地实现。

1. RESTful Controller 示例(路径 + 方法)

package com.example.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;@Controller
@RequestMapping("/user")
public class UserController {// 查询用户(GET /user/admin)@GetMapping("/{username}")public String getUser(@PathVariable("username") String username) {System.out.println("查询用户:" + username);return "success";}// 添加用户(POST /user)@PostMappingpublic String addUser(User user) {System.out.println("添加用户: " + user);return "success";}// 修改用户(PUT /user/wsbazinga/123)@PutMappingpublic String updateUser(@RequestParam("username") String username,@RequestParam("password") String password) {System.out.println("更新用户: username = " + username + ", password = " + password);return "success";}// 删除用户(DELETE /user/wsbazinga)@DeleteMapping("/{username}")public String deleteUser(@PathVariable("username") String username) {System.out.println("删除用户:" + username);return "success";}
}

2-5、前端如何测试不同的 HTTP 方法?

1、post和get请求:

    <!-- get请求 --><a th:href="@{/user/admin}">查询id = 1的用户</a><br><!-- post请求 --><form th:action="@{/user}" method="post">username: <input type="text" name="username">password: <input type="text" name="password">role: <input type="text" name="role"><input type="submit" value="add"></form>

2、put请求 

浏览器默认只能发 GET 和 POST 请求。对于 PUT 和 DELETE,有几种方法:

方法1:使用 Postman测试

curl -X PUT http://localhost:8080/user/1
curl -X DELETE http://localhost:8080/user/1

方法2:表单中使用 Spring 的隐藏字段 + 过滤器支持

示例:put请求

    <form th:action="@{/user}" method="post"><!-- 对用户没有意义 --><input type="hidden" name="_method" value="put" />username: <input type="text" name="username">password: <input type="text" name="password">role: <input type="text" name="role"><input type="submit" value="update"></form>

【注意】:

type="hidden":用户页面不可见

name = "_method" value="put"才能让post请求变成put请求! 

并在 web.xml 中配置过滤器:

<!-- 支持RESTful方式提交PUT/DELETE -->
<filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

3、delete请求 

通过<a>超链接,点击之后,调用form表单的delete方法,走filter执行。

    <div id="delete"><h2>form delete request</h2><a th:href="@{/user/wsbainga123}" @click="deleteUser">delete user</a><form id="deleteForm" method="post"><!-- 对用户没有意义 --><input type="hidden" name="_method" value="delete" /></form></div><!-- 引入 Vue --><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>new Vue({el: '#delete',methods:{deleteUser: function (event) {// 获取form表单var deleteForm = document.getElementById("deleteForm");// 添加form表单的action属性,若是没有,默认提交到当前页面// form表单的action属性 = 点击事件<a>的href的值deleteForm.action = event.target.href;// 提交表单deleteForm.submit();// 取消超链接的默认行为(跳转页面)event.preventDefault();}}});</script>

2-6、总结一句话:

RESTful 是一种使用“URL 表示资源 + HTTP 方法表示动作”的设计风格。Spring MVC 通过 @GetMapping@PostMapping@PutMapping@DeleteMapping 注解完美支持 RESTful,非常适合写清晰简洁的接口。


2-7、web.xml中多个过滤器

此时web.xml文件中有两个过滤器,对顺序有要求!

<!-- 处理编码的过滤器 --><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><!-- 响应设置编码 --><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 支持RESTful方式提交PUT/DELETE --><filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

一定要是处理编码的过滤器在前!否则,中卫乱码,因为 hiddenHttpMethodFilter 中会先获取参数_method,导致处理编码的过滤器失效!

springmvc项目的web.xml文件内容,基本上就是:一个servlet+两个过滤器

三、default-servlet-handler配置

在 Spring MVC 中,default-servlet-handler 是一个非常关键但经常被忽略的配置,它的作用是:静态资源(如图片、CSS、JS 等)能够被正常访问


 

3-1、为什么需要 default-servlet-handler

Spring MVC 的核心思想是:把所有请求都交给前端控制器 DispatcherServlet 统一处理。

比如你在 web.xml 中通常是这样配置的:

<servlet-mapping><servlet-name>springDispatcher</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

这意味着:所有请求(包括静态资源)都会被 SpringMVC 接管

⚠️ 问题:

SpringMVC 的 DispatcherServlet 默认只处理动态请求(Controller 处理的),对像 /css/style.css/js/app.js 这样的静态资源它是不会处理的,所以最终就 404 了。


3-2、<mvc:default-servlet-handler> 的作用

该配置的作用是:

告诉 SpringMVC:你不处理静态资源,请把它们交回给默认的 Servlet(即 Tomcat 的 DefaultServlet)去处理

处理顺序:

1、先交给dispatherServlet处理;

2、找不到,交给defaultServlet处理;

3、找不到,返回404!

示例配置:在springMVC.xml文件中配置

<mvc:default-servlet-handler />

配合使用 DispatcherServlet/ 映射时效果最好:

<servlet-mapping><servlet-name>springDispatcher</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

【注意】:

 

这两个注解要一起使用,要是只配置了default-servlet-handler,所有的请求将交给default-servlet-handler处理!包括动态请求!


3-3、补充:Spring Boot 中怎么处理静态资源?

Spring Boot 不需要配置 <mvc:default-servlet-handler>,它默认自动处理静态资源,资源路径为:

src/main/resources/static/
src/main/resources/public/
src/main/resources/resources/

3-4、WEB-INF下的静态资源

即使你配置了 <mvc:default-servlet-handler/>,如果静态资源(如 .html.css、图片等)放在 WEB-INF 文件夹下,浏览器依然无法直接访问!

Web 容器(如 Tomcat)会自动阻止用户直接访问 WEB-INF 及其子目录的任何资源,这是 Java Web 的安全机制。 

正确放静态资源的位置:

你应该把 HTML、CSS、JS、图片 等资源放在这些位置:

放置路径是否能被访问说明
/webapp/static/✅ 可以访问推荐:SpringMVC 中常用
/webapp/public/✅ 可以访问Tomcat 支持的默认静态目录
/webapp/css//js/✅ 可以访问可以自由命名
/WEB-INF/❌ 不能访问SpringMVC 和浏览器都无法直接访问

示例项目结构(推荐):

src
└── main└── webapp├── index.html         ✅ 可访问:http://localhost:8080/项目名/index.html├── css/│   └── style.css      ✅ 可访问:http://localhost:8080/项目名/css/style.css├── js/└── WEB-INF/└── views/└── page.jsp    ✅ 只能通过控制器转发访问,不能直接访问

WEB-INF 的作用是什么?

  • 用来存放 JSP 文件(如视图页面)

  • 保证用户不能通过 URL 直接访问它们

  • 必须通过控制器转发才能访问,如:

3-5、总结:

在 Spring MVC 中,<mvc:default-servlet-handler /> 是用于将 静态资源请求交还给 Web 容器(如 Tomcat)默认处理的关键配置,如果你使用了 / 映射 DispatcherServlet,就必须加它,否则 CSS/JS/图片可能无法加载。

返回列表