- Spring Boot的Web开发支持
- Thymeleaf模版引擎
- Spring和Thymeleaf的整合
- Spring Boot对Thymeleaf支持
- Spring Boot对JSP的支持
- Spring Boot对JSON的支持
- Spring Boot的文件上传下载
- Spring Boot的异常处理
- Spring Boot的Web开发支持
Spring Boot的Web开发内嵌了Servlet容器,并结合SpringMVC来完成
spring-boot-starter-web包含了Spring Boot预定义的一些Web开发的常用依赖包,为开发者提供了嵌入的Tomcat以及SpringMVC的依赖,与Web相关的自动配置支持则保存在spring-boot-autoconfigure.jar的org.springframework.boot.autoconfigure.web下面
MultipartAutoConfiguration和MultipartProperties用来自动配置上传文件的属性
- Thymeleaf模版引擎
Spring Boot建议使用HTML来完成动态页面,官方推荐使用Thymeleaf模版引擎来完成动态页面,并且为Thymeleaf提供了完美的SpringMVC支持
Thymeleaf是面向Web和独立环境的现代服务器端Java模版引擎,能够处理HTML、XML、JavaScript、CSS甚至纯文本,可以作为MVC Web应用层的View层显示数据
Spring Boot官方推荐使用Thymeleaf完全替代JSP,以下JSP代码片段不能在模版被解析之前通过浏览器直接显示,而Thymeleaf可以
//JSP
<form:inputText name=“username” value=“${user.username}”/>
//Thymeleaf
<input type=“text” name=“username” value=“fkjava” th:value="${user.username}"/>
引入Thymeleaf首先要改写html标签🏷️,这样才可以在其他标签中使用th:*这样的语法
<html xmlns:th=“http://www.thymeleaf.org">
通过xmlns:th=“http://www.thymeleaf.org"命名空间,引入Thymeleaf模版引擎,将静态页面转换为动态页面,需要进行动态处理的元素都使用th:为前缀
Thymeleaf对于URL的处理是通过语法@{…}来处理的
<a th:href=“@{http://www.baidu.com}”>绝对路径</a>
<a th:href=“@{/}”>相对路径</a>
<a th:href=“@{css/bootstrap.min.css}”>Content路径,默认访问static下的css文件夹</a>
${x}将返回存储在thymeleaf上下文中的变量x或作为请求Request作用域中的属性,$表达式只能写在th标签内部,否则不会生效
${param.x}:返回一个名为x的请求参数(可能是多值的)
${session.x}:返回一个名为x的会话HttpSession作用域中的属性
${application.x}:返回一个名为x的全局ServletContext上下文作用域中的属性
在表达式中可以使用各类算术运算符,注意⚠️,<和>应该使用它们的HTML转义符
条件判断:th:if(只有条件成立才显示)、th:unless(只有条件不成立才显示)、多路选择switch(default用*表示)
循环变量集合使用th:each标签,用于迭代循环,迭代对象可以是java.util.List、java.util.Map、数组,interStat表示状态变量
// th:if
<a th:href=“main.html” th:if=“${username!=null}”>Login1</a><br>
// switch
<div th:switch="${role}”>
<p th:case=“‘admin’”>User is an administrator</p>
<p th:case=“‘manager’”>User is a manager</p>
<p th:case=“‘*’”>User is some other thing</p>
</div>
// th:each
th:each=“obj,iterStat:${objList}"
<tr>行、<td>列、<th>表头单元格
Thymeleaf提供了很多内置对象(一般以s结尾),通过#直接访问,如#dates(日期格式化内置对象),#numbers,#strings
使用内置对象dates的format函数即可对日期进行格式化
<span th:text=“${#dates.format(curDate,’yyyy-mm-dd HH:mm:ss')}”></span>
//获取变量str的长度
<span th:text=“${#strings.length(str)}”></span>
- Spring和Thymeleaf的整合
使用SpringMVC的@Controller注解来映射Thymeleaf的模版文件
访问应用context中的Beans可以使用SpringEL语法:${@myBean.doSomething()}
- Spring Boot对Thymeleaf支持
Spring Boot通过org.springframework.boot.autoconfigure.thymeleaf包对Thymeleaf进行自动配置,其中最重要的是ThymeleafAutoConfiguration和ThymeleafProperties
ThymeleafAutoConfiguration类:对集成所需要的Bean进行自动配置,包括templateEngine和templateResolver的配置
templateEngine:用来执行在SpringMVC中使用的Thymeleaf模版引擎
templateResolver:用来设置通用的模版引擎
二者使得开发者在SpringMVC中集成Thymeleaf变得非常简单
ThymeleafProperties类:读取application.properties配置文件,设置Thymeleaf的属性以及默认配置,可以通过application.properties对默认设置进行修改
模版的类型设置,默认为text/html
- Spring Boot的Web开发实例
前端开发的开源工具包:Bootstrap,完成页面排版
Javascript框架:JQuery
MVC框架:Spring MVC
1、创建一个Maven项目,在src/main下新建resources,并在src/main/resources下再新建static和templates
2、添加spring-boot-starter-web模块依赖,添加spring-boot-starter-thymeleaf模块依赖
3、引入静态文件,将Bootstrap的脚本样式、项目所需图片等放在src/main/resources/static下
4、在src/main/resources/templates下心间一个页面文件index.html
class="container":用于固定宽度并支持响应式布局的容器
class="row":栅格系统用于通过一系列的行与列的组合来创建页面布局
class="form-horizontal":将label标签和控件组水平并排布局
class="form-inline":多个控件可以排列在同一行,水平
class="input-group":用于将图片和控件放在一组
btn-group-justified:能够让按钮组根据父容器尺寸来设定各自相同的尺寸,采用响应式布局技术从而有利于移动端的用户体验
@Controller注解:用于指示该类是一个控制器
@RequestMapping注解:用于映射请求的URL
返回的是字符串“index”,由于Thymeleaf默认的前缀是“class:/templates”,后缀是“html”,所以该请求返回的是“classpath:/templates/index.html”
1. | IndexController.java | @RequestMapping("/") return "index" |
2. | index.html | <a th:href="@{test?loginName=jack&password=123}">测试</a> |
3. | ThymeleafController.java | @RequestMapping("/test") request.setAttribute("book1","讲义") //将数据保存到request作用域中 session.setAttribute("book2","讲义") //将数据保存到session作用域中 request.getServletContext().setAttribute("book3","讲义") //将数据保存到ServletContext(application)作用域中 return "success1" |
4. | success1.html | ${param.loginName[0]},${param.password[0]} ${book1} ${session.book2} ${application.book3} |
Spring MVC更推荐使用WebRequest:
webRequest.setAttribute("book1","讲义",webRequest.SCOPE_REQUEST);
public class Book implements Serializable
List<Book> books = new ArrayList<>();
books.add(new Book(1,"讲义","作者",56.00));
class="table table-responsive":响应式表格,在一个表中展示所有数据,当不够显示的时候可以左右滑动浏览
table-bordered:为表格和其中的每个单元格增加边框
table-hover:可以让<tbody>中的每一行对鼠标悬停状态做出响应
- Spring Boot对JSP的支持
Spring Boot建议使用HTML来完成动态页面,但是由于大多数Java Web项目之前的页面展示层使用JSP来完成,所以Spring Boot同时也支持使用JSP。
1、创建一个Maven Web项目,创建完成的项目有错误,这是因为没有加入JSP的支持
2、修改pom.xml文件,加入Servlet、JSTL(JSP Standard Tag Library,JSP标准标签库)、Tomcat的依赖
3、在resources下创建application.properties配置文件,添加页面配置信息,使之支持JSP
#页面默认前缀目录
spring.mvc.view.prefix=/WEB-INF/jsp/
#响应页面默认后缀
Spring.mvc.view.suffix=.jsp
4、IndexController.java:将一个username保存到model中:model.addAttribute("username","软件")
5、在webapp/WEB-INF/下新建一个jsp目录,并重新创建一个index.jsp文件
${requestScope.username}:EL表达式,<c:forEach></c:forEach>:JSTL标签库
- Spring Boot处理JSON数据
几乎所有的项目都要用到JSON,Spring Boot内置了JSON解析功能(默认Jaskson解析器,也可以换成阿里的Fastjson或者其他JSON解析器),当Controller返回的是一个Java对象或者是List集合时,Spring Boot自动将其转换成JSON数据
1. | AppController.java | @RequestMapping(value="/index") return "index" |
2. | index.html | ${document}.ready(function(){findbook();}); function findBook(){$.ajax("/findBook",......);}; dataType:"json" //预期服务器返回的数据类型 type:"post" //请求方式POST或GET contentType:"application/json" //发送信息至服务器时的内容编码类型 data:JSON.stringify({id:1,name:"书名"}) //发送到服务器的数据【发送的一个JSON数据】 async:true //默认所有请求均为异步请求 success:function(data) //【返回的JSON数据】 |
3. | BookController.java | @RequestMapping("/findBook") @RequestBody Book book book.setPrice(58.00); |
使用JQuery发送JSON数据,页面载入时调用findBook函数,findBook函数发送异步请求到“/findBook”
@RequestBody Book book表示,使用@RequestBody注解获取页面传递的JSON数据(前台JSP页面的JSON数据中传递了id和name)
index.html页面载入时会发送Ajax请求,传递JSON数据,BookController接收到请求后,@RequestBody注解会将JSON数据设置到Book参数对应的属性当中
转换集合数据:略
- Spring Boot的文件上传下载
需将表单的method设置为POST,将enctype设置为multipart/form-data,只有这样,浏览器才会把用户所选文件的二进制数据发送给服务器,一旦设置enctype为multipart/form-data,浏览器将采用二进制流的方式来处理表单数据
Spring MVC的文件上传还需要依赖Apache Commons FileUpload组件,Spring Boot的spring-boot-starter-web已经集成了Spring MVC,所以使用Spring Boot完成文件上传下载更加简单
1、修改pom.xml文件,引入Apache Commons依赖
2、负责文件上传的表单和一般表单有些区别,表单的编码类型必须是“multipart/form-data”类型
<form class=“form-horizontal” action=“upload” enctype=“multipart/form-data” method=“post”></form>
3、上传文件会自动绑定到MultipartFile中:@RequestParam("file") MultipartFile file
上传文件路径(保存到的路径):String path = requset.getServletContext().getRealPath("/upload/");
当前项目部署在Web服务器路径下的“upload”文件夹
上传文件名(被选中文件的名称):String filename = file.getOriginalFilename();
将文件保存到目标文件中:file.transferTo(new File(path + File.separator + filename));
MultipartFile提供了获取上传文件内容、文件名的方法,通过transferTo()方法还可以将文件存储到磁盘当中
默认上传文件大小是1MB,当上传文件超过1MB时就会报错,可以在application.properties中设置上传文件的参数:
#单个文件大小
Spring.http.multipart.maxFileSize=50MB
#总上传的数据大小
Spring.http.multipart.maxRequestSize=50MB
上传的文件会作为对象的属性保存,对象(实体):
public class User implements Serializable {
private String username;
private MultipartFile headPortrait;
……
}
属性headPortrait对应页面html的file类型,类型为MultipartFile,上传文件会自动保存到headPortrait属性中
1. | registerForm.html | multipart/form-data |
2. | FileUploadController.java | @RequestMapping(value="/register") @ModelAttribute User user,Model model String path = requset.getServletContext().getRealPath("/upload/"); String filename = user.getHeadPortrait().getOriginalFilename(); user.getHeadPortrait().transferTo(new File(path + File.separator + filename)); model.addAttribute("user",user) //将用户添加到model return "userInfo" |
3. | userInfo.html | @{'upload/'+${user.headPortrait.originalFilename}} ${user.username} @{download(filename=${user.headPortrait.originalFilename})} |
使用@ModelAttribute注解将表单参数绑定到User对象,html控件的username会保存到User对象的username属性,html控件的headPortrait会保存到User对象的headPortrait属性,转换为MultipartFile类型
文件上传成功后将用户信息保存到model当中
测试:http://localhost:8080/registerForm
文件下载:
在页面上给出一个超链接,该链接的href属性等于要下载文件的文件名,进入download控制器进行文件下载
Spring MVC提供了一个ResponseEntity类型,可以很方便的定义返回的HttpHeaders和HttpStatus
1. | FileDownloadController.java | @RequestMapping(value="/download") public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename, @RequestHeader("User-Agent") String userAgent, Model model ) BodyBuilder builder = ResponseEntity.ok(); //ok表示HTTP中的状态200 二进制流数据:APPLICATION_OCTET_STREAM return builder.body(FileUtils.readFileToByteArray(file)); |
download处理方法:接受到页面传递的文件名filename后,使用Apache Commons FileUpload组件的FileUtils读取项目的upload文件夹下的该文件,并将其构建成ResponseEntity对象返回客户端下载
- Spring Boot的异常处理
1、@ExceptionHandler处理异常:
1. | index.html | href="@{hello}" //抛出异常不做任何处理 href="@{test}" //使用@ExceptionHandler注解处理异常 |
2. | TestController.java | Controller使用@ExceptionHandler注解处理异常,而不会抛给Servlet容器 @ExceptionHandler(value=Exception.class) //value属性表示处理的异常类型 如果在一个Controller中有一个用@ExceptionHandler修饰的方法,当Controller的任何一个方法抛出异常时,都由@ExceptionHandler注解修饰的方法处理异常 |
2、父类Controller处理异常:
可以将异常处理方法向上移到父类中,然后所有的Controller统一继承父类即可
BaseController.java:
public ModelAndView defaultErrorHandler(HttpServletRequest req,Exception e)
ModelAndView mav = new ModelAndView();
mav.addObject("exception",e);
mav.addObject("url",req.getRequestURL());
mav.setViewName("error"); //跳转到error.html页面
UserController.java:
public class UserController extends BaseController
3、Advice处理异常返回JSON
@ControllerAdvice注解的类是当前项目中所有类的统一异常处理类,只需在@ExceptionHandler之后加入@ResponseBody,就能将处理方法返回的Map集合转换为JSON格式
@ControllerAdvice
@ExceptionHandler(value=Exception.class)
@ResponseBody
@ControllerAdvice是最方便的,如果返回的是View(视图),方法的返回值是ModelAndView;如果返回的是String或者JSON数据,那么只需要在方法上添加@ResponseBody注解就可以了