Spring的资源抽象Resource2实体类
aaarticlea/png;base64,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" alt="" name="" />
public class FileSystemResource extends AbstractResource implements WritableResource { private final File file; // 不可变属性 private final String path; // 不可变属性 public FileSystemResource(File file) { // 简单的构造方法,path为file路径格式化后的样子
Assert.notNull(file, "File must not be null");
this.file = file;
this.path = StringUtils.cleanPath(file.getPath());
} public FileSystemResource(String path) { //简单的构造方法
Assert.notNull(path, "Path must not be null");
this.file = new File(path);
this.path = StringUtils.cleanPath(path);
} public final String getPath() { //新增的方法,返回资源路径,方法不可重写
return this.path;
} @Override
public boolean exists() {
return this.file.exists();
} @Override
public boolean isReadable() {
return (this.file.canRead() && !this.file.isDirectory());
} public InputStream getInputStream() throws IOException { //InputStreamSource接口的实现方法
return new FileInputStream(this.file);
} @Override
public URL getURL() throws IOException { //可见这个url是通过uri得到的
return this.file.toURI().toURL();
} @Override
public URI getURI() throws IOException {
return this.file.toURI();
} @Override
public File getFile() {
return this.file;
} @Override
public long contentLength() throws IOException {
return this.file.length();
} @Override
public Resource createRelative(String relativePath) {
String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);
return new FileSystemResource(pathToUse);
} @Override
public String getFilename() {
return this.file.getName();
} public String getDescription() { // 资源描述,直接用绝对路径来构造
return "file [" + this.file.getAbsolutePath() + "]";
} public boolean isWritable() { // WritableResource接口的实现方法
return (this.file.canWrite() && !this.file.isDirectory());
} public OutputStream getOutputStream() throws IOException {
return new FileOutputStream(this.file);
} @Override
public boolean equals(Object obj) { //通过path来比较
return (obj == this ||
(obj instanceof FileSystemResource && this.path.equals(((FileSystemResource) obj).path)));
} @Override
public int hashCode() { // 文件资源的HashCode就是path的hashCode
return this.path.hashCode();
} }
public class ClassPathResource extends AbstractFileResolvingResource { private final String path; private ClassLoader classLoader; private Class<?> clazz; /**
* Create a new ClassPathResource for ClassLoader usage.
* A leading slash will be removed, as the ClassLoader
* resource access methods will not accept it.
* <p>The thread context class loader will be used for
* loading the resource.
* @param path the absolute path within the class path
* @see java.lang.ClassLoader#getResourceAsStream(String)
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
public ClassPathResource(String path) {
this(path, (ClassLoader) null);
} /**
* Create a new ClassPathResource for ClassLoader usage.
* A leading slash will be removed, as the ClassLoader
* resource access methods will not accept it.
* @param path the absolute path within the classpath
* @param classLoader the class loader to load the resource with,
* or {@code null} for the thread context class loader
* @see ClassLoader#getResourceAsStream(String)
*/
public ClassPathResource(String path, ClassLoader classLoader) {
Assert.notNull(path, "Path must not be null");
String pathToUse = StringUtils.cleanPath(path);
if (pathToUse.startsWith("/")) {
pathToUse = pathToUse.substring(1);
}
this.path = pathToUse;
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
} /**
* Create a new ClassPathResource for Class usage.
* The path can be relative to the given class,
* or absolute within the classpath via a leading slash.
* @param path relative or absolute path within the class path
* @param clazz the class to load resources with
* @see java.lang.Class#getResourceAsStream
*/
public ClassPathResource(String path, Class<?> clazz) {
Assert.notNull(path, "Path must not be null");
this.path = StringUtils.cleanPath(path);
this.clazz = clazz;
} /**
* Create a new ClassPathResource with optional ClassLoader and Class.
* Only for internal usage.
* @param path relative or absolute path within the classpath
* @param classLoader the class loader to load the resource with, if any
* @param clazz the class to load resources with, if any
*/
protected ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz) {
this.path = StringUtils.cleanPath(path);
this.classLoader = classLoader;
this.clazz = clazz;
} /**
* Return the path for this resource (as resource path within the class path).
*/
public final String getPath() {
return this.path;
} /**
* Return the ClassLoader that this resource will be obtained from.
*/
public final ClassLoader getClassLoader() {
return (this.classLoader != null ? this.classLoader : this.clazz.getClassLoader());
} /**
* This implementation checks for the resolution of a resource URL.
* @see java.lang.ClassLoader#getResource(String)
* @see java.lang.Class#getResource(String)
*/
@Override
public boolean exists() {
URL url;
if (this.clazz != null) {
url = this.clazz.getResource(this.path);
}
else {
url = this.classLoader.getResource(this.path);
}
return (url != null);
} /**
* This implementation opens an InputStream for the given class path resource.
* @see java.lang.ClassLoader#getResourceAsStream(String)
* @see java.lang.Class#getResourceAsStream(String)
*/
public InputStream getInputStream() throws IOException {
InputStream is;
if (this.clazz != null) {
is = this.clazz.getResourceAsStream(this.path);
}
else {
is = this.classLoader.getResourceAsStream(this.path);
}
if (is == null) {
throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
}
return is;
} /**
* This implementation returns a URL for the underlying class path resource.
* @see java.lang.ClassLoader#getResource(String)
* @see java.lang.Class#getResource(String)
*/
@Override
public URL getURL() throws IOException {
URL url;
if (this.clazz != null) {
url = this.clazz.getResource(this.path);
}
else {
url = this.classLoader.getResource(this.path);
}
if (url == null) {
throw new FileNotFoundException(getDescription() + " cannot be resolved to URL because it does not exist");
}
return url;
} /**
* This implementation creates a ClassPathResource, applying the given path
* relative to the path of the underlying resource of this descriptor.
* @see org.springframework.util.StringUtils#applyRelativePath(String, String)
*/
@Override
public Resource createRelative(String relativePath) {
String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);
return new ClassPathResource(pathToUse, this.classLoader, this.clazz);
} /**
* This implementation returns the name of the file that this class path
* resource refers to.
* @see org.springframework.util.StringUtils#getFilename(String)
*/
@Override
public String getFilename() {
return StringUtils.getFilename(this.path);
} /**
* This implementation returns a description that includes the class path location.
*/
public String getDescription() {
StringBuilder builder = new StringBuilder("class path resource [");
String pathToUse = path;
if (this.clazz != null && !pathToUse.startsWith("/")) {
builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));
builder.append('/');
}
if (pathToUse.startsWith("/")) {
pathToUse = pathToUse.substring(1);
}
builder.append(pathToUse);
builder.append(']');
return builder.toString();
} /**
* This implementation compares the underlying class path locations.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof ClassPathResource) {
ClassPathResource otherRes = (ClassPathResource) obj;
return (this.path.equals(otherRes.path) &&
ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) &&
ObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz));
}
return false;
} /**
* This implementation returns the hash code of the underlying
* class path location.
*/
@Override
public int hashCode() {
return this.path.hashCode();
} }
public class UrlResource extends AbstractFileResolvingResource { /**
* Original URI, if available; used for URI and File access.
*/
private final URI uri; /**
* Original URL, used for actual access.
*/
private final URL url; /**
* Cleaned URL (with normalized path), used for comparisons.
*/
private final URL cleanedUrl; /**
* Create a new UrlResource based on the given URI object.
* @param uri a URI
* @throws MalformedURLException if the given URL path is not valid
*/
public UrlResource(URI uri) throws MalformedURLException {
Assert.notNull(uri, "URI must not be null");
this.uri = uri;
this.url = uri.toURL();
this.cleanedUrl = getCleanedUrl(this.url, uri.toString());
} /**
* Create a new UrlResource based on the given URL object.
* @param url a URL
*/
public UrlResource(URL url) {
Assert.notNull(url, "URL must not be null");
this.url = url;
this.cleanedUrl = getCleanedUrl(this.url, url.toString());
this.uri = null;
} /**
* Create a new UrlResource based on a URL path.
* <p>Note: The given path needs to be pre-encoded if necessary.
* @param path a URL path
* @throws MalformedURLException if the given URL path is not valid
* @see java.net.URL#URL(String)
*/
public UrlResource(String path) throws MalformedURLException {
Assert.notNull(path, "Path must not be null");
this.uri = null;
this.url = new URL(path);
this.cleanedUrl = getCleanedUrl(this.url, path);
} /**
* Create a new UrlResource based on a URI specification.
* <p>The given parts will automatically get encoded if necessary.
* @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);
* also known as "scheme"
* @param location the location (e.g. the file path within that protocol);
* also known as "scheme-specific part"
* @throws MalformedURLException if the given URL specification is not valid
* @see java.net.URI#URI(String, String, String)
*/
public UrlResource(String protocol, String location) throws MalformedURLException {
this(protocol, location, null);
} /**
* Create a new UrlResource based on a URI specification.
* <p>The given parts will automatically get encoded if necessary.
* @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);
* also known as "scheme"
* @param location the location (e.g. the file path within that protocol);
* also known as "scheme-specific part"
* @param fragment the fragment within that location (e.g. anchor on an HTML page,
* as following after a "#" separator)
* @throws MalformedURLException if the given URL specification is not valid
* @see java.net.URI#URI(String, String, String)
*/
public UrlResource(String protocol, String location, String fragment) throws MalformedURLException {
try {
this.uri = new URI(protocol, location, fragment);
this.url = this.uri.toURL();
this.cleanedUrl = getCleanedUrl(this.url, this.uri.toString());
}
catch (URISyntaxException ex) {
MalformedURLException exToThrow = new MalformedURLException(ex.getMessage());
exToThrow.initCause(ex);
throw exToThrow;
}
} /**
* Determine a cleaned URL for the given original URL.
* @param originalUrl the original URL
* @param originalPath the original URL path
* @return the cleaned URL
* @see org.springframework.util.StringUtils#cleanPath
*/
private URL getCleanedUrl(URL originalUrl, String originalPath) {
try {
return new URL(StringUtils.cleanPath(originalPath));
}
catch (MalformedURLException ex) {
// Cleaned URL path cannot be converted to URL
// -> take original URL.
return originalUrl;
}
} /**
* This implementation opens an InputStream for the given URL.
* It sets the "UseCaches" flag to {@code false},
* mainly to avoid jar file locking on Windows.
* @see java.net.URL#openConnection()
* @see java.net.URLConnection#setUseCaches(boolean)
* @see java.net.URLConnection#getInputStream()
*/
public InputStream getInputStream() throws IOException {
URLConnection con = this.url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
try {
return con.getInputStream();
}
catch (IOException ex) {
// Close the HTTP connection (if applicable).
if (con instanceof HttpURLConnection) {
((HttpURLConnection) con).disconnect();
}
throw ex;
}
} /**
* This implementation returns the underlying URL reference.
*/
@Override
public URL getURL() throws IOException {
return this.url;
} /**
* This implementation returns the underlying URI directly,
* if possible.
*/
@Override
public URI getURI() throws IOException {
if (this.uri != null) {
return this.uri;
}
else {
return super.getURI();
}
} /**
* This implementation returns a File reference for the underlying URL/URI,
* provided that it refers to a file in the file system.
* @see org.springframework.util.ResourceUtils#getFile(java.net.URL, String)
*/
@Override
public File getFile() throws IOException {
if (this.uri != null) {
return super.getFile(this.uri);
}
else {
return super.getFile();
}
} /**
* This implementation creates a UrlResource, applying the given path
* relative to the path of the underlying URL of this resource descriptor.
* @see java.net.URL#URL(java.net.URL, String)
*/
@Override
public Resource createRelative(String relativePath) throws MalformedURLException {
if (relativePath.startsWith("/")) {
relativePath = relativePath.substring(1);
}
return new UrlResource(new URL(this.url, relativePath));
} /**
* This implementation returns the name of the file that this URL refers to.
* @see java.net.URL#getFile()
* @see java.io.File#getName()
*/
@Override
public String getFilename() {
return new File(this.url.getFile()).getName();
} /**
* This implementation returns a description that includes the URL.
*/
public String getDescription() {
return "URL [" + this.url + "]";
} /**
* This implementation compares the underlying URL references.
*/
@Override
public boolean equals(Object obj) {
return (obj == this ||
(obj instanceof UrlResource && this.cleanedUrl.equals(((UrlResource) obj).cleanedUrl)));
} /**
* This implementation returns the hash code of the underlying URL reference.
*/
@Override
public int hashCode() {
return this.cleanedUrl.hashCode();
} }
public class ServletContextResource extends AbstractFileResolvingResource implements ContextResource { private final ServletContext servletContext; private final String path; /**
* Create a new ServletContextResource.
* <p>The Servlet spec requires that resource paths start with a slash,
* even if many containers accept paths without leading slash too.
* Consequently, the given path will be prepended with a slash if it
* doesn't already start with one.
* @param servletContext the ServletContext to load from
* @param path the path of the resource
*/
public ServletContextResource(ServletContext servletContext, String path) {
// check ServletContext
Assert.notNull(servletContext, "Cannot resolve ServletContextResource without ServletContext");
this.servletContext = servletContext; // check path
Assert.notNull(path, "Path is required");
String pathToUse = StringUtils.cleanPath(path);
if (!pathToUse.startsWith("/")) {
pathToUse = "/" + pathToUse;
}
this.path = pathToUse;
} /**
* Return the ServletContext for this resource.
*/
public final ServletContext getServletContext() {
return this.servletContext;
} /**
* Return the path for this resource.
*/
public final String getPath() {
return this.path;
} /**
* This implementation checks {@code ServletContext.getResource}.
* @see javax.servlet.ServletContext#getResource(String)
*/
@Override
public boolean exists() {
try {
URL url = this.servletContext.getResource(this.path);
return (url != null);
}
catch (MalformedURLException ex) {
return false;
}
} /**
* This implementation delegates to {@code ServletContext.getResourceAsStream},
* which returns {@code null} in case of a non-readable resource (e.g. a directory).
* @see javax.servlet.ServletContext#getResourceAsStream(String)
*/
@Override
public boolean isReadable() {
InputStream is = this.servletContext.getResourceAsStream(this.path);
if (is != null) {
try {
is.close();
}
catch (IOException ex) {
// ignore
}
return true;
}
else {
return false;
}
} /**
* This implementation delegates to {@code ServletContext.getResourceAsStream},
* but throws a FileNotFoundException if no resource found.
* @see javax.servlet.ServletContext#getResourceAsStream(String)
*/
public InputStream getInputStream() throws IOException {
InputStream is = this.servletContext.getResourceAsStream(this.path);
if (is == null) {
throw new FileNotFoundException("Could not open " + getDescription());
}
return is;
} /**
* This implementation delegates to {@code ServletContext.getResource},
* but throws a FileNotFoundException if no resource found.
* @see javax.servlet.ServletContext#getResource(String)
*/
@Override
public URL getURL() throws IOException {
URL url = this.servletContext.getResource(this.path);
if (url == null) {
throw new FileNotFoundException(
getDescription() + " cannot be resolved to URL because it does not exist");
}
return url;
} /**
* This implementation resolves "file:" URLs or alternatively delegates to
* {@code ServletContext.getRealPath}, throwing a FileNotFoundException
* if not found or not resolvable.
* @see javax.servlet.ServletContext#getResource(String)
* @see javax.servlet.ServletContext#getRealPath(String)
*/
@Override
public File getFile() throws IOException {
URL url = this.servletContext.getResource(this.path);
if (url != null && ResourceUtils.isFileURL(url)) {
// Proceed with file system resolution...
return super.getFile();
}
else {
String realPath = WebUtils.getRealPath(this.servletContext, this.path);
return new File(realPath);
}
} /**
* This implementation creates a ServletContextResource, applying the given path
* relative to the path of the underlying file of this resource descriptor.
* @see org.springframework.util.StringUtils#applyRelativePath(String, String)
*/
@Override
public Resource createRelative(String relativePath) {
String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);
return new ServletContextResource(this.servletContext, pathToUse);
} /**
* This implementation returns the name of the file that this ServletContext
* resource refers to.
* @see org.springframework.util.StringUtils#getFilename(String)
*/
@Override
public String getFilename() {
return StringUtils.getFilename(this.path);
} /**
* This implementation returns a description that includes the ServletContext
* resource location.
*/
public String getDescription() {
return "ServletContext resource [" + this.path + "]";
} public String getPathWithinContext() {
return this.path;
} /**
* This implementation compares the underlying ServletContext resource locations.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof ServletContextResource) {
ServletContextResource otherRes = (ServletContextResource) obj;
return (this.servletContext.equals(otherRes.servletContext) && this.path.equals(otherRes.path));
}
return false;
} /**
* This implementation returns the hash code of the underlying
* ServletContext resource location.
*/
@Override
public int hashCode() {
return this.path.hashCode();
} }
Spring的资源抽象Resource2实体类的更多相关文章
- Spring Data JPA 多个实体类表联合视图查询
Spring Data JPA 查询数据库时,如果两个表有关联,那么就设个外键,在查询的时候用Specification创建Join 查询便可.但是只支持左连接,不支持右连接,虽说左右连接反过来就能实 ...
- 在spring的过滤器中注入实体类(@autowire会失效可使用这个方法)
转载:难得可贵的好文章 https://blog.csdn.net/chl191623691/article/details/78657638 首先,本文 绝对是好文!不止本文,作者的文章都是很经 ...
- 通过JPA注解映射视图的实体类 jpa 视图 无主键 @Query注解的用法(Spring Data JPA) jpa 使用sql语句
参考: https://blog.csdn.net/qq465235530/article/details/68064074 https://www.cnblogs.com/zj0208/p/6008 ...
- spring boot JPA中实体类常用注解
spring boot jpa中的注解很多,参数也比较多.没必要全部记住,但是经常查看官方文档也比较麻烦,记录一下一些常用的注解.通过一些具体的例子来帮助记忆. @Entity @Table(name ...
- Spring MVC如何接收浏览器传递来的请求参数--request--形参--实体类封装
阅读目录 1. 通过HttpServletRequest获得请求参数和数据 2. 处理方法形参名==请求参数名 3. 如果形参名跟请求参数名不一样怎么办呢?用@RequestParam注解 4. 用实 ...
- spring boot: spring-data-jpa (Repository/CrudRepository) 数据库操作, @Entity实体类持久化
SpringBoot实现的JPA封装了JPA的特性, Repository是封装了jpa的特性(我是这么理解的) 1在pom.xml引入mysql, spring-data-jpa依赖 2.在src/ ...
- JAVA Spring 简单的配置和操作 ( 创建实体类, 配置XML文件, 调试 )
< 1 > 实体类 Person package java_spring.modle; /** * 一个实体类( Person ) */ public class Person { pri ...
- Spring简单获得实体类的实例, 使用ApplicationContext()方法的几点注意事项
今天接触了Spring的初步用法, 感觉跟实例化实体类没啥区别, 像这种简单的代码还不如直接实例化来的方便, 这样使用Spring的话总共需要三个文件 第一个当然是一个实体类了, 定义好属性, get ...
- 0056 Spring MVC如何接收浏览器传递来的请求参数--request--形参--实体类封装
浏览器总会向服务器传递一些参数,那么Spring MVC如何接收这些参数? 先写个简单的html,向服务器传递一些书籍信息,如下: <!DOCTYPE html> <html> ...
随机推荐
- linux6.0系统如何安装portmap
因为在6.0的系统里,portmap已经改名了.在Redhat或CentOS5中可以使用 service portmap start启动服务,然后在启动nfs服务,实现挂载. 6里面可是试试 serv ...
- [AngularFire2 & Firestore] Example for collection and doc
import {Injectable} from '@angular/core'; import {Skill} from '../models/skills'; import {AuthServic ...
- 关于Webpack详述系列文章 (第二篇)
1.缩小文件搜索范围 1.1.1 include & exclude module:{ rules:[ { test:/\.js$/, use:['babel-loader?cacheDire ...
- vector转数组
vector转数组 由于vector内部的数据是存放在连续的存储空间,vector转数组事实上只需要获取vector中第一个数据的地址和数据的长度即可.如果仅仅是传参,无需任何操作,直接传地址即可,如 ...
- MySQL 5.7 多实例安装部署实例
1. 背景 MySQL数据库的集中化运维,可以通过在一台服务器上,部署运行多个MySQL服务进程,通过不同的socket监听不同的服务端口来提供各自的服务.各个实例之间是相互独立的,每个实例的dat ...
- 图文具体解释 IntelliJ IDEA 15 创建 Maven 构建的 Java Web 项目(使用 Jetty 容器)
图文具体解释 IntelliJ IDEA 15 创建 maven 的 Web 项目 搭建 maven 项目结构 1.使用 IntelliJ IDEA 15 新建一个项目. 2.设置 GAV 坐标 3. ...
- php函数,static,globalkeyword及三种变量作用域
函数 和js函数相似,关注php与其它语言不用的地方 函数的形參默认值 形式: function f($a,$b=3,$vc = "abc"){ } 注意:没有给默认值的形參必须传 ...
- Light OJ 1373 Strongly Connected Chemicals 二分匹配最大独立集
m种阳离子 n种阴离子 然后一个m*n的矩阵 第i行第j列为1代表第i种阴离子和第j种阴离子相互吸引 0表示排斥 求在阳离子和阴离子都至少有一种的情况下 最多存在多少种离子能够共存 阴阳离子都至少须要 ...
- 转 openssl 建立服务器证书
openssl 建立服务器证书 ## 1,建立目录和文件 set path=D:/openssl/bin D: cd D:/openssl/conf/ ren ope ...
- 循环体(for/while)循环变量的设置
1. 求滑动(移动)平均(moving average) double partialSum = 0; for (int i = 0; i < M-1; ++i) partialSum += A ...