1.静态文件访问
使用IDEA创建Spring Boot项目,会默认创建出classpath:/static/目录,静态资源一般放在这个目录下即可。
如果默认的静态资源过滤策略不能满足开发需求,也可以自定义静态资源过滤策略。
1.1直接访问
在application.properties中直接定义过滤规则和静态资源位置:
如果要在浏览器访问这张图片,路径默认为: http://localhost:8080/zzc.webp
1.2虚拟路径访问
可以统计加一个虚拟路径,例如:在application.properties中接入:
spring.mvc.static-path-pattern=/images/**
即给图片接入了一个虚拟前缀,
在浏览器中输入网址:http://localhost:8080/images/zzc.webp
1.3自定义路径(了解)
创建java类、上传图片等会自动在target下创建class类
静态资源位置为classpath:/static/
demo中编写的java类(class)如下:
2.文件上传原理
表单的enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。
当表单的enctype="application/x-www-form-urlencoded"(默认)时,form表单中的数据格式为:key=value&key=value。一定要把enctype类型改为form-data类型。
当表单的enctype="multipart/form-data"时,其传输数据形式如下:
Spring Boot工程嵌入的tomcat限制了请求的文件大小,每个文件的配置最大为1Mb,单次请求的文件的总数不能大于10Mb。 要更改这个默认值需要在配置文件(如application.properties)中加入两个配置:
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
2.1SpirngBoot实现文件上传功能
当表单的enctype="multipart/form-data"时,可以使用MultipartFile 获取上传的文件数据,再通过transferTo方法将其写入到磁盘中。
编写类 FileUploadController:
package com.example.demo.contraller;import com.sun.net.httpserver.HttpServer;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.coyote.http11.filters.SavedRequestInputFilter;
import org.springframework.web.bind.annotation.Mapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;@RestController
public class FileUploadController {@PostMapping("/upload")//等价于://@RequestMapping(value = "/uplload",method = RequestMethod.POST)public String up(String nickname, MultipartFile photo, HttpServletRequest request) throws IOException {System.out.println(nickname);//获取图片的原始名称System.out.println(photo.getOriginalFilename());//获取图片路径System.out.println(photo.getContentType());//获取文件类型String path = request.getServletContext().getRealPath("/upload/");//获取web服务器的运行目录,因为这个web服务器最终要部署到Linux系统上去,放到云端上去//要求动态的获取到web服务器所在的位置//这个tomcat是我们IDEA自带的,若要运行在云端,那么tomcat也会运行到云端//因此定义了一个HttpServletRequest request参数,代表网络请求//String path = request.getServletContext().getRealPath("/upload/");//通过这个对象可以获取到上下文对象(web服务器),接着就可以获取其路径(.getRealPath)//request.getServletContext().getRealPath 前面这部分是动态获取的,//("/upload/") 后面这部分是不存在的,如果不存在那么就创建出来(后面函数有写的)System.out.println(path);saveFile(photo,path);//自定义一个方法,把文件存储起来return "上传成功";}private void saveFile(MultipartFile photo,String path) throws IOException{File dir = new File(path);if(!dir.exists()){dir.mkdir();}File file = new File(path + photo.getOriginalFilename());//该文件是最终存储的文件photo.transferTo(file);}
}
获取web服务器的运行目录,因为这个web服务器最终要部署到Linux系统上去,放到云端上去;因此要求动态的获取到web服务器所在的位置。这个tomcat是我们IDEA自带的,若要运行在云端,那么tomcat也会运行到云端。因此定义了一个HttpServletRequest request参数,代表网络请求,String path = request.getServletContext().getRealPath("/upload/");通过这个对象可以获取到上下文对象(web服务器),接着就可以获取其路径(.getRealPath)
request.getServletContext().getRealPath 前面这部分是动态获取的,("/upload/") 后面这部分是不存在的,如果不存在那么就创建出来(后面函数有写的)。
2.2上传文件
注:使用form-data类型上传,且名称要对应起来。
运行和结果:
zhangzongchang
zzc.webp
image/webp
C:\Windows\Temp\tomcat-docbase.8080.626034175088608909\upload\
//动态路径+固定的\upload\ 如上:
自定义方法(存储文件)如下:
private void saveFile(MultipartFile photo,String path) throws IOException{File dir = new File(path);if(!dir.exists()){
// 判断路径是否存在dir.mkdir();
// 若不存在就创建路径}File file = new File(path + photo.getOriginalFilename());//该文件是最终存储的文件//还要加上目录路径path和存储的文件名称photo.getOriginalFilename()photo.transferTo(file);//MultipartFile对象有一个transferTo()方法//该方法可以将网络上传输过来的文件存储到上面的文件目录(file)中去}
在pc上打开该目录:C:\Windows\Temp\tomcat-docbase.8080.626034175088608909\upload\
但该目录不可以通过浏览器访问。 如果想要用户访问之前上传的头像文件,可以重新配置路径如下:spring.web.resources.static-locations=/upload/
可以访问了:如下
3.拦截器
拦截器在Web系统中非常常见,对于某些全局统一的操作,我们可以把它提取到拦截器中实现。总结起来,拦截器大致有以下几种使用场景:
权限检查:如登录检测,进入处理程序检测是否登录,如果没有,则直接返回登录页面。
性能监控:有时系统在某段时间莫名其妙很慢,可以通过拦截器在进入处理程序之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间
通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有提取Locale、Theme信息等,只要是多个处理程序都需要的,即可使用拦截器实现。
3.1功能
Spring Boot定义了HandlerInterceptor接口来实现自定义拦截器的功能
HandlerInterceptor接口定义了preHandle(常用)、postHandle、afterCompletion三种方法,通过重写这三种方法实现请求前、请求后等操作
3.2拦截器的定义
例子:
重写父类里的方法:
package com.example.demo.interceptor;//import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;public class LoginInterceptor implements HandlerInterceptor {//继承了andlerInterceptor,重写了父类里的方法preHandle@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception{//request参数对应前端的请求,response给前端返回信息System.out.println("LoginInterceptor");return true;}
}
3.3拦截器注册
拦截器定义完成后还需要进行注册,否则不能使用。
addPathPatterns方法定义拦截的地址
excludePathPatterns定义排除某些地址不被拦截
添加的一个拦截器没有addPathPattern任何一个url则默认拦截所有请求
如果没有excludePathPatterns任何一个请求,则默认不放过任何一个请求。
在config包下:
package com.example.demo.config;import com.example.demo.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
//为了让这个类生效,加一个注解@Configuration,有了这个世界springboot会自动读取这个类,下面的配置才会生效
public class WebConfig implements WebMvcConfigurer{//重写父类的方法@Overridepublic void addInterceptors(InterceptorRegistry registry){//一个增加拦截器的方法registry.addInterceptor(new LoginInterceptor());//}
}
3.4测试拦截器
运行后访问之前的http://localhost:8080/hello
这说明在访问http://localhost:8080/hello之前就已经进入到了拦截器内部了。
@Configuration
//为了让这个类生效,加一个注解@Configuration,有了这个世界springboot会自动读取这个类,下面的配置才会生效
public class WebConfig implements WebMvcConfigurer{//重写父类的方法@Overridepublic void addInterceptors(InterceptorRegistry registry){//一个增加拦截器的方法registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**");//代表只拦截/user/**里的}
}
刷新后发现已经不打印了,因为访问的是/hello