最全面的SpringBoot教程(三)——SpringBoot Web开发

news2025/1/15 6:28:16

前言

在这里插入图片描述

本文为SpringBoot Web开发相关内容介绍,下边将对静态资源管理(包括:静态资源访问静态资源前缀webjar首页支持),请求参数处理(包括:Rest风格参数注释),数据响应模板引擎(包括:Thymeleaf模板引擎基本语法thymeleaf使用),登录功能 + 拦截器异常处理等进行详尽介绍~

📌博主主页:小新要变强 的主页
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)


目录

SpringBoot Web开发

  • 前言
  • 目录
  • 一、静态资源管理
    • 1️⃣静态资源访问
    • 2️⃣静态资源前缀
    • 3️⃣webjar
    • 4️⃣首页支持
  • 二、请求参数处理
    • 1️⃣Rest风格
    • 2️⃣参数注释
  • 三、数据响应
  • 四、模板引擎
    • 1️⃣Thymeleaf模板引擎
    • 2️⃣基本语法
    • 3️⃣thymeleaf使用
  • 五、登录功能 + 拦截器
  • 六、异常处理
  • 后记

在这里插入图片描述

一、静态资源管理

1️⃣静态资源访问

默认情况下,Spring Boot 从类路径中的/static (或/public 或/resources 或/META-INF/resources)目录或 ServletContext的根目录提供静态内容。

访问: 当前项目根路径/ + 静态资源名

原理: 静态映射/**。

请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应404页面

我们添加图片到resource下的static里:

在这里插入图片描述

请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应404页面

2️⃣静态资源前缀

可以添加访问静态资源前缘:

spring:
  mvc:
    static-path-pattern: /res/**

现在访问就是: 当前项目根路径 + /res + 静态资源名

3️⃣webjar

webjar官网:https://www.webjars.org/

webJars是可以让大家以jar包的形式来使用前端的各种框架、组件。例如,引用jquery。

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.6.1</version>
</dependency>

在这里插入图片描述

访问路径:当前项目根路径/ + webjars/**

在这里插入图片描述

4️⃣首页支持

  • 静态资源路径下 index.html
  • 可以配置静态资源路径
  • 不能与静态资源前缀共用
spring:
  resources:
    static-locations: [classpath:/haha/]

二、请求参数处理

1️⃣Rest风格

RESTFUL是一种网络应用程序的设计风格和开发方式。

对比:

功能传统请求Rest风格
获取用户/user/getUser (GET请求)/user (GET请求)
保存用户/user/saveUse (POST请求)/user (POST请求)
修改用户/user/editUser (POST请求)/user (PUT请求)
删除用户/user/deleteUser(POST请求)/user (DELETE请求)

springboot用法:表单method=post,隐藏域 _method=put。

(1)开启页面表单的Rest功能

spring:
  mvc:
    hiddenmethod:
      filter:
        # 开启页面表单的Rest功能
        enabled: true

(2)添加页面请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="/webjars/jquery/3.6.1/jquery.js"></script>
<body>
    <h1>首页</h1>
    <button id="getUser">获取用户</button>
    <button id="saveUser">保存用户</button>
    <button id="editUser">修改用户</button>
    <button id="deleteUser">删除用户</button>
    <p id="msg"></p>
<script>
    $("#getUser").on("click",()=>{
        $.get("/user",(res)=>{
            $("#msg").text(res);
        })
    });
    $("#saveUser").on("click",()=>{
        sendAjax(null);
    });
    $("#editUser").on("click",()=>{
        sendAjax('PUT');
    });
    $("#deleteUser").on("click",()=>{
        sendAjax("DELETE");
    });
    function sendAjax(type){
        let data = {'_method':type}
        $.post("/user",data,(res)=>{
            $("#msg").text(res);
        })
    }
</script>
</body>
</html>

(3)添加后端接口

// 组合注解,@Controller + RequestBody
@RestController
@RequestMapping("/user")
public class UserController {
    // 普通写法
    // @RequestMapping(value = "/user",method = RequestMethod.GET)
    // 精简写法
    @GetMapping
    public String getUser(){
        return "get user";
    }
    @PostMapping
    public String saveUser(){
        return "post user";
    }
    @PutMapping
    public String editUser(){
        return "put user";
    }
    @DeleteMapping
    public String deleteUser(){
        return "delete user";
    }
}

为什么明明请求方式是POST,会跑到别的接口。

  • 核心Filter;HiddenHttpMethodFilter。
  • 由过滤器来判断改变。

在这里插入图片描述

如果请求方式是直接发送Put、delete等方式请求,无需Filter。

扩展:_method的值可以自定义,只需要重新实现过滤器方法即可。

//自定义filter
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
    HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
    methodFilter.setMethodParam("_m");
    return methodFilter;
}

2️⃣参数注释

  • @PathVariable:从请求路径上获取参数
  • @RequestHeader:从请求头上获取参数
  • @RequestParam:从请求参数上获取参数
  • @CookieValue:从请求Cookie中获取参数
  • @RequestBody:从请求body上获取参数
  • @MatrixVariable:从请求路径上;分割获取变量
    • SpringBoot默认禁用
    • 语法: 请求路径/test;user=jack;age=16,interests=sleep,dream
    • 后端接收,@MatrixVariable("user") String name,@MatrixVariable("age") Integer age,@MatrixVariable("interests") List<String> interests
@GetMapping("/{id}")
public String getParam(@PathVariable("id") Integer id,
                      @RequestHeader("Host") String host,
                      @RequestParam("name") Integer name,
                      @CookieValue("_username") String usernmae){
}
@PostMapping
public void postMethod(@RequestBody String content){
}
// 可以传多个值,用对象来接收,存在相同属性时,会自动封装到里面。
@PostMapping
public void postMethod(@RequestBody Student student){
}

三、数据响应

数据响应,一般分两个类型:

  • 响应页面
  • 响应数据

响应数据的格式可以是json,xml,io流等。

SpringMVC支持返回值:

ModelAndView
Model
View
ResponseEntity 
ResponseBodyEmitter
StreamingResponseBody
HttpEntity
HttpHeaders
Callable
DeferredResult
ListenableFuture
CompletionStage
WebAsyncTask@ModelAttribute 且为对象类型的@ResponseBody 注解

四、模板引擎

SpringBoot默认不支持 JSP,需要引入第三方模板引擎技术实现页面渲染。

1️⃣Thymeleaf模板引擎

官网:https://www.thymeleaf.org/

前端显示页面,是html页面。我们以前开发,做的是jsp页面,jsp可以动态渲染一些数据在页面上,可以写Java代码。JSP+Servlet+JavaBean,是我们很早之前就不用了,企业也用得少。

现在SpringBoot推荐Thymeleaf模板引擎。

2️⃣基本语法

表达式名字语法用途
变量取值${…}获取请求域、session域、对象等值
选择变量*{…}获取上下文对象值
消息#{…}获取国际化等值
链接@{…}生成链接
片段表达式~{…}jsp:include 作用,引入公共页面片段
<!-- 常用标签,一般都是  th:XXX -->
<!-- 需要设置头部(非标准HTML5 规范),也可以不设置 -->
<html xmlns:th="http://www.thymeleaf.org">
<!-- 不设置头部的写法(符合HTML5规范) -->
<p data-th-text="${msg}">msg</p>
<!--设置文本-->
<p th:text="${msg}">提醒消息</p>
<!--设置文本-->
<a th:href="@{href}">超链接</a>
<!-- 设置属性值 -->
<input type="text" th:id="${student.id}" />
<!-- 获取session -->
<p th:id="${#session.user}" />

3️⃣thymeleaf使用

(1)添加thymeleaf依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

(2)创建文件,springboot帮我们配置好了,我们直接开发页面即可

在这里插入图片描述

// 接口
@Controller
public class IndexController {
    @GetMapping("/thymeleaf")
    public String index(Model model) {
        model.addAttribute("msg","hello thymeleaf");
        model.addAttribute("link","www.baidu.com");
        // 返回视图层
        return "thymeleaf";
    }
}

在templates下新建thymeleaf.html:

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1 data-th-text="${msg}">提醒消息</h1>
    <h2>
        <a data-th-href="${link}">超连接</a>
    </h2>
</body>
</html>

(3)效果

在这里插入图片描述

五、登录功能 + 拦截器

例子:访问项目,需要登录,如果没有登录就不能访问

🍀(1)添加登录页面:login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LOGIN</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        html {
            height: 100%;
        }
        body {
            height: 100%;
        }
        .container {
            height: 100%;
            background-image: linear-gradient(to right, #fbc2eb, #a6c1ee);
        }
        .login-wrapper {
            background-color: #fff;
            width: 358px;
            height: 588px;
            border-radius: 15px;
            padding: 0 50px;
            position: relative;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
        .header {
            font-size: 38px;
            font-weight: bold;
            text-align: center;
            line-height: 200px;
        }
        .input-item {
            display: block;
            width: 100%;
            margin-bottom: 20px;
            border: 0;
            padding: 10px;
            border-bottom: 1px solid rgb(128, 125, 125);
            font-size: 15px;
            outline: none;
        }
        .input-item:placeholder {
            text-transform: uppercase;
        }
        .btn {
            border: 0;
            font-size: 20px;
            text-align: center;
            padding: 10px;
            width: 100%;
            margin-top: 40px;
            background-image: linear-gradient(to right, #a6c1ee, #fbc2eb);
            color: #fff;
        }
        .msg {
            color:red;
            text-align: center;
            line-height: 88px;
        }
        a {
            text-decoration-line: none;
            color: #abc1ee;
        }
    </style>
</head>
<body>
<div class="container">
    <div class="login-wrapper">
        <div class="header">Login</div>
        <div class="form-wrapper">
            <form data-th-action="@{/login}" method="post">
                <input type="text" name="username" placeholder="username" class="input-item" /  >
                <input type="password" name="password" placeholder="password" class="input-item" />
                <input type="submit" class="btn" value="Login" />
            </form>
        </div>
        <div class="msg" data-th-text="${msg}">
            Don't have account?
            <a href="#">Sign up</a>
        </div>
    </div>
</div>
</body>
</html>

🍀(2)添加登录接口

@Controller
public class LoginController {
    @GetMapping("/")
    public String index() {
        // 返回视图层
        return "/login/login";
    }
    @PostMapping("/login")
    public String login(String username, String password, HttpSession session, Model model) {
        if(StringUtils.hasLength(username) && "123456".equals(password)){
            //把登陆成功的用户保存起来
            session.setAttribute("loginUserName",username);
            //登录成功重定向到 thymeleaf ;  重定向防止表单重复提交
            return "redirect:/thymeleaf";
        }else {
            model.addAttribute("msg","账号密码错误");
            //回到登录页面
            return "/";
        }
    }
}

🍀(3)添加拦截器

继承HandlerInterceptor 接口

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 目标方法执行之前
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 请求路径 request.getRequestURI();
        //登录检查逻辑
        HttpSession session = request.getSession();
        Object loginUser = session.getAttribute("loginUserName");
        if(loginUser != null){
            //放行
            return true;
        }
        //拦截住。未登录。跳转到登录页
        request.setAttribute("msg","请先登录");
        // 跳转
        request.getRequestDispatcher("/").forward(request,response);
        return false;
    }
}

🍀(4)配置拦截器

@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                // 所有请求都被拦截包括静态资源
                .addPathPatterns("/**")
                // 放行的请求
                .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**");
    }
}

🍀(5)测试

在这里插入图片描述

六、异常处理

错误处理:

  • 默认情况下,Spring Boot提供/error处理所有错误的映射
  • 对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据
  • 对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息

在这里插入图片描述
在这里插入图片描述

SpringBoot也为我们提供了自定义错误页的功能。

自定义错误页的话可以在静态路径(如/static/)下的error目录。或放在模板目录(如 /templates/)下的error目录,都会被SpringBootz自动解析。

DefaultErrorAttributes:定义错误页面中可以包含哪些数据。

在这里插入图片描述


后记

在这里插入图片描述

👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/409759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【微信小程序】-- 自定义组件 - 父子组件之间的通信(三十八)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…

也许是全网最全的 Angular 新手入门指南

文章目录Angular概述Angular程序架构Angular优势angular/cli脚手架文件加载顺序项目目录结构Angular模块NgModule 装饰器内置模块自定义模块模块的tipsAngular组件Component 元数据数据绑定脏值检测父子组件通讯投影组件Angular指令内置属性型指令内置结构型指令指令事件样式绑…

若依框架(前后端分离)打war包部署到linux

一、前端部署 1.找到ruoyi-ui目录。 2.安装依赖。 npm install 3.执行以下操作&#xff0c;解决 npm 下载速度慢的问题。 npm install --registryhttps://registry.npmmirror.com 4.修改vue.config.js,若后端采用的是默认8080端口&#xff0c;则不用修改&#xff0c;默认就是…

2023最新最全vscode插件精选

文章简介 本文介绍最新、最实用、最强大的 vscode 精选扩展。好用的扩展&#xff0c;犹如神兵利器&#xff0c;帮助程序员在代码的世界中&#xff0c;所向披靡&#xff0c;战无不胜&#xff01; 作者介绍 随易出品&#xff0c;必属精品&#xff0c;只写有深度&#xff0c;有质…

vue 路由钩子

路由钩子分为三种 全局钩子&#xff1a; beforeEach、 afterEach、beforeResolve单个路由里面的钩子&#xff1a; beforeEnter组件路由&#xff1a;beforeRouteEnter、 beforeRouteUpdate、 beforeRouteLeave 它的三个参数&#xff1a; to: (Route路由对象) 即将要进入的目标…

【前端知识体系梳理(三)】Diff策略

​ 目录 &#x1f349;前言 &#x1f349;传统Diff算法 &#x1f349;React Diff &#x1f353;&#x1f353;&#x1f353;1、tree diff &#x1f353;&#x1f353;&#x1f353;2、component diff &#x1f353;&#x1f353;&#x1f353;3、element diff &#x1…

前端页面项目——博客系统

目录 1.实现博客列表页 1.1 实现导航栏 1.2 实现中间版心 1.3 实现个人信息 1.4 实现博客列表 2. 实现博客正文页 3. 实现博客登陆页 4. 实现博客编辑 4.1 实现编辑区 4.2 引入编辑器 展示 1&#xff09;登录页面 2&#xff09;博客列表页 3&#xff09;博客详情页 4&am…

【JavaScript】手撕前端面试题:手写Object.create | 手写Function.call | 手写Function.bind

&#x1f5a5;️ NodeJS专栏&#xff1a;Node.js从入门到精通 &#x1f5a5;️ 博主的前端之路&#xff08;源创征文一等奖作品&#xff09;&#xff1a;前端之行&#xff0c;任重道远&#xff08;来自大三学长的万字自述&#xff09; &#x1f5a5;️ TypeScript知识总结&…

PyQt5之进度条:QProgressBar

PyQt5之进度条&#xff1a;QProgressBar 在软件中&#xff0c;在处理特别冗长的任务时&#xff0c;如果没有相关的进度信息&#xff0c;这个等待的过程会比较考验用户的耐心&#xff0c;根据相关理论&#xff0c;进度条可以缓解用户在等待过程中的焦虑&#xff0c;所以&#x…

前端学习笔记(14)-Vue3组件传参

1.props&#xff08;父组件传递给子组件&#xff09;1.1 实现如果你没有使用 <script setup>&#xff0c;props 必须以 props 选项的方式声明&#xff0c;props 对象会作为 setup() 函数的第一个参数被传入&#xff1a;在子组件中&#xff1a;export default {props: {ti…

微信小程序头像昵称填写能力

1、基本介绍 微信小程序获取头像昵称的能力&#xff0c;最近又进行了一次调整&#xff0c;如果没有记错这是今年第三次调整了&#xff0c;每次调整每个开发者心中我相信都跟我一样&#xff0c;万马奔腾。。。今天写个demo体验下实际效果如何。 详细信息请见小程序用户头像昵称…

微信小程序实现PDF预览功能——pdf.js(含源码解析)

文章目录前言一、pdf.js 是什么&#xff1f;二、使用步骤1.下载库文件2.使用方式微信小程序端——使用 web-view 标签H5 端——使用 iframe 标签&#xff08;使用vue框架&#xff09;3.更改源码如何隐藏顶部工具栏如何让用户强制阅读一定时间如何获取pdf总页数如何获取pdf当前页…

【折腾电脑】Edge浏览器看B站视频卡顿最全解决办法合集

开头碎碎念&#xff1a;更新频率明显和疫情呈正相关&#xff0c;祝大家健健康康吃好喝好&#xff01; 使用Microsoft Edge浏览器观看B站视频&#xff0c;卡得无法忍受。 在网络上搜索相关问题&#xff0c;最早的一条是2016/04/17微软问题反馈的记录。任何原因的卡顿都是正常的&…

Vue样式穿透

Vue样式穿透 vue文件的style标签的scoped属性作用&#xff1a;PostCSS在元素标签上添加特殊属性值&#xff0c;在样式的选择器后面添加属性选择器&#xff0c;实现了组件样式的私有化&#xff0c;防止组件之间的样式污染&#xff08;比如相同类名的元素&#xff09;。 但在使…

【CSS】盒子模型内边距 ② ( 内边距复合写法 | 代码示例 )

文章目录一、内边距复合写法1、语法2、代码示例 - 设置 1 个值3、代码示例 - 设置 2 个值4、代码示例 - 设置 3 个值5、代码示例 - 设置 4 个值一、内边距复合写法 1、语法 盒子模型内边距 可以通过 padding-left 左内边距padding-right 右内边距padding-top 上内边距padding-…

前端开发服务器中的 Proxy 代理跨域实现原理解读

各位朋友你们好&#xff0c;我是桃小瑞&#xff0c;微信公众 桃小瑞。在这给大家拜个晚年&#xff0c;祝各位朋友新年快乐。 前言 在前端的开发过程中&#xff0c;尤其是在浏览器环境下&#xff0c;跨域是个绕不开的话题&#xff0c;相信每个前端都会涉及到这个问题&#xf…

“write javaBean error, fastjson version 1.2.83, class org.apache.shiro.web.servlet.ShiroHttpServletR

1. 相关技术 springboot 2.6.3mybatis-spring-boot-starter 2.2.2mybatis 3.5.10fastjson 1.2.83hutool-all 5.7.22shiro-spring 1.8.0 2. 报错信息 "write javaBean error, fastjson version 1.2.83, class org.apache.shiro.web.servlet.ShiroHttpServletRequest, meth…

<router-view> can no longer be used directly inside <transition> or <keep-alive>.

百度翻译&#xff1a; &#xff1c;router view&#xff1e;不能直接在&#xff1c;transition&#xff1e;或&#xff1c;keep alive&#xff1e;中使用。 改用插槽道具&#xff1a; 运行环境&#xff1a; "vue": "^3.2.8", "vue-router": &quo…

idea的vue文件中使用ElementUi组件

作为计算机专业的学生&#xff0c;在做实训项目时很惆怅前端页面的搭建&#xff0c;这个时候就突出到了组件的好处&#xff1b; 这篇就是给大家展示使用ElementUi组件&#xff01;&#xff01;&#xff01; 内容上分为vue3和之前的版本&#xff0c;自行选择&#xff01;&#x…

33.JavaScript映射与集合(Map、Set)数据类型基础知识介绍与使用

文章目录映射与集合&#xff08;Map、Set&#xff09;映射&#xff08;Map&#xff09;Map常用的方法不要使用map[key]访问属性对象作为Map的键Map的遍历与迭代默认的迭代方式forEach()从数组、对象创建Map从数组、Map创建对象集合&#xff08;Set&#xff09;集合迭代总结映射…