在Web开发中,会涉及到静态资源的访问支持、视图解析器的配置、转换器和格式化器的定制、文件上传下载等功能,甚至还需要考虑到与Web服务器关联的Servlet相关组件的定制,Spring Boot框架支持整合一些常用Web框架从而实现Web开发,并默认支持Web开发中的一些通用功能。

SpringMVC整合支持

Spring MVC 自动配置介绍

在Spring Boot项目中,一旦引入了Web依赖启动器spring-boot-starter-web,那么Spring Boot整合Spring MVC框架默认实现的一些XxxAutoConfiguration自动配置类就会自动生效,几乎可以在无任何额外配置的情况下进行Web开发。

Spring Boot整合Spring MVC 的自动化配置功能特性

  1. 内置了两个视图解析器:ContentNegotiatingViewResolver和BeanNameViewResolver;
  2. 支持静态资源以及WebJars;
  3. 自动注册了转换器和格式化器;
  4. 支持Http消息转换器;
  5. 自动注册了消息代码解析器;
  6. 支持静态项目首页index.html;
  7. 支持定制应用图标favicon.ico;
  8. 自动初始化Web数据绑定器ConfigurableWebBindingInitializer。

Spring MVC 功能拓展实现案例

1.项目基础环境搭建

使用Spring starter project方式创建Spring Boot项目,并在Dependencies依赖选择中选择Web依赖启动器和Thymeleaf依赖启动器

将上一章节中编写好的文件复制到本章项目对应目录下,项目初始化结构图如下

功能一:注册视图控制器

创建一个实现WebMvcConfigurer接口的配置类MyMVCconfig,用于对MVC框架功能扩展

@Configuration
public class MyMVCconfig implements WebMvcConfigurer {@Overridepublic void addViewControllers(ViewControllerRegistry registry) {//将/toLoginPage和/login.html请求路径都映射到login.html页面registry.addViewController("/toLoginPage").setViewName("login");registry.addViewController("/login.html").setViewName("login");}}

注释掉之前创建的用户登录控制类LoginController,启动项目,在浏览器上分别访问http://localhost:8080/toLoginPage和http://localhost:8080/login.html

总结:只适合较为简单的无参数get请求跳转,对于有参数或者需要业务处理的跳转需求,最好采用传统方式。

功能二:注册自定义拦截器MyInterceptor

实现HandlerInterceptor 接口,在该类中编写如下方法

@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 获取请求路径String requestURI = request.getRequestURI();// 获取登录用户Object loginUser = request.getSession().getAttribute("loginUser");// 如果请求路径是“/admin”开头的,并且用户没有登录,那么将请求重定向到登录页面if (requestURI.startsWith("/admin") && loginUser == null) {response.sendRedirect("/toLoginPage");return false;}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {// 向request域中存放当前年份用于页面动态显示request.setAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR));}}

在自定义配置类MyMVCconfig中,重写addInterceptors()方法注册自定义的拦截器

@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/login.html");}

效果测试

重启项目,启动成功后,在浏览器上访问http://localhost:8080/admin

SpringBoot整合javaweb三大件

目的:注册自定义的Servlet、Filter、Listener组件到springboot内嵌的Servlet容器,让它们发挥自己的作用

使用组件注册方式整合Servlet

1.创建com.itheima.servlet.component包及一个自定义Servlet类MyServlet,使用@Component注解将MyServlet类作为组件注入Spring容器。MyServlet类继承自HttpServlet,通过HttpServletResponse对象向页面输出“hello MyServlet”。

@Component
public class MyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {resp.getWriter().write("hello MyServlet");}
}

2.在com.itheima.config下创建Servlet组件配置类ServletConfig,来注册Servlet组件

@Configuration
public class ServletConfig {// 注册servlet组件@Beanpublic ServletRegistrationBean getServlet(MyServlet myServlet) {ServletRegistrationBean registrationBean =new ServletRegistrationBean(myServlet, "/myServlet");return registrationBean;}
}

3.重启项目,启动成功后,在浏览器上访问http://localhost:8080/myServlet

使用组件注册方式整合Filter

1.在com.itheima.servletComponent包下创建一个自定义Filter类MyFilter,使用@Component注解将当前MyFilter类作为组件注入到Spring容器中。MyFilter类实现Filter接口,并重写了init()、doFilter()和destroy()方法,在doFilter()方法中向控制台打印了“hello MyFilter”字符串。

@Component
public class MyFilter implements Filter {@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {System.out.println("hello my filter!"); chain.doFilter(request, response);}}

2.向Servlet组件配置类注册自定义Filter类

@Bean
public FilterRegistrationBean getFilter(MyFilter filter){                        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);//过滤出请求路径"/toLoginPage","/myFilter",对它们特殊处理,也就是执行Filter中的方法。                 registrationBean.setUrlPatterns(Arrays.asList("/toLoginPage","/myFilter"));  return registrationBean;
}                                                                                

3、项目启动成功后,在浏览器上访问http://localhost:8080/myFilter,查看控制台打印效果

使用组件注册方式整合Listener

1.创建一个类MyListener

@Component
public class MyListener implements ServletContextListener {@Override public void contextInitialized(ServletContextEvent servletContextEvent) {System.out.println("contextInitialized ...");}@Override public void contextDestroyed(ServletContextEvent servletContextEvent) {System.out.println("contextDestroyed ...");}}

2.向Servlet组件配置类注册自定义Listener类

@Bean
public ServletListenerRegistrationBean getServletListener(MyListener myListener){ServletListenerRegistrationBean registrationBean =                           new ServletListenerRegistrationBean(myListener);                     return registrationBean;                                                     }                                                                                

3.项目启动成功后查看控制台打印效果

当正常启动,正常关闭时,会出现如下日志

路径扫描整合javaweb三大组件

1.三大组件上添加对应注解,同时注释掉@Component

在对应组件上分别使用@WebServlet(“/annotationServlet”)注解来映射“/annotationServlet”请求的Servlet类,使用@WebFilter(value = {“/antionLogin”,“/antionMyFilter”})注解来映射“/antionLogin”和“/antionMyFilter”请求的Filter类,使用@WebListener注解来标注Listener类。

@WebServlet("/annotationServlet")
public class MyServlet extends HttpServlet {
@WebFilter(value = {"/antionLogin","/antionMyFilter"})
public class MyFilter implements Filter {
@WebListener
public class MyListener implements ServletContextListener {

2.注释掉配置类

//@Configuration

public class ServletConfig {

3.主程序启动类上添加@ServletComponentScan注解

开启基于注解方式的Servlet组件扫描支持

@ServletComponentScan

@SpringBootApplication

public class MyChapter05Application

4.测试

http://localhost:8080/annotationServlet

http://localhost:8080/antionLogin

http://localhost:8080/antionMyFilter

文件上传

1.编写文件上传的表单页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>动态添加文件上传列表</title><link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet"><script th:src="@{/login/js/jquery.min.js}"></script>
</head>
<body><div th:if="${uploadStatus}" style="color: red" th:text="${uploadStatus}">上传成功</div><form th:action="@{/uploadFile}" method="post" enctype="multipart/form-data">上传文件:  <input type="button" value="添加文件" onclick="add()"/><div id="file" style="margin-top: 10px;" th:value="文件上传区域"></div><input id="submit" type="submit" value="上传"style="display: none;margin-top: 10px;"/></form><script type="text/javascript">// 动态添加上传按钮function add(){var innerdiv = "<div>";innerdiv += "<input type='file' name='fileUpload' required='required'>" +
"<input type='button' value='删除' onclick='remove(this)'>";innerdiv +="</div>";$("#file").append(innerdiv);// 打开上传按钮$("#submit").css("display","block");}// 删除当前行<div>function remove(obj) {$(obj).parent().remove();if($("#file div").length ==0){$("#submit").css("display","none");}}</script>
</body>
</html>

2.引入jQuery

3.在全局配置文件中添加文件上传的相关配置

# 单个上传文件大小限制(默认1MB)
spring.servlet.multipart.max-file-size=10MB
# 总上传文件大小限制(默认10MB)
spring.servlet.multipart.max-request-size=50MB

4.进行文件上传处理实现文件上传功能

//toUpload()方法处理路径为“/toUpload”的GET请求,向文件上传页面//upload.html跳转;
@GetMapping("/toUpload")
public String toUpload(){return "upload";}

/*uploadFile()方法处理路径为“/uploadFile”的POST请求,对上传文件进行处理。文件上传处理过程中,对文件名进行重命名并存放在“F:/file/”目录下,并封装了返回结果。其中,处理上传文件的请求方法中,使用了“MultipartFile[] fileUpload”参数处理单个或多个上传文件(也可以使用单列集合参数),fileUpload参数名必须与upload.html页面中上传文件<input>框中的name属性值一致。*/

    @PostMapping("/uploadFile")public String uploadFile(MultipartFile[] fileUpload, Model model) {// 默认文件上传成功,并返回状态信息model.addAttribute("uploadStatus", "上传成功!");for (MultipartFile file : fileUpload) {// 获取文件名以及后缀名String fileName = file.getOriginalFilename();// 重新生成文件名(根据具体情况生成对应文件名)fileName = UUID.randomUUID()+"_"+fileName;// 指定上传文件本地存储目录,不存在需要提前创建String dirPath = "F:/file/";File filePath = new File(dirPath);if(!filePath.exists()){filePath.mkdirs();}try {file.transferTo(new File(dirPath+fileName));} catch (Exception e) {e.printStackTrace();// 上传失败,返回失败信息model.addAttribute("uploadStatus","上传失败: "+e.getMessage());}}// 携带上传状态信息回调到文件上传页面return "upload";}

5.效果测试

在浏览器上访问http://localhost:8080/toUpload

如果不能正常解析模板页面,那么

a.添加NekoHTML依赖(一个简单地HTML扫描器和标签补偿器)

<dependency>

<groupId>net.sourceforge.nekohtml</groupId>

<artifactId>nekohtml</artifactId>

<version>1.9.22</version>

</dependency>

b.在全局配置文件上添加如下配置

#thymeleaf对html的标签约束非常严格,所有的标签必须有开有闭,比如#<br></br>或者<br/>是可以的,但是<br>会报错,配置#spring.thymeleaf.mode=LEGACYHTML5 目的就是为了解决这个问题,可以使页面#松校验。

spring.thymeleaf.mode=LEGACYHTML5

点击【添加文件】,添加几个文件

验证文件上传处理效果,查看定制的上传文件存储目录“F:/file/”

文件下载

1.添加文件下载工具依赖

Commons IO is a library of utilities to assist with developing IO functionality.

<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version>
</dependency>

2.定制文件下载页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<div style="margin-bottom: 10px">文件下载列表:</div>
<table>
<tr>
<td>bloglogo.jpg</td>
<td><a th:href="@{/download(filename='bloglogo.jpg')}">下载文件</a></td>
</tr>
<tr>
<td>Spring Boot应用级开发教程.pdf</td>
<td><a th:href="@{/download(filename='Spring Boot应用级开发教程.pdf')}">下载文件</a></td>
</tr>
</table>
</body>
</html>

3.编写文件下载处理办法

FileController中添加跳转到下载页面的方法

@GetMapping("/toDownload")
public String toDownload(){return "download";
}

/**在fileDownload(String filename)方法中,设定了被下载文件的路径为“F:/file/”、文件下载的打开方式和返回形式;

在获取下载结果时,使用了commons-io的FileUtils的readFileToByteArray()方法快速下载文件,并以ResponseEntity<byte[]>类型数据返回。*/

    // 文件下载管理@GetMapping("/download")public ResponseEntity<byte[]> fileDownload(String filename){// 指定要下载的文件根路径String dirPath = "F:/file/";// 创建该文件对象File file = new File(dirPath + File.separator + filename);// 设置响应头HttpHeaders headers = new HttpHeaders();// 通知浏览器以下载方式打开headers.setContentDispositionFormData("attachment",filename);// 定义以流的形式下载返回文件数据headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);try {return new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);} catch (Exception e) {e.printStackTrace();return new ResponseEntity<byte[]>(e.getMessage().getBytes(),HttpStatus.EXPECTATION_FAILED);}}

4.效果测试

在浏览器上访问http://localhost:8080/toDownload

问题:下载后的文件中文名称统一变成了“_”

中文名文件下载改进

注释在FileController类的fileDownload()方法,

添加有中文处理方法的fileDownload(),中文处理方法getFilename(HttpServletRequest request,String filename)用来根据不同浏览器对下载的中文名进行转码。

其中,通过HttpServletRequest中的“User-Agent”用于获取用户下载文件的浏览器内核信息(不同版本的IE浏览器内核可能不同,需要特别查看),

如果内核信息是IE则转码为UTF-8,其他浏览器转码为ISO-8859-1即可。

注释之前写的fileDownload,添加如下的fileDownload

    // 中文文件名下载管理@GetMapping("/download")public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,String filename) throws Exception{// 指定要下载的文件根路径String dirPath = "F:/file/";// 创建该文件对象File file = new File(dirPath + File.separator + filename);// 设置响应头HttpHeaders headers = new HttpHeaders();// 通知浏览器以下载方式打开(下载前对文件名进行转码)filename=getFilename(request,filename);headers.setContentDispositionFormData("attachment",filename);// 定义以流的形式下载返回文件数据headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);try {return new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);} catch (Exception e) {e.printStackTrace();return new ResponseEntity<byte[]>(e.getMessage().getBytes(),HttpStatus.EXPECTATION_FAILED);}}// 根据浏览器的不同进行编码设置,返回编码后的文件名private String getFilename(HttpServletRequest request, String filename)throws Exception {// IE不同版本User-Agent中出现的关键词String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};// 获取请求头代理信息String userAgent = request.getHeader("User-Agent");for (String keyWord : IEBrowserKeyWords) {if (userAgent.contains(keyWord)) {//IE内核浏览器,统一为UTF-8编码显示,并对转换的+进行更正return URLEncoder.encode(filename, "UTF-8").replace("+","");}}//火狐等其它浏览器统一为ISO-8859-1编码显示return new String(filename.getBytes("UTF-8"), "ISO-8859-1");}

Jar包方式打包部署

1.Pom中确认存在Maven打包插件和打包方式为jar

<packaging>jar</packaging> 可省略,默认就是这个方式打包

<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

2.使用eclipse进行打包

用package命令即可

出现如下结果,说明打包成功

3.Jar包目录结构展示说明

4.Jar包方式部署

5.问题

Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project ruanjian0105: Compilation failure
[ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?

设置jre为jdk的位置,如下

如果还是不行,查看是否真的改过来了,如果没有,点击RestoreDefault

War包方式打包部署

1.声明打包方式为War包

<packaging>war</packaging>

2.声明使用外部的Tomcat服务器

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope>
</dependency>

3.提供Spring Boot启动的Servlet初始化器

主程序启动类继承SpringBootServletInitializer类并实现configure()方法,在configure()方法中,sources(Chapter05Application.class)方法的首个参数必须是项目主程序启动类。

需要说明的是,为Spring Boot提供启动的Servlet初始化器SpringBootServletInitializer的典型的做法就是让主程序启动类继承SpringBootServletInitializer类并实现configure()方法;除此之外,还可以在项目中单独提供一个继承SpringBootServletInitializer的子类,并实现configure()方法。

public class MyChapter05Application extends SpringBootServletInitializer {public static void main(String[] args) {SpringApplication.run(MyChapter05Application.class, args);}@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {return builder.sources(MyChapter05Application.class);}}

4.使用eclipse进行打包

package命令即可,假如遇到failOnMissingWebXml,pom中添加如下插件

        <plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-war-plugin</artifactId>  <version>2.3</version>  <configuration>  <failOnMissingWebXml>false</failOnMissingWebXml>  </configuration>  </plugin>

5.War包目录结构

6.以war方式打包失败[webxml attribute is required]解决方案

7.War包方式部署

将打包好的War包拷贝到Tomcat安装目录下的webapps目录中,执行Tomcat安装目录下bin目录中的startup.bat命令启动War包项目

8.测试

使用外部Tomcat部署的项目进行访问时,必须加上项目名称(打成war包后的项目全名)

http://localhost:8080/MyChapter05-0.0.1-SNAPSHOT/toLoginPage

9.修改tomcat端口号

作业:

文件下载

5-Springboot实现web的常用功能相关推荐

  1. SpringBoot中使用Thymeleaf常用功能(一):表达式访问数据

    环境搭建: 创建一个Maven项目,按照Maven项目的规范,在src/main/下新建一个名为resources的文件夹,并在下面新建static和templates文件夹. ①  修改pom.xm ...

  2. 19. web 应用常用功能 -文件上传下载

    文章目录 19.1 基本介绍 19.2 文件上传 19.2.1 文件上传的基本原理 19.2.2 文件上传应用实例 19.2.3 文件上传注意事项和细节 19.3 文件下载 19.3.1 文件下载的原 ...

  3. web网站常用功能测试点总结

    一.输入框 1.字符型输入框: (1)字符型输入框:英文全角.英文半角.数字.空或者空格.特殊字符 "~!@#¥%--&*?[]{}" 特别要注意单引号和&符号.禁 ...

  4. SpringBoot中使用Thymeleaf常用功能(三):测试Thymeleaf循环取数据

    搭建环境请参考文章一 在index.html中新建超链接:<a th:href="@{eachtest}">测试循环</a> 新建包com.ysh.thym ...

  5. SpringBoot中使用Thymeleaf常用功能(二):测试Thymeleaf条件判断

    环境搭建请先阅读文章一 在一的基础上 先在index.html中添加超链接 <a th:href="@{iftest}">测试条件判断</a> 在Thyme ...

  6. ②SpringBoot之Web综合开发

    Spring boot初级教程 :<SpringBoot入门教学篇①>,方便大家快速入门.了解实践Spring boot特性,本文介绍springBoot的web开发 web开发 spri ...

  7. 实现以最快速度搭建springboot后台web项目并连通数据库实现控制层与服务层与dao层的select查询...

    背景 Servlet的出现 上世纪90年代,随着Internet和浏览器的飞速发展,基于浏览器的B/S模式随之火爆发展起来.最初,用户使用浏览器向WEB服务器发送的请求都是请求静态的资源,比如html ...

  8. (附源码)springboot基于WEB的高校文档打印系统 毕业设计101004

    Springboot 高校文档打印系统 摘要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以 ...

  9. nginx介绍及常用功能

    什么是nginx nginx跟Apache一样,是一个web服务器(网站服务器),通过HTTP协议提供各种网络服务. Apache:重量级的,不支持高并发的服务器.在Apache上运行数以万计的并发访 ...

最新文章

  1. 软件不可靠,服务是王道
  2. Start Activity for Result(Bug)
  3. 自定义LocaleResolver实现页面中英文切换
  4. 架构设计系列(一)——架构设计概述
  5. mysql编译安装原理_MySQL编译安装全过程
  6. Filecoin Gas基础费率降至0.23 nanoFIL
  7. python程序语法元素的描述_Python入门——Python程序语法元素
  8. 《ggplot2:数据分析与图形艺术》,读书笔记
  9. [POI2006]OKR-Periods of Words(KMP)
  10. Abb变频器输参数只读_ABB变频器ACSM1-04/ACS380产品参数说明及功能介绍
  11. Atitit 查找轮廓 findContours
  12. adobe photoshop cs4 注册码
  13. 不同币种间的清账 应付账款是USD记账 预付账款账款是人民币记账 如何清账
  14. linux学校_济南教师招聘 |济南市益友培训学校7大岗位教师招聘(月薪4k15k、包住)...
  15. 联合国会员国国家名称中英文对照
  16. canvas的width和style.width的区别
  17. 1138:破解简单密码
  18. matlab初值微分方程,常微分方程初值问题的MATLAB解法
  19. 光学成像系统中的像差
  20. 头条搜索下拉词怎么做?高粱seo实战告诉你答案

热门文章

  1. oracle:用户购买平台案例分析与优化
  2. vue-cli目录结构介绍
  3. 【Flink】Flink Remote Shuffle 开源:面向流批一体与云原生的 Shuffle 服务
  4. 【java】httpclient 链接偶尔会 Read timed out
  5. 【mac】iTerm2中ssh保持连接不断开
  6. 【Kafka】Kafka Record for partition topic at offset xx is invalid, cause: Record corrupt
  7. 60-150-040-使用-Sink-Flink自定义UpsertStreamTableSink
  8. 【Janino】Janino Java表达式计算引擎 案例
  9. 【Docker】docker 执行 apt-get E: Could not open lock file /var/lib/dpkg/lock - open
  10. Springboot java -jar 提示没没有主清单属性