SpringBoot2零基础到精通之数据与页面响应
作者:扎哇太枣糕 发布时间:2022-08-25 22:26:41
1 数据响应
  数据响应一般分为两种:页面响应和数据响应,一般来说页面响应是用来开发一些单体项目(也就是前后端都在一个开发工具中),而数据响应则是用来进行前后端分离开发的项目,前端发送过来请求后端响应相应的数据。
1.1 数据响应(JSON为例)
  如果想让SpringMVC响应返回一个JSON类型的数据,首先需要在项目的pom.xml文件中导入web场景的启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--web场景的启动器的底层导入了JSON的开发场景-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.6.4</version>
<scope>compile</scope>
</dependency>
  其次就是在controller中加入@ResponseBody注解,这样的话就是响应数据而不是页面跳转,或者将controller上的@Controller注解换成@RestController,相当于这个controller下的所有方法都自动加上了@ResponseBody注解。
1.2 数据响应之内容协商
内容协商: 服务器会根据客户端接收能力的不同,返回不同媒体类型的数据。
原理: 前端发送请求的时候请求头携带Accept字段,用于服务器声明自己(客户端)能够接收的数据类型。
处理流程: 首先判断当前响应头中是否已经有之前处理时缓存的媒体类型,如果没有的话就是第一次处理需要确定处理的媒体类型,通过Accept字段获取客户(PostMan、浏览器)支持接收的内容类型。经过遍历循环所有当前系统的MessageConverter看谁支持操作这个对象(Person),找到支持操作Person的converter之后把它支持的媒体类型统计出来。如此操作我们就得到了客户端支持接受的类型和服务端能够返回的类型,再通过内容协商的最佳匹配媒体类型,用支持将对象转为最佳匹配媒体类型converter。
2 页面响应
  SpringBoot默认的打包方式是jar包方式,但是JSP不支持在jar包(一种压缩包)中编译,所以SpringBoot默认不支持JSP,于是我们需要引入第三方的模板引擎技术——Thymeleaf实现页面的渲染。
2.1 模板引擎之Thymeleaf
  要想使用Thymeleaf实现页面的渲染的话,首先需要在pom.xml文件里引入它的场景启动器依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  在导入场景启动器之后,SpringBoot就会给我们在ThymeleafAutoConfiguration自动配置类中配置好所有的相关组件,并将相关配置项与ThymeleafProperties.class(代码如下)通过注解@EnableConfigurationProperties相关联,配置类中设置了默认页面跳转的前缀和后缀,也就是规范了页面存放的位置必须是templates文件夹和页面的文件后缀必须是.html,我们只需要直接开发页面即可。
private String prefix = "classpath:/templates/";
private String suffix = ".html";
入门案例
第一步: templates文件夹下建个html文件
第二步: <html>标签引入templates命名空间,这样的优点就是在进行页码编写的时候会有相关的提示信息
xmlns:th="http://www.thymeleaf.org"
第三步: 创建一个controller用于进页面跳转
@Controller
public class ViewTestController {
@GetMapping("/jump")
public String jumpTo(Model model) {
// 之前讲过model的所有属性值都会存储在request域中,需要使用的时候直接使用
model.addAttribute("msg", "你好,张三");
model.addAttribute("link", "http://www.baidu.com");
return "seccess";
}
}
第四步: 编写页面代码获取域中的值
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${msg}">哈哈</h1>
<h2>
<a th:href="${link}" rel="external nofollow" >点击进入百度</a>
<a th:href="@{link}" rel="external nofollow" >点击进入百度</a>
</h2>
</body>
</html>
⚠  页面中两种符号区别:${}是直接获取到link属性的值作为链接地址,而@{}是拼装项目的访问路径+符号里的值,对本案例而言:第一个链接是打开百度,第二个是发送http://localhost:8080/link的请求
2.2 *
  用户登陆成功之后,再发送任意请求的时候都应该是有个登录判断的过程(判断session中是否有正确的用户名和密码),这个功能可以在每个controller使用代码进行判断,但是这个过程是重复的会大大增加代码的冗余,于是我们可以将判断功能放在 * 中,将登陆成功后的所有从页面发送的请求拦截住进行用户判断,成功则放行失败则返回登录。 以上述例子为例讲解 * 的使用:
第一步: 自定义 * (实现HandlerInterceptor接口,重写内置方法在相应的方法内编写判断逻辑)
public class LoginInterceptor implements HandlerInterceptor {
// 在目标方法执行之前执行的方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 实现登录检查的逻辑
HttpSession session = request.getSession();
Object user = session.getAttribute("loginUser");
if (user != null) {
// 已经登录,放行
return true;
}
// 未登录,重定向到登录页面
request.setAttribute("msg", "请先登录之后再进行相关操作");
request.getRequestDispatcher("/").forward(request, response);
return false;
}
// 在目标方法执行之后执行的方法
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
// 页面渲染之后执行的方法
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
第二步: 自定义配置类实现WebMvcConfigurer接口,重写addInterceptors方法将 * 注册进容器中,并指定拦截规则
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 有个问题就是, * 拦截的不只是动态请求,还有静态的页面资源和样式,所以也要将静态资源放行
registry.addInterceptor(new LoginInterceptor())
// 拦截所有的请求
.addPathPatterns("/**")
// 直接放行的请求
.excludePathPatterns("/", "/login", "/css/**", "/fonts/**", "/js/**", "/images/**");
}
}
2.3 文件上传
  文件上传需要前后端的协调配合,前端使用一个form表单提交所有的信息,包括单文件上传和多文件上传,后端使用注解获取到表单中的所有值,对他们进行操作 前端表单:
<form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data">
<!--email邮箱-->
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
<!--userName用户名-->
<div class="form-group">
<label for="exampleInputPassword1">userName</label>
<input type="text" name="userName" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<!--单文件上传 头像-->
<div class="form-group">
<label for="exampleInputFile">headerImg</label>
<input type="file" name="headerImg" id="exampleInputFile">
</div>
<!--多文件上传 生活照-->
<div class="form-group">
<label for="exampleInputFile">image of yourself</label>
<input type="file" name="photos" multiple >
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
后端controller:
@PostMapping("/upload")
public String upload(@RequestParam("email") String email,
@RequestParam("userName") String userName,
@RequestPart("headerImg")MultipartFile headerImg,
@RequestPart("photos")MultipartFile[] photos) throws IOException {
// 将头像保存到本地磁盘中
if (!headerImg.isEmpty()) {
// 创建相应的文件夹
File file1 = new File("E:\\bootTest\\" + userName + "\\headerImg");
file1.mkdirs();
// 获取图片名 生成存储路径
headerImg.transferTo(new File("E:\\bootTest\\" + userName + "\\headerImg\\" + headerImg.getOriginalFilename()));
}
// 将生活照保存到本地磁盘中
if (photos.length > 0) {
// 创建相应的文件夹
File file1 = new File("E:\\bootTest\\" + userName + "\\photos");
file1.mkdirs();
// 存储图片
for (MultipartFile photo:photos) {
if (!photo.isEmpty()) {
// 获取图片名 生成存储路径
photo.transferTo(new File("E:\\bootTest\\" + userName + "\\photos\\" + photo.getOriginalFilename()));
}
}
}
return "index";
}
文件上传的配置:
# 文件上传大小的设置
spring:
servlet:
multipart:
# 单个文件的最大大小
max-file-size: 50MB
# 总文件的最大大小
max-request-size: 100MB
来源:https://blog.csdn.net/qq_59138417/article/details/123298818
猜你喜欢
- 目录Directory:创建文件夹删除文件夹获取文件夹下的子文件夹获取同类型的文件判断文件夹是否存在移动文件夹总结之前发过File对文件的操
- 一.利用二进制状态法求排列组合,此种方法比较容易懂,但是运行效率不高,小数据排列组合可以使用import java.util.Arrays;
- 一. 封装封装是面向对象的三大特性之一;面向对象程序三大特性:封装、继承、多态 。封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和
- 一:什么是逆行工程。MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDB
- Android中的线程池ThreadPoolExecutor解决了单线程下载数据的效率慢和线程阻塞的的问题,它的应用也是优化实现的方式。所以
- 相对于Swing来说,JavaFX在UI上改善了很多,不仅可以通过FXML来排版布局界面,同时也可以通过CSS样式表来美化UI。其实在开发J
- 本文实例讲述了Android MediaPlayer基本使用方法。分享给大家供大家参考,具体如下:使用MediaPlayer播放音频或者视频
- C#中如何给Excel添加水印我们知道Microsoft Excel并没有内置的功能直接给Excel表添加水印,但是其实我们可以用其他变通的
- Android自带的跑马灯效果不太好控制,还必须要满足条件才能有效果,而且速度不受控制。前面我的博客中有一篇就是用Android自带的跑马灯
- 使用datatables自带后台查询 前台代码:<!DOCTYPE html><html><head>&
- MyBatis多数据源配置(读写分离)首先说明,本文的配置使用的最直接的方式,实际用起来可能会很麻烦。实际应用中可能存在多种结合的情况,你可
- 代码从windows下visual studio到andriod平台迁移实现步骤:前言前言也是迁言,从windows的visual stud
- Java5以后开始支持枚举类型,枚举类型使用起来非常方便,其重要的作用是作为类型安全使用的。如果在不考虑系统内存开销的情况下大量的使用枚举也
- @[toc]在之前的文章中松哥和小伙伴们聊过,正在执行的流程信息是保存在以 ACT_RU_ 为前缀的表中,执行完毕的流程
- @Profiles和@PropertySource根据环境切换配置文件使用@PropertySource注解加载配置文件,并制定解析配置文件
- SpringMVC * 介绍springMVC 中的 * 用于拦截控制器方法的执行。先创建出前置需要的一些条件:<a th:href=
- 目录一. 先简单总结一下比较常见的几个解决方案的弊端:1. IMEI2. Android ID3. MAC地址二. uuid + 本地文件,
- 主从表关联查询,返回对象带有集合属性昨天有同事让我帮着看一个问题,mybatis主从表联合查询,返回的对象封装集合属性。我先将出现的问题记录
- 本文实例为大家分享了android自定义波浪加载动画的具体代码,供大家参考,具体内容如下效果图1.自定义控件 WaveViewpackage
- 一、概要我们可以用java实现简单的登录界面。如上效果,直观但也需要一步一步来完成,从界面弹窗的设置,图片的插入,文本框的设置,到登录的按钮