SpringBoot Web开发

文章目录

  • SpringBoot Web开发
    • 1. 静态资源访问
      • 1.1 静态资源目录
      • 1.2 静态资源访问前缀
    • 2. 自定义 Favicon
    • 3. 欢迎页支持
    • 4. Rest映射原理
    • 5. 请求映射原理
    • 6. 常用注解
      • 6.1 @PathVariable
      • 6.2 @RequestHeader
      • 6.3 @RequestParam
      • 6.4 @CookieValue
      • 6.5 @RequestAttribute
      • 6.6 @RequestBody
    • 7. 视图解析与模板引擎
      • 7.1 视图解析
      • 7.2 模板引擎-Thymeleaf
      • 7.3 Thymeleaf 基本语法
      • 7.4 Thymeleaf使用
        • 7.4.1 引入Stater
        • 7.4.2 SprinBoot自动配置Thymeleaf
        • 7.4.3 页面开发
    • 8. 拦截器
      • 8.1 实现HandlerInterceptor接口
      • 8.2 注册拦截器
      • 8.3 拦截器原理
    • 9. 文件上传

1. 静态资源访问

1.1 静态资源目录

  • 只要静态资源放在类路径下: called /static (or /public or /resources or /META-INF/resources
  • 访问 : 当前项目根路径/ + 静态资源名
  • 原理: 静态映射/**。

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

修改默认的资源访问目录:

resources:
# 配置是数组的形式,可以定义多个目录static-locations: [classpath:/test/]

1.2 静态资源访问前缀

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

当前项目 + static-path-pattern + 静态资源名

例如:http://localhost:8080/res/xxx.jpg

2. 自定义 Favicon

将Favicon放到静态资源目录下即可。

3. 欢迎页支持

  • 静态资源路径下 index.html

    • 可以配置静态资源路径
      - 但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问
  • 通过controller进行设置

4. Rest映射原理

根据源码分析直接得出结论:

Rest原理(表单提交要使用REST的时候)

  • 表单提交会带上 _method=PUT

  • 请求过来被 HiddenHttpMethodFilter拦截

    • 请求是否正常,并且是POST
    • 获取到**_method**的值。
      - 兼容以下请求;PUT.DELETE.PATCH
      - 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
      - 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper

补充:

Rest使用客户端工具,如PostMan直接发送Put、delete等方式请求,无需Filter。

5. 请求映射原理

实际上执行功能的类是DispatcherServlet中的doDispatch方法实现功能。

doDispatch方法中调用了getHandler方法获取应该处理请求的Handler或Controller:

通过循环依次遍历:

6. 常用注解

6.1 @PathVariable

@PathVariable用于映射URL绑定的占位符,使用@RequestMapping URI template 样式映射时,例如:xxx/{paramId},可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。

@GetMapping("/getUser/{userId}")
public String getUserId(@PathVariable("userId") Integer userId) {return "userId = " + userId;
}

6.2 @RequestHeader

@RequestHeader 是获取请求头中的数据,通过指定参数 value 的值来获取请求头中指定的参数值。

@GetMapping("/getHeader")
public String getHeader(@RequestHeader("User-Agent") String userAgent) {return "User-Agent: " + userAgent;
}

6.3 @RequestParam

@RequestParam获取请求参数

@GetMapping("/getParam")
public String getParam(@RequestParam("userId") Integer userId) {return "userId = " + userId;
}

6.4 @CookieValue

获取Cookie值

@GetMapping("/getCookieValue")
public String getCookieValue(@CookieValue("_ga") String _ga, @CookieValue Cookie cookie) {return "success";
}

6.5 @RequestAttribute

获取request域属性

@Controller
public class RequestController {@GetMapping("/goto")public String goToPage(HttpServletRequest request){request.setAttribute("msg","成功了...");request.setAttribute("code",200);return "forward:/success";  //转发到  /success请求}@GetMapping("/params")public String testParam(Map<String,Object> map,Model model,HttpServletRequest request,HttpServletResponse response){map.put("hello","world666");model.addAttribute("world","hello666");request.setAttribute("message","HelloWorld");Cookie cookie = new Cookie("c1","v1");response.addCookie(cookie);return "forward:/success";}///@RequestAttribute在这个方法被使用@ResponseBody@GetMapping("/success")public Map success(@RequestAttribute(value = "msg",required = false) String msg,@RequestAttribute(value = "code",required = false)Integer code,HttpServletRequest request){Object msg1 = request.getAttribute("msg");Map<String,Object> map = new HashMap<>();Object hello = request.getAttribute("hello");Object world = request.getAttribute("world");Object message = request.getAttribute("message");map.put("reqMethod_msg",msg1);map.put("annotation_msg",msg);map.put("hello",hello);map.put("world",world);map.put("message",message);return map;}
}

6.6 @RequestBody

获取请求体,注意是POST请求。

@PostMapping("/getRequestBody")
public String getRequestBody(@RequestBody String body) {return body;
}

7. 视图解析与模板引擎

在视图解析层面:SpringBoot默认不支持 JSP,需要引入第三方模板引擎技术实现页面渲染。

7.1 视图解析

视图的处理方式有三种:

  • 转发
  • 重定向
  • 自定义视图

视图解析的流程:

1、目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址。

2、方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在ModelAndViewContainer

3、任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址)。

4、processDispatchResult 处理派发结果(页面改如何响应)

  • 1、render(mv, request, response); 进行页面渲染逻辑

    • 1、根据方法的String返回值得到 View 对象【定义了页面的渲染逻辑】
    • 1、所有的视图解析器尝试是否能根据当前返回值得到View对象
      - 2、得到了 redirect:/main.html --> Thymeleaf new RedirectView()
      - 3、ContentNegotiationViewResolver 里面包含了下面所有的视图解析器,内部还是利用下面所有视图解析器得到视图对象。
      - 4、view.render(mv.getModelInternal(), request, response); 视图对象调用自定义的render进行页面渲染工作
    • RedirectView 如何渲染【重定向到一个页面】
      - 1、获取目标url地址
      - 2、response.sendRedirect(encodedURL);

7.2 模板引擎-Thymeleaf

Thymeleaf is a modern server-side Java template engine for both web and standalone environments.

Thymeleaf是用于Web和独立环境的现代服务器端Java模板引擎。

— 官方文档

7.3 Thymeleaf 基本语法

① 表达式

表达式名字 语法 用途
变量取值 ${...} 获取请求域、session域、对象等值
选择变量 *{...} 获取上下文对象值
消息 #{...} 获取国际化等值
链接 @{...} 生成链接
片段表达式 ~{...} jsp:include 作用,引入公共页面片段

② 字面量

  • 文本文字(Text literals): ‘one text’, ‘Another one!’,…
  • 数字文本(Number literals): 0, 12, 3.0, 12.3,…
  • 布尔文本(Boolean literals): true, false
  • 空(Null literal): null
  • 文字标记(Literal tokens): one , sometext

③ 文本操作

  • 字符串连接(String concatenation): +
  • 文本替换(Literal substitutions): |The name is ${name}|
<div th:class="'content'">...</div>
<span th:text="|Welcome to our application, ${user.name}!|">
//Which is equivalent to:
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
<span th:text="${onevar} + ' ' + |${twovar}, ${threevar}|">

④ 数学运算

  • 二元运算符(Binary operators): + , - , * , / , %

⑤ 布尔运算

  • 运算符: and , or
  • 一元运算: ! , not

⑥ 比较运算

  • 比较: > , < , >= , <= ( gt , lt , ge , le )
  • 等式: == , != ( eq , ne )

⑦ 条件运算符

  • If-then: (if) ? (then)

  • If-then-else: (if) ? (then) : (else)

  • Default: (value) ?: (defaultvalue)

⑧ 设置属性值-th:attr

  • 设置单个值
<form action="subscribe.html" th:attr="action=@{/subscribe}"><fieldset><input type="text" name="email" /><input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/></fieldset>
</form>
  • 设置多个值
<img src="../images/xxx.png"  th:attr="src=@{/images/xxx.png},title=#{logo},alt=#{logo}" />
  • 以上两个的代替写法 th:xxxx
<img src="../images/xxx.png"  th:attr="src=@{/images/xxx.png},title=#{logo},alt=#{logo}" />

⑨ 迭代

使用th:each

<tr th:each="prod : ${prods}"><td th:text="${prod.name}">Onions</td><td th:text="${prod.price}">2.41</td><td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'"><td th:text="${prod.name}">Onions</td><td th:text="${prod.price}">2.41</td><td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>

⑩ 条件运算

<a href="comments.html"
th:href="@{/product/comments(prodId=${prod.id})}"
th:if="${not #lists.isEmpty(prod.comments)}">view</a>
<div th:switch="${user.role}"><p th:case="'admin'">User is an administrator</p><p th:case="#{roles.manager}">User is a manager</p><p th:case="*">User is some other thing</p>
</div>

7.4 Thymeleaf使用

7.4.1 引入Stater

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

7.4.2 SprinBoot自动配置Thymeleaf

Thymeleaf 的自动配置类:ThymeleafAutoConfiguration :

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration { }

自动配好的策略:

  • 所有thymeleaf的配置值都在 ThymeleafProperties
  • 配置好了 SpringTemplateEngine
  • 配好了 ThymeleafViewResolver
  • 我们只需要直接开发页面

7.4.3 页面开发

首先要引入名称空间:

<html lang="en" xmlns:th="http://www.thymeleaf.org">

8. 拦截器

实现拦截请求功能的方式有两种:

  • 第一种是通过filter过滤器
  • 第二种就是配置HandlerInterceptor实现拦截器。

实现拦截器的大致流程:

  • 实现HandlerInterceptor接口
  • 注册自定义拦截器
  • 指定拦截规则(注意:如果是拦截所有,那么静态资源也会被拦截)

假设一个业务场景:

一个后台管理系统,第一次进入时需要登录,也就是说没有登录却访问主页面的请求会被拦截住。实现这个功能的方式就是通过拦截器来拦截没有登录的请求。

8.1 实现HandlerInterceptor接口

实现HandlerInterceptor接口重写其中的方法:

  • preHandle:方法执行之前拦截
  • postHandle:方法执行之后拦截
  • afterCompletion:页面渲染完成之后执行

注意: 要在自定义的拦截器实现类上标记@Component注解,将其添加到容器中; 同时拦截器的实现原理是对Controller层进行动态代理,所以拦截器拦截的是Controller层的方法。

package com.jc.admin.interceptor;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;@Slf4j
@Component
public class loginInterceptor implements HandlerInterceptor {/*** 方法执行之前拦截* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();Object loginUser = session.getAttribute("loginUser");if (loginUser != null) {log.info("用户已经登录,执行放行操作");return true;}// 用户没有登录,将请求转发到登录页session.setAttribute("msg", "请先登录!");// 获取请求调度程序,然后进行请求转发request.getRequestDispatcher("/").forward(request, response);return false;}/*** 方法执行之后拦截* @param request* @param response* @param handler* @param modelAndView* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("后置处理方法执行");}/*** 页面渲染完成之后执行* @param request* @param response* @param handler* @param ex* @throws Exception*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("视图渲染后方法执行");}
}

8.2 注册拦截器

注册拦截器这一步需要在配置类中进行,同时配置类需要实现addInterceptors方法。
同时注意,registry对象中的方法都是链式调用,其中有一个方法叫做order, 此方法中传入一个int类型的值,值越小的拦截器就越先执行(从0开始)。

package com.jc.admin.config;import com.jc.admin.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class AdminWebConfig implements WebMvcConfigurer {@AutowiredLoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**") // 添加要拦截的内容.excludePathPatterns("/","/login", "/css/**", "/fonts/**", "/images/**", "/js/**");// 排除要拦截的内容}
}

8.3 拦截器原理

  1. 根据当前请求,找到HandlerExecutionChain(可以处理请求的handler以及handler的所有 拦截器)
  2. 先来顺序执行 所有拦截器的 preHandle()方法。
    • 如果当前拦截器preHandle()返回为true。则执行下一个拦截器的preHandle()
    • 如果当前拦截器返回为false。直接倒序执行所有已经执行了的拦截器的 afterCompletion();
  3. 如果任何一个拦截器返回false,直接跳出不执行目标方法。
  4. 所有拦截器都返回true,才执行目标方法。
  5. 倒序执行所有拦截器的postHandle()方法。
  6. 前面的步骤有任何异常都会直接倒序触发 afterCompletion()
  7. 页面成功渲染完成以后,也会倒序触发 afterCompletion()

9. 文件上传

Controller层的方法参数中放置MultipartFile类型的属性。

  • 页面中上传文件的表单:
<form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data"><div class="form-group"><label for="exampleInputEmail1">邮箱</label><input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email"></div><div class="form-group"><label for="exampleInputPassword1">名字</label><input type="text" name="username" class="form-control" id="exampleInputPassword1" placeholder="Password"></div><div class="form-group"><label for="exampleInputFile">头像</label><input type="file" name="headerImg" id="exampleInputFile"></div><div class="form-group"><label for="exampleInputFile">生活照</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">提交</button>
</form>
  • **实现文件上传的Controller: **
@Controller
public class FormController {@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()) {// 保存文件操作:保存到本地或者OSSString filename = headerImg.getOriginalFilename();headerImg.transferTo(new File("E:\\springboot-study\\uploadfile" + filename));}if (photos.length > 0) {for (MultipartFile photo : photos) {String filename = photo.getOriginalFilename();photo.transferTo(new File("E:\\springboot-study\\uploadfile" + filename));}}return "main";}
}
  • 通过修改配置文件可以自定义上传问价大小(如果上传超过阈值的文件,会抛出异常)
# 上传文件最大大小
spring.servlet.multipart.max-file-size=10MB
# 一次请求中上传的所有文件最大大小
spring.servlet.multipart.max-request-size=100MB

SpringBoot Web开发相关推荐

  1. springboot:web开发-Thymeleaf

    1.thymeleaf依赖 <dependency><groupId>org.thymeleaf</groupId><artifactId>thymel ...

  2. Spring Boot与Web开发简介||SpringBoot对静态资源的映射规则

    Web开发 1.简介 使用SpringBoot: 1).创建SpringBoot应用,选中我们需要的模块: 2).SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运 ...

  3. Web开发静态资源处理---SpringBoot

    Web开发静态资源处理 使用SpringBoot的步骤: 1.创建一个SpringBoot应用,选择我们需要的模块,SpringBoot就会默认将我们的需要的模块自动配置好 2.手动在配置文件中配置部 ...

  4. Springboot的web开发-静态资源

    1.web开发简介 SpringMVC自动配置概览 Spring Boot provides auto-configuration for Spring MVC that works well wit ...

  5. springboot thymeleaf配置_【程序源代码】Spring Boot 开发笔记web开发实战1

    关键字:<Spring Boot 开发笔记>系列文章 各位亲爱的小伙伴:大家好! <Spring Boot 开发笔记>系列文章 这套笔记和源码是我自己在学习springboot ...

  6. 史上最全SpringBoot教程,从零开始带你深入♂学习(四)——web开发

    Springboot(四)--web开发 静态资源 四个目录存放的静态资源可以被我们识别,用来存放我们的html.css.js.图片等文件 "classpath:/META-INF/reso ...

  7. SpringBoot 之 Web开发

    2.Web开发 2.1.SpringMVC自动化配置概述 Spring Boot provides auto-configuration for Spring MVC that works well ...

  8. springboot系列课程笔记-第四章-WEB开发

    四.Web开发 1.简介 使用SpringBoot: 1).创建SpringBoot应用,选中我们需要的模块: 2).SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可 ...

  9. Springboot学习笔记(二)Web开发

    前言: 学习B站UP主狂神说视频笔记整理视频链接 狂神笔记链接 上篇笔记链接-Springboot学习笔记(一)快速上手 Web开发 静态资源 在以往的SpringMVC中所有静态资源或者页面应该放在 ...

  10. SpringBoot的Web开发入门案例1

    SpringBoot的Web开发入门案例1-登录和页面数据遍历读取 新建maven项目:logintest pom.xml文件: <project xmlns="http://mave ...

最新文章

  1. 重磅!国内首个缺陷检测教程:理论、源码与实战
  2. linux ip -o,linux IP 命令使用举例
  3. 使用指针字符串查找字串的个数
  4. legend3---lavarel常用artisan命令操作
  5. UA MATH566 用Basu定理证明统计量不完备
  6. Codeforces Global Round 14 E. Phoenix and Computers 思维 + dp
  7. 第8章 硬盘和显卡的访问与控制
  8. 为什么换工作?(面试必问问题)
  9. 190304每日一句
  10. Vensim系统建模论文阅读-Information diffusion through social networks: The case of an online petition
  11. 星空主题设计理念_新加坡设计师—宇宙艺术主题展厅概念设计方案
  12. 阿里巴巴编程考试认证java编程规范+考试分享
  13. 微信 8.0 「裂开」「炸弹」的特效代码
  14. Linux 查看文件格式和更改文件格式
  15. vtp服务器作用,VTP
  16. 文献阅读: 基因组选择技术在农业动物育种中的应用
  17. 如果一个n位正整数等于它的n个数字的n次方和,则称该数为n位自方幂数。编程计算并输出所有的n的所有情况。
  18. Kotlin里的takeIf和takeUnless
  19. vue给html动态添加属性,Vue中怎么动态添加类名?
  20. php imap函数详解,Imap是什么意思,php imap 函数详解

热门文章

  1. 重庆云阳2021云中高考成绩查询,重庆云阳中学2021年招生简章
  2. 做硬件,真的没前途吗?看看资深工程师是怎么说的
  3. 车联网智能终端GB/T 32960国标协议规范 、国标新能源车联网终端GB/T32960标准T-BOX应用
  4. iOS 相机调用后为英文的解决办法
  5. 手把手教你写电商爬虫-第五课 京东商品评论爬虫 一起来对付反爬虫
  6. 小罗说敏捷 | 使用关键路径法优化项目进度管理
  7. linux系统输入法进程怎么关闭,快速解决linux下中文输入法问题
  8. SkipList(跳跃表)详解
  9. MOSFet cutoff frequency ( From google)
  10. python 声音指纹识别,Python-samp中的Dejavu音频指纹识别