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() 方法:

java 复制代码
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 {

    @Override
    public 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 中的写法:

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 路径对比

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

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

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

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

java 复制代码
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)
    @PostMapping
    public String addUser(User user) {
        System.out.println("添加用户: " + user);
        return "success";
    }

    // 修改用户(PUT /user/wsbazinga/123)
    @PutMapping
    public 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请求:

html 复制代码
    <!-- 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请求

html 复制代码
    <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 中配置过滤器:

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执行。

html 复制代码
    <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文件中有两个过滤器,对顺序有要求!

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 中通常是这样配置的:

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文件中配置

XML 复制代码
<mvc:default-servlet-handler />

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

XML 复制代码
<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 和浏览器都无法直接访问

示例项目结构(推荐):

XML 复制代码
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/图片可能无法加载。

相关推荐
endswel2 天前
Spring MVC HandlerInterceptor 拦截请求及响应体
springmvc·springboot
sniper_fandc6 天前
SpringMVC详解
java·springmvc
保持学习ing17 天前
SpringBoot电脑商城项目--创建订单+统计业务方法耗时
java·spring boot·spring·springmvc·jquery
编程大全22 天前
47道SpringMVC高频题整理(附答案背诵版)
springmvc·面试题
周星星日记1 个月前
1.springmvc基础入门(一)
spring·springmvc
abcnull1 个月前
springboot中过滤器配置使用
java·spring boot·后端·springmvc·过滤器
liubo666_2 个月前
SpringMVC(结合源码浅析工作流程)
java·spring·springmvc
唐僧洗头爱飘柔95272 个月前
【SSM-SSM整合】将Spring、SpringMVC、Mybatis三者进行整合;本文阐述了几个核心原理知识点,附带对应的源码以及描述解析
java·spring·mybatis·springmvc·动态代理·ioc容器·视图控制器
超级无敌永恒暴龙战士2 个月前
SpringMVC-执行流程
spring·servlet·springmvc