# 操作系统中的文件
# 文件
- 具有 符号名的,逻辑上具有完整意义的一组相关信息项的有序序列。信息项是构成文件的基本单位(百度百科)。
- 系统的内存有限并且不能长期保存,故平时总是把它们以文件的形式存放在外存中,需要时再将它们调入内存(《操作系统》)。
# 文件系统
- 现代OS通过文件系统,来组织和管理在计算机中存储的大量程序和数据。
- 文件系统管理的对象有: 文件,目录,磁盘
# 目录
- 目录文件,是长度固定的记录式文件
- 目前,大多数操作系统采用多级目录结构,称为树形目录结构
# linux文件系统与windows文件系统的区别
规范方面的差异
- linux只有一个单独的顶级目录,而windows有不同的分区,目录都存在于分区上。
- linux用/ 作为目录分隔符,而windows使用 \ 作为目录分隔符
权限上的差距
- windows用户分为两类,admin和limited;
- linux用户分为四类: root,普通用户,同组用户,其它用户;
文件命名规范
- windows的 NTFS文件系统,允许特殊字符: ? " / \ < > * | :
- windows的 FAT文件系统(文件名不允许中文),允许特殊字符: . " / \ [ ] : ; | = ,
- linux的文件系统,允许特殊字符: 除/外的所有字符
# java中的文件API
# 文件
- 抽象结构
public interface Comparable<T> {
public int compareTo(T o);
}
public class File
implements Serializable, Comparable<File>
{
private static final FileSystem fs = DefaultFileSystem.getFileSystem();
private final String path;
/**
* The length of this abstract pathname's prefix, or zero if it has no
* prefix.
*/
private final transient int prefixLength;
public File(String pathname) {
if (pathname == null) {
throw new NullPointerException();
}
this.path = fs.normalize(pathname);
this.prefixLength = fs.prefixLength(this.path);
}
public boolean isDirectory() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
}
if (isInvalid()) {
return false;
}
return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
!= 0);
}
public boolean isFile() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
}
if (isInvalid()) {
return false;
}
return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
}
//省略其它抽象...
}
- 注意事项
- new File(),实例化动作并未与实际的文件系统产生交互
# 文件系统--文件管理
- 抽象结构
class DefaultFileSystem {
/**
* Return the FileSystem object for Windows platform.
*/
public static FileSystem getFileSystem() {
return new WinNTFileSystem();
}
}
abstract class FileSystem {
public abstract char getSeparator();
public abstract char getPathSeparator();
public abstract String normalize(String path);
public abstract int prefixLength(String path);
//省略其它抽象...
}
class WinNTFileSystem extends FileSystem {
private final char slash;
private final char altSlash;
private final char semicolon;
public WinNTFileSystem() {
slash = AccessController.doPrivileged(
new GetPropertyAction("file.separator")).charAt(0);
semicolon = AccessController.doPrivileged(
new GetPropertyAction("path.separator")).charAt(0);
altSlash = (this.slash == '\\') ? '/' : '\\';
}
@Override
public String normalize(String path) {
int n = path.length();
char slash = this.slash;
char altSlash = this.altSlash;
char prev = 0;
for (int i = 0; i < n; i++) {
char c = path.charAt(i);
if (c == altSlash)
return normalize(path, n, (prev == slash) ? i - 1 : i);
if ((c == slash) && (prev == slash) && (i > 1))
return normalize(path, n, i - 1);
if ((c == ':') && (i > 1))
return normalize(path, n, 0);
prev = c;
}
if (prev == slash) return normalize(path, n, n - 1);
return path;
}
private String normalize(String path, int len, int off) {
if (len == 0) return path;
if (off < 3) off = 0; /* Avoid fencepost cases with UNC pathnames */
int src;
char slash = this.slash;
StringBuffer sb = new StringBuffer(len);
if (off == 0) {
/* Complete normalization, including prefix */
src = normalizePrefix(path, len, sb);
} else {
/* Partial normalization */
src = off;
sb.append(path.substring(0, off));
}
/* Remove redundant slashes from the remainder of the path, forcing all
slashes into the preferred slash */
while (src < len) {
char c = path.charAt(src++);
if (isSlash(c)) {
while ((src < len) && isSlash(path.charAt(src))) src++;
if (src == len) {
/* Check for trailing separator */
int sn = sb.length();
if ((sn == 2) && (sb.charAt(1) == ':')) {
/* "z:\\" */
sb.append(slash);
break;
}
if (sn == 0) {
/* "\\" */
sb.append(slash);
break;
}
if ((sn == 1) && (isSlash(sb.charAt(0)))) {
/* "\\\\" is not collapsed to "\\" because "\\\\" marks
the beginning of a UNC pathname. Even though it is
not, by itself, a valid UNC pathname, we leave it as
is in order to be consistent with the win32 APIs,
which treat this case as an invalid UNC pathname
rather than as an alias for the root directory of
the current drive. */
sb.append(slash);
break;
}
/* Path does not denote a root directory, so do not append
trailing slash */
break;
} else {
sb.append(slash);
}
} else {
sb.append(c);
}
}
String rv = sb.toString();
return rv;
}
public boolean createNewFile() throws IOException {
SecurityManager security = System.getSecurityManager();
if (security != null) security.checkWrite(path);
if (isInvalid()) {
throw new IOException("Invalid file path");
}
return fs.createFileExclusively(path);
}
//省略其它抽象...
}
- 注意事项
- 与文件抽象结构不同的是,它具有多个native函数,能够与实际的文件系统进行交互
class Block{ public native long getLength(File f); public native boolean checkAccess(File f, int access); public native String[] list(File f); public native boolean createDirectory(File f); private native boolean delete0(File f); public native boolean createFileExclusively(String path) throws IOException; private native boolean rename0(File f1, File f2); }
# 文件流--文件读写
- 文件读取
- 用完之后,需要关闭流。可以看到,该流打开了实际文件系统的资源引用;关闭的本质,是需要调用close0()方法
- 文件读取,可以使用文件名作为参数,进行读取。文件不存在,则会报错
public
class FileInputStream extends InputStream
{
private final FileDescriptor fd;
private FileChannel channel = null;
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
public FileInputStream(File file) throws FileNotFoundException {
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(name);
}
if (name == null) {
throw new NullPointerException();
}
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor();
fd.attach(this);
path = name;
open(name);
}
private void open(String name) throws FileNotFoundException {
open0(name);
}
private native void open0(String name) throws FileNotFoundException;
public int read() throws IOException {
return read0();
}
private native int read0() throws IOException;
private native int readBytes(byte b[], int off, int len) throws IOException;
public void close() throws IOException {
synchronized (closeLock) {
if (closed) {
return;
}
closed = true;
}
if (channel != null) {
channel.close();
}
fd.closeAll(new Closeable() {
public void close() throws IOException {
close0();
}
});
}
//省略其它抽象...
}
- 文件写入
- 用完之后,需要关闭流。可以看到,该流打开了实际文件系统的资源引用;关闭的本质,是需要调用close0()方法
- 可以使用文件名作为参数,进行写入。文件不存在,会自动创建文件
public
class FileOutputStream extends OutputStream
{
private final FileDescriptor fd;
public FileOutputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null, false);
}
public FileOutputStream(File file, boolean append)
throws FileNotFoundException
{
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkWrite(name);
}
if (name == null) {
throw new NullPointerException();
}
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
this.fd = new FileDescriptor();
fd.attach(this);
this.append = append;
this.path = name;
open(name, append);
}
private void open(String name, boolean append)
throws FileNotFoundException {
open0(name, append);
}
private native void open0(String name, boolean append)
throws FileNotFoundException;
private native void write(int b, boolean append) throws IOException;
private native void writeBytes(byte b[], int off, int len, boolean append)
throws IOException;
public void close() throws IOException {
synchronized (closeLock) {
if (closed) {
return;
}
closed = true;
}
if (channel != null) {
channel.close();
}
fd.closeAll(new Closeable() {
public void close() throws IOException {
close0();
}
});
}
//省略其它抽象...
}
# URL获取文件
# 何谓URL
- Uniform Resource Locator,统一资源定位符。由三部分组成:
- 资源类型(协议)
- 主机(ip+端口)
- 资源名称(路径)
- 路径可以包括参数、查询、片段(hash)
- 参数格式形如: www.automannn.cn/:param1=1¶m2=2
- 查询格式形如: www.automannn.cn/index.html?param1=1¶m2=2
- 片段格式形如: www.automannn.cn/index.html#hear1
# 常见URL
- http类型: 如 http://www.baidu.com/index.html
- file类型(三斜杠): 如 file:///D:/mytest/
- ftp类型: 如 ftp://www.automannn.cn/a.txt
# URL的抽象结构
- URL
public final class URL implements java.io.Serializable {
private String protocol;
private String host;
private String file;
private int port = -1;
private transient String query;
private transient String path;
transient URLStreamHandler handler;
public URL(String protocol, String host, int port, String file)
throws MalformedURLException
{
this(protocol, host, port, file, null);
}
public URL(String protocol, String host, int port, String file,
URLStreamHandler handler) throws MalformedURLException {
if (handler != null) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// check for permission to specify a handler
checkSpecifyHandler(sm);
}
}
protocol = protocol.toLowerCase();
this.protocol = protocol;
if (host != null) {
/**
* if host is a literal IPv6 address,
* we will make it conform to RFC 2732
*/
if (host.indexOf(':') >= 0 && !host.startsWith("[")) {
host = "["+host+"]";
}
this.host = host;
if (port < -1) {
throw new MalformedURLException("Invalid port number :" +
port);
}
this.port = port;
authority = (port == -1) ? host : host + ":" + port;
}
Parts parts = new Parts(file);
path = parts.getPath();
query = parts.getQuery();
if (query != null) {
this.file = path + "?" + query;
} else {
this.file = path;
}
ref = parts.getRef();
// Note: we don't do validation of the URL here. Too risky to change
// right now, but worth considering for future reference. -br
if (handler == null &&
(handler = getURLStreamHandler(protocol)) == null) {
throw new MalformedURLException("unknown protocol: " + protocol);
}
this.handler = handler;
}
public URLConnection openConnection(Proxy proxy)
throws java.io.IOException {
if (proxy == null) {
throw new IllegalArgumentException("proxy can not be null");
}
// Create a copy of Proxy as a security measure
Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy);
SecurityManager sm = System.getSecurityManager();
if (p.type() != Proxy.Type.DIRECT && sm != null) {
InetSocketAddress epoint = (InetSocketAddress) p.address();
if (epoint.isUnresolved())
sm.checkConnect(epoint.getHostName(), epoint.getPort());
else
sm.checkConnect(epoint.getAddress().getHostAddress(),
epoint.getPort());
}
return handler.openConnection(this, p);
}
public final InputStream openStream() throws java.io.IOException {
return openConnection().getInputStream();
}
static URLStreamHandler getURLStreamHandler(String protocol) {
URLStreamHandler handler = handlers.get(protocol);
if (handler == null) {
boolean checkedWithFactory = false;
// Use the factory (if any)
if (factory != null) {
handler = factory.createURLStreamHandler(protocol);
checkedWithFactory = true;
}
// Try java protocol handler
if (handler == null) {
String packagePrefixList = null;
packagePrefixList
= java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(
protocolPathProp,""));
if (packagePrefixList != "") {
packagePrefixList += "|";
}
// REMIND: decide whether to allow the "null" class prefix
// or not.
packagePrefixList += "sun.net.www.protocol";
StringTokenizer packagePrefixIter =
new StringTokenizer(packagePrefixList, "|");
while (handler == null &&
packagePrefixIter.hasMoreTokens()) {
String packagePrefix =
packagePrefixIter.nextToken().trim();
try {
String clsName = packagePrefix + "." + protocol +
".Handler";
Class<?> cls = null;
try {
cls = Class.forName(clsName);
} catch (ClassNotFoundException e) {
ClassLoader cl = ClassLoader.getSystemClassLoader();
if (cl != null) {
cls = cl.loadClass(clsName);
}
}
if (cls != null) {
handler =
(URLStreamHandler)cls.newInstance();
}
} catch (Exception e) {
// any number of exceptions can get thrown here
}
}
}
synchronized (streamHandlerLock) {
URLStreamHandler handler2 = null;
// Check again with hashtable just in case another
// thread created a handler since we last checked
handler2 = handlers.get(protocol);
if (handler2 != null) {
return handler2;
}
// Check with factory if another thread set a
// factory since our last check
if (!checkedWithFactory && factory != null) {
handler2 = factory.createURLStreamHandler(protocol);
}
if (handler2 != null) {
// The handler from the factory must be given more
// importance. Discard the default handler that
// this thread created.
handler = handler2;
}
// Insert this handler into the hashtable
if (handler != null) {
handlers.put(protocol, handler);
}
}
}
return handler;
}
//省略其它抽象...
}
- URLConnection
public abstract class URLConnection {
protected URL url;
protected boolean connected = false;
private int connectTimeout;
private int readTimeout;
protected URLConnection(URL url) {
this.url = url;
}
abstract public void connect() throws IOException;
public long getContentLengthLong() {
return getHeaderFieldLong("content-length", -1);
}
public long getHeaderFieldLong(String name, long Default) {
String value = getHeaderField(name);
try {
return Long.parseLong(value);
} catch (Exception e) { }
return Default;
}
public String getContentType() {
return getHeaderField("content-type");
}
public String getHeaderField(String name) {
//由子类实现
return null;
}
//省略其它抽象...
}
- URLSteamHandler
public abstract class URLStreamHandler {
abstract protected URLConnection openConnection(URL u) throws IOException;
protected URLConnection openConnection(URL u, Proxy p) throws IOException {
throw new UnsupportedOperationException("Method not implemented.");
}
}
# URL的实现示例
- http实现
public class Handler extends URLStreamHandler {
protected URLConnection openConnection(URL var1) throws IOException {
return this.openConnection(var1, (Proxy)null);
}
protected URLConnection openConnection(URL var1, Proxy var2) throws IOException {
return new HttpURLConnection(var1, var2, this);
}
//省略其他抽象...
}
//package java.net;
abstract public class HttpURLConnection extends URLConnection {
public static final int HTTP_OK = 200;
public static final int HTTP_CREATED = 201;
public static final int HTTP_ACCEPTED = 202;
public static final int HTTP_NOT_AUTHORITATIVE = 203;
public static final int HTTP_NO_CONTENT = 204;
public static final int HTTP_RESET = 205;
public static final int HTTP_PARTIAL = 206;
public static final int HTTP_MULT_CHOICE = 300;
public static final int HTTP_MOVED_PERM = 301;
public static final int HTTP_MOVED_TEMP = 302;
public static final int HTTP_SEE_OTHER = 303;
public static final int HTTP_NOT_MODIFIED = 304;
public static final int HTTP_USE_PROXY = 305;
public static final int HTTP_BAD_REQUEST = 400;
public static final int HTTP_UNAUTHORIZED = 401;
public static final int HTTP_PAYMENT_REQUIRED = 402;
public static final int HTTP_FORBIDDEN = 403;
public static final int HTTP_NOT_FOUND = 404;
public static final int HTTP_BAD_METHOD = 405;
public static final int HTTP_NOT_ACCEPTABLE = 406;
public static final int HTTP_PROXY_AUTH = 407;
public static final int HTTP_CLIENT_TIMEOUT = 408;
public static final int HTTP_CONFLICT = 409;
public static final int HTTP_GONE = 410;
public static final int HTTP_LENGTH_REQUIRED = 411;
public static final int HTTP_PRECON_FAILED = 412;
public static final int HTTP_ENTITY_TOO_LARGE = 413;
public static final int HTTP_REQ_TOO_LONG = 414;
public static final int HTTP_UNSUPPORTED_TYPE = 415;
public static final int HTTP_INTERNAL_ERROR = 500;
public static final int HTTP_NOT_IMPLEMENTED = 501;
public static final int HTTP_BAD_GATEWAY = 502;
public static final int HTTP_UNAVAILABLE = 503;
public static final int HTTP_GATEWAY_TIMEOUT = 504;
public static final int HTTP_VERSION = 505;
//省略其它抽象...
}
//sun.net.www.protocol.http;
public class HttpURLConnection extends java.net.HttpURLConnection {
private boolean connecting;
public void connect() throws IOException {
synchronized(this) {
this.connecting = true;
}
this.plainConnect();
}
protected void plainConnect() throws IOException {
synchronized(this) {
if (this.connected) {
return;
}
}
SocketPermission var1 = this.URLtoSocketPermission(this.url);
if (var1 != null) {
try {
AccessController.doPrivilegedWithCombiner(new PrivilegedExceptionAction<Void>() {
public Void run() throws IOException {
HttpURLConnection.this.plainConnect0();
return null;
}
}, (AccessControlContext)null, var1);
} catch (PrivilegedActionException var3) {
throw (IOException)var3.getException();
}
} else {
this.plainConnect0();
}
}
protected void plainConnect0() throws IOException {
if (this.cacheHandler != null && this.getUseCaches()) {
try {
URI var1 = ParseUtil.toURI(this.url);
if (var1 != null) {
this.cachedResponse = this.cacheHandler.get(var1, this.getRequestMethod(), this.getUserSetHeaders().getHeaders());
if ("https".equalsIgnoreCase(var1.getScheme()) && !(this.cachedResponse instanceof SecureCacheResponse)) {
this.cachedResponse = null;
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest("Cache Request for " + var1 + " / " + this.getRequestMethod());
logger.finest("From cache: " + (this.cachedResponse != null ? this.cachedResponse.toString() : "null"));
}
if (this.cachedResponse != null) {
this.cachedHeaders = this.mapToMessageHeader(this.cachedResponse.getHeaders());
this.cachedInputStream = this.cachedResponse.getBody();
}
}
} catch (IOException var6) {
}
if (this.cachedHeaders != null && this.cachedInputStream != null) {
this.connected = true;
return;
}
this.cachedResponse = null;
}
try {
if (this.instProxy != null) {
if (!this.failedOnce) {
this.http = this.getNewHttpClient(this.url, this.instProxy, this.connectTimeout);
this.http.setReadTimeout(this.readTimeout);
} else {
this.http = this.getNewHttpClient(this.url, this.instProxy, this.connectTimeout, false);
this.http.setReadTimeout(this.readTimeout);
}
} else {
ProxySelector var9 = (ProxySelector)AccessController.doPrivileged(new PrivilegedAction<ProxySelector>() {
public ProxySelector run() {
return ProxySelector.getDefault();
}
});
if (var9 == null) {
if (!this.failedOnce) {
this.http = this.getNewHttpClient(this.url, (Proxy)null, this.connectTimeout);
this.http.setReadTimeout(this.readTimeout);
} else {
this.http = this.getNewHttpClient(this.url, (Proxy)null, this.connectTimeout, false);
this.http.setReadTimeout(this.readTimeout);
}
} else {
URI var2 = ParseUtil.toURI(this.url);
if (logger.isLoggable(Level.FINEST)) {
logger.finest("ProxySelector Request for " + var2);
}
Iterator var3 = var9.select(var2).iterator();
while(var3.hasNext()) {
Proxy var4 = (Proxy)var3.next();
try {
if (!this.failedOnce) {
this.http = this.getNewHttpClient(this.url, var4, this.connectTimeout);
this.http.setReadTimeout(this.readTimeout);
} else {
this.http = this.getNewHttpClient(this.url, var4, this.connectTimeout, false);
this.http.setReadTimeout(this.readTimeout);
}
if (logger.isLoggable(Level.FINEST) && var4 != null) {
logger.finest("Proxy used: " + var4.toString());
}
break;
} catch (IOException var7) {
if (var4 == Proxy.NO_PROXY) {
throw var7;
}
var9.connectFailed(var2, var4.address(), var7);
if (!var3.hasNext()) {
this.http = this.getNewHttpClient(this.url, (Proxy)null, this.connectTimeout, false);
this.http.setReadTimeout(this.readTimeout);
break;
}
}
}
}
}
this.ps = (PrintStream)this.http.getOutputStream();
} catch (IOException var8) {
throw var8;
}
this.connected = true;
}
protected HttpClient getNewHttpClient(URL var1, Proxy var2, int var3) throws IOException {
return HttpClient.New(var1, var2, var3, this);
}
//省略其他抽象...
}
//sun.net.www.http;
public class HttpClient extends NetworkClient {
protected HttpClient(URL var1, Proxy var2, int var3) throws IOException {
//省略其其它抽象...
this.openServer();
}
protected synchronized void openServer() throws IOException {
SecurityManager var1 = System.getSecurityManager();
if (var1 != null) {
var1.checkConnect(this.host, this.port);
}
if (!this.keepingAlive) {
if (!this.url.getProtocol().equals("http") && !this.url.getProtocol().equals("https")) {
if (this.proxy != null && this.proxy.type() == Type.HTTP) {
URLConnection.setProxiedHost(this.host);
this.privilegedOpenServer((InetSocketAddress)this.proxy.address());
this.usingProxy = true;
} else {
super.openServer(this.host, this.port);
this.usingProxy = false;
}
} else if (this.proxy != null && this.proxy.type() == Type.HTTP) {
URLConnection.setProxiedHost(this.host);
this.privilegedOpenServer((InetSocketAddress)this.proxy.address());
this.usingProxy = true;
} else {
this.openServer(this.host, this.port);
this.usingProxy = false;
}
}
}
//省略其它抽象...
}
//sun.net;
public class NetworkClient {
public void openServer(String var1, int var2) throws IOException, UnknownHostException {
if (this.serverSocket != null) {
this.closeServer();
}
this.serverSocket = this.doConnect(var1, var2);
try {
this.serverOutput = new PrintStream(new BufferedOutputStream(this.serverSocket.getOutputStream()), true, encoding);
} catch (UnsupportedEncodingException var4) {
throw new InternalError(encoding + "encoding not found", var4);
}
this.serverInput = new BufferedInputStream(this.serverSocket.getInputStream());
}
protected Socket doConnect(String var1, int var2) throws IOException, UnknownHostException {
Socket var3;
if (this.proxy != null) {
if (this.proxy.type() == Type.SOCKS) {
var3 = (Socket)AccessController.doPrivileged(new PrivilegedAction<Socket>() {
public Socket run() {
return new Socket(NetworkClient.this.proxy);
}
});
} else if (this.proxy.type() == Type.DIRECT) {
var3 = this.createSocket();
} else {
var3 = new Socket(Proxy.NO_PROXY);
}
} else {
var3 = this.createSocket();
}
if (this.connectTimeout >= 0) {
var3.connect(new InetSocketAddress(var1, var2), this.connectTimeout);
} else if (defaultConnectTimeout > 0) {
var3.connect(new InetSocketAddress(var1, var2), defaultConnectTimeout);
} else {
var3.connect(new InetSocketAddress(var1, var2));
}
if (this.readTimeout >= 0) {
var3.setSoTimeout(this.readTimeout);
} else if (defaultSoTimeout > 0) {
var3.setSoTimeout(defaultSoTimeout);
}
return var3;
}
//省略其它抽象...
}
- file实现
//package sun.net.www.protocol.file;
public class Handler extends URLStreamHandler {
public synchronized URLConnection openConnection(URL var1, Proxy var2) throws IOException {
String var4 = var1.getFile();
String var5 = var1.getHost();
String var3 = ParseUtil.decode(var4);
var3 = var3.replace('/', '\\');
var3 = var3.replace('|', ':');
if (var5 != null && !var5.equals("") && !var5.equalsIgnoreCase("localhost") && !var5.equals("~")) {
var3 = "\\\\" + var5 + var3;
File var6 = new File(var3);
if (var6.exists()) {
return this.createFileURLConnection(var1, var6);
} else {
URLConnection var7;
try {
URL var8 = new URL("ftp", var5, var4 + (var1.getRef() == null ? "" : "#" + var1.getRef()));
if (var2 != null) {
var7 = var8.openConnection(var2);
} else {
var7 = var8.openConnection();
}
} catch (IOException var10) {
var7 = null;
}
if (var7 == null) {
throw new IOException("Unable to connect to: " + var1.toExternalForm());
} else {
return var7;
}
}
} else {
return this.createFileURLConnection(var1, new File(var3));
}
}
protected URLConnection createFileURLConnection(URL var1, File var2) {
return new FileURLConnection(var1, var2);
}
//省略其他抽象...
}
public class FileURLConnection extends URLConnection {
public void connect() throws IOException {
if (!this.connected) {
try {
this.filename = this.file.toString();
this.isDirectory = this.file.isDirectory();
if (this.isDirectory) {
String[] var1 = this.file.list();
if (var1 == null) {
throw new FileNotFoundException(this.filename + " exists, but is not accessible");
}
this.files = Arrays.asList(var1);
} else {
this.is = new BufferedInputStream(new FileInputStream(this.filename));
boolean var4 = ProgressMonitor.getDefault().shouldMeterInput(this.url, "GET");
if (var4) {
ProgressSource var2 = new ProgressSource(this.url, "GET", this.file.length());
this.is = new MeteredStream(this.is, var2, this.file.length());
}
}
} catch (IOException var3) {
throw var3;
}
this.connected = true;
}
}
//省略其它抽象...
}
- ftp实现
//package sun.net.www.protocol.ftp;
public class Handler extends URLStreamHandler {
protected URLConnection openConnection(URL var1) throws IOException {
return this.openConnection(var1, (Proxy)null);
}
protected URLConnection openConnection(URL var1, Proxy var2) throws IOException {
return new FtpURLConnection(var1, var2);
}
//省略其它抽象...
}
//sun.net.www.protocol.ftp;
public class FtpURLConnection extends URLConnection {
public synchronized void connect() throws IOException {
//省略其它抽象...
try {
this.ftp = FtpClient.create();
if (var1 != null) {
this.ftp.setProxy(var1);
}
this.setTimeouts();
if (this.port != -1) {
this.ftp.connect(new InetSocketAddress(this.host, this.port));
} else {
this.ftp.connect(new InetSocketAddress(this.host, FtpClient.defaultPort()));
}
} catch (UnknownHostException var9) {
throw var9;
} catch (FtpProtocolException var10) {
if (this.ftp != null) {
try {
this.ftp.close();
} catch (IOException var7) {
var10.addSuppressed(var7);
}
}
throw new IOException(var10);
}
try {
this.ftp.login(this.user, this.password == null ? null : this.password.toCharArray());
} catch (FtpProtocolException var8) {
this.ftp.close();
throw new FtpLoginException("Invalid username/password");
}
this.connected = true;
}
}
//package sun.net.ftp;
public abstract class FtpClient implements Closeable {
public abstract FtpClient connect(SocketAddress var1) throws FtpProtocolException, IOException;
//省略其它抽象...
}
//package sun.net.ftp.impl;
public class FtpClient extends sun.net.ftp.FtpClient {
public sun.net.ftp.FtpClient connect(SocketAddress var1) throws FtpProtocolException, IOException {
return this.connect(var1, -1);
}
public sun.net.ftp.FtpClient connect(SocketAddress var1, int var2) throws FtpProtocolException, IOException {
if (!(var1 instanceof InetSocketAddress)) {
throw new IllegalArgumentException("Wrong address type");
} else {
this.serverAddr = (InetSocketAddress)var1;
this.tryConnect(this.serverAddr, var2);
if (!this.readReply()) {
throw new FtpProtocolException("Welcome message: " + this.getResponseString(), this.lastReplyCode);
} else {
this.welcomeMsg = this.getResponseString().substring(4);
return this;
}
}
}
private Socket doConnect(InetSocketAddress var1, int var2) throws IOException {
Socket var3;
if (this.proxy != null) {
if (this.proxy.type() == Type.SOCKS) {
var3 = (Socket)AccessController.doPrivileged(new PrivilegedAction<Socket>() {
public Socket run() {
return new Socket(FtpClient.this.proxy);
}
});
} else {
var3 = new Socket(Proxy.NO_PROXY);
}
} else {
var3 = new Socket();
}
if (var2 >= 0) {
var3.connect(var1, var2);
} else if (this.connectTimeout >= 0) {
var3.connect(var1, this.connectTimeout);
} else if (defaultConnectTimeout > 0) {
var3.connect(var1, defaultConnectTimeout);
} else {
var3.connect(var1);
}
if (this.readTimeout >= 0) {
var3.setSoTimeout(this.readTimeout);
} else if (defaultSoTimeout > 0) {
var3.setSoTimeout(defaultSoTimeout);
}
return var3;
}
//省略其他抽象...
}
# 类或者类加载器获取文件
# 类加载器获取当前类路径资源
- 获取当前工作路径
public class Test {
public static void main(String[] args) throws IOException {
System.out.println(ClassLoader.getSystemResource(""));
//输出: file:/D:/dev/springSource/practice/target/test-classes/
}
}
//下同
public class Test {
public static void main(String[] args) throws IOException {
System.out.println(Thread.currentThread().getContextClassLoader().getResource(""));
}
}
- 获取当前工作路径资源
public class Test {
public static void main(String[] args) throws IOException {
System.out.println(ClassLoader.getSystemResource("abc.txt"));
//存在返回: file:/D:/dev/springSource/practice/target/test-classes/abc.txt
//不存在返回: null
}
}
//下同
public class Test {
public static void main(String[] args) throws IOException {
System.out.println(Thread.currentThread().getContextClassLoader().getResource("abc.txt"));
}
}
- 枚举当前工作类路径资源
public class Test {
public static void main(String[] args) throws IOException {
Enumeration<URL> urls= Thread.currentThread().getContextClassLoader().getResources("");
while (urls.hasMoreElements()){
System.out.println(urls.nextElement());
}
}
//输出
/** file:/D:/dev/springSource/practice/target/test-classes/
file:/D:/dev/springSource/practice/target/classes/
file:/D:/dev/springSource/springContext/target/classes/
file:/D:/dev/springSource/springCore/target/classes/
file:/D:/dev/springSource/springJcl/target/classes/
file:/D:/dev/springSource/springBeans/target/classes/
file:/D:/dev/springSource/springAop/target/classes/
file:/D:/dev/springSource/springExpression/target/classes/
file:/D:/dev/springSource/springInstrument/target/classes/
file:/D:/dev/springSource/springWeb/target/classes/
file:/D:/dev/springSource/springOxm/target/classes/
file:/D:/dev/springSource/springWebmvc/target/classes/
file:/D:/dev/springSource/springContextSupport/target/classes/
file:/D:/dev/springSource/springTx/target/classes/
file:/D:/dev/springSource/springJdbc/target/classes/
**/
}
# 注意事项
- ClassLoader可以获取到当前项目的资源,包括启动类所在的jar以及普通的jar;
- 使用ClassLoader获取路径时,不要使用前缀的/号,会导致获取不到资源,具体原因有待考究
- 要注意idea的包名问题,是收缩包,还是包名.这个也比较坑;
# 类获取伪路径资源(classpath)资源
- 注意事项: 路径不以“/”开头时,默认是从此类所在的包下取资源;path以“/”开头时,则是从ClassPath根下获取;
public class Test {
public static void main(String[] args) throws IOException {
System.out.println(Test.class.getResource(""));
//输出: file:/D:/dev/springSource/practice/target/test-classes/com/automannn/test/
}
}
public class Test {
public static void main(String[] args) throws IOException {
System.out.println(Test.class.getResource("/"));
//输出: file:/D:/dev/springSource/practice/target/test-classes/
}
}
# 类获取jar包中的资源
- jar加载器
//package sun.misc;
public class URLClassPath {
static class JarLoader extends URLClassPath.Loader {
private JarFile jar;
JarLoader(URL var1, URLStreamHandler var2, HashMap<String, URLClassPath.Loader> var3, AccessControlContext var4) throws IOException {
super(new URL("jar", "", -1, var1 + "!/", var2));
this.csu = var1;
this.handler = var2;
this.lmap = var3;
this.acc = var4;
if (!this.isOptimizable(var1)) {
this.ensureOpen();
} else {
String var5 = var1.getFile();
if (var5 != null) {
var5 = ParseUtil.decode(var5);
File var6 = new File(var5);
this.metaIndex = MetaIndex.forJar(var6);
if (this.metaIndex != null && !var6.exists()) {
this.metaIndex = null;
}
}
if (this.metaIndex == null) {
this.ensureOpen();
}
}
}
URL findResource(String var1, boolean var2) {
Resource var3 = this.getResource(var1, var2);
return var3 != null ? var3.getURL() : null;
}
//省略其它抽象...
}
}
# spring中常见文件句柄
# ClassPathResource
- 获取classPath下的资源
# FileSystemResource
- 获取文件系统资源
# UrlResource
- 基于URL的资源句柄
# ServletContextResource
- 基于ServletContextResource的资源句柄
- 正常情况下,其位于: /WEB-INF/classes/ 路径下
# resource资源句柄的使用注意事项
- 参考文档-excel模板下载报错cannot be resolved to absolute file path because it does not reside in the file system: (opens new window)
- 简言之,不能在jar包中,使用resource.getFile,会获取资源的绝对路径,会报错! 可以获取资源流;
# classPath
- java种有两个classPath,
bootstrapClassPath
以及classPath
# bootstrapClasspath
通过
-Xbootclasspath
JVM参数可以指定bootstrapClassPath的位置-Xbootclasspath:<path> #完全取代基本核心的javaClass搜索路径 -Xbootclasspath/a:<path> #后缀在核心class搜索路径后,常用! -Xbootclasspath/p:<path> #前缀在核心class路径前面,不常用,避免引起不必要的冲突
通过
System.getProperty("sun.boot.class.path")
可获取bootstrapClasspath的位置getResource
等资源加载方法,也遵循双亲委派模型,委托到启动类加载器时,会从bootstrap classpath对应的jar包或目录中加载资源.
D:\Program Files\Java\jdk1.8.0_212\jre\lib\resources.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\rt.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\sunrsasign.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\jsse.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\jce.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\charsets.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\jfr.jar
D:\Program Files\Java\jdk1.8.0_212\jre\classes
# extention directory
- 双亲委派过程种,如果启动类加载器无法加载资源,则扩展类加载器会尝试从扩展目录的jar包中加载;
- 通过
-Djava.ext.dirs=xxx;fdfsd;
可设置扩展目录 - 通过
System.getProperty("java.ext.dirs")
可获取扩展目录
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext
C:\Windows\Sun\Java\lib\ext
# classpath
- 用来定位用户自定义的类和资源,这里的用户是相对于jdk官方意外的个人或组织
- 通过
-classpath
jvm参数,可以指定当前的classpath资源 - 通过
System.getProperty("java.class.path")
获取当前的classPath
D:\Program Files\Java\jdk1.8.0_212\jre\lib\charsets.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\deploy.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\access-bridge-64.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\cldrdata.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\dnsns.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\jaccess.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\jfxrt.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\localedata.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\nashorn.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunec.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunjce_provider.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunmscapi.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunpkcs11.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\zipfs.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\javaws.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\jce.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\jfr.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\jfxswt.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\jsse.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\management-agent.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\plugin.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\resources.jar
D:\Program Files\Java\jdk1.8.0_212\jre\lib\rt.jar
E:\dev\natm-generator\generator-starter\target\test-classes
E:\dev\natm-generator\generator-starter\target\classes
E:\dev\natm-generator\generator-adapter\target\classes
D:\mvn\repository\com\automannn\natm\natm-component-web-support\1.1.2.9\natm-component-web-support-1.1.2.9.jar
D:\mvn\repository\org\springframework\spring-context\5.2.10.RELEASE\spring-context-5.2.10.RELEASE.jar
D:\mvn\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar
D:\mvn\repository\com\automannn\natm\natm-component-common\1.1.2.9\natm-component-common-1.1.2.9.jar
D:\mvn\repository\com\alibaba\fastjson\1.2.47\fastjson-1.2.47.jar
D:\mvn\repository\cn\hutool\hutool-all\5.7.14\hutool-all-5.7.14.jar
E:\dev\natm-generator\generator-app\target\classes
E:\dev\natm-generator\generator-client\target\classes
D:\mvn\repository\cn\afterturn\easypoi-spring-boot-starter\4.0.0\easypoi-spring-boot-starter-4.0.0.jar
D:\mvn\repository\cn\afterturn\easypoi-web\4.0.0\easypoi-web-4.0.0.jar
D:\mvn\repository\cn\afterturn\easypoi-base\4.0.0\easypoi-base-4.0.0.jar
D:\mvn\repository\org\apache\poi\poi-ooxml-schemas\4.0.0\poi-ooxml-schemas-4.0.0.jar
D:\mvn\repository\com\google\guava\guava\16.0.1\guava-16.0.1.jar
D:\mvn\repository\ognl\ognl\3.2.6\ognl-3.2.6.jar
D:\mvn\repository\org\javassist\javassist\3.20.0-GA\javassist-3.20.0-GA.jar
D:\mvn\repository\cn\afterturn\easypoi-annotation\4.0.0\easypoi-annotation-4.0.0.jar
E:\dev\natm-generator\generator-components\generator-component-pdmaner\target\classes
D:\mvn\repository\com\deepoove\poi-tl\1.12.1\poi-tl-1.12.1.jar
D:\mvn\repository\org\apache\poi\poi-ooxml\5.2.2\poi-ooxml-5.2.2.jar
D:\mvn\repository\org\apache\poi\poi\5.2.2\poi-5.2.2.jar
D:\mvn\repository\org\apache\commons\commons-math3\3.6.1\commons-math3-3.6.1.jar
D:\mvn\repository\com\zaxxer\SparseBitSet\1.2\SparseBitSet-1.2.jar
D:\mvn\repository\org\apache\poi\poi-ooxml-lite\5.2.2\poi-ooxml-lite-5.2.2.jar
D:\mvn\repository\org\apache\xmlbeans\xmlbeans\5.0.3\xmlbeans-5.0.3.jar
D:\mvn\repository\xml-apis\xml-apis\1.4.01\xml-apis-1.4.01.jar
D:\mvn\repository\org\apache\commons\commons-compress\1.21\commons-compress-1.21.jar
D:\mvn\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0.jar
D:\mvn\repository\com\github\virtuald\curvesapi\1.07\curvesapi-1.07.jar
D:\mvn\repository\org\apache\commons\commons-collections4\4.4\commons-collections4-4.4.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-transcoder\1.14\batik-transcoder-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-anim\1.14\batik-anim-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-css\1.14\batik-css-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-ext\1.14\batik-ext-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-parser\1.14\batik-parser-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-svg-dom\1.14\batik-svg-dom-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-awt-util\1.14\batik-awt-util-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\xmlgraphics-commons\2.6\xmlgraphics-commons-2.6.jar
D:\mvn\repository\commons-logging\commons-logging\1.0.4\commons-logging-1.0.4.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-bridge\1.14\batik-bridge-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-script\1.14\batik-script-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-dom\1.14\batik-dom-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-gvt\1.14\batik-gvt-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-shared-resources\1.14\batik-shared-resources-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-svggen\1.14\batik-svggen-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-util\1.14\batik-util-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-constants\1.14\batik-constants-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-i18n\1.14\batik-i18n-1.14.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-xml\1.14\batik-xml-1.14.jar
D:\mvn\repository\xml-apis\xml-apis-ext\1.3.04\xml-apis-ext-1.3.04.jar
D:\mvn\repository\org\apache\xmlgraphics\batik-codec\1.14\batik-codec-1.14.jar
D:\mvn\repository\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar
E:\dev\natm-generator\generator-infrastructure\target\classes
E:\dev\natm-generator\generator-domain\target\classes
D:\mvn\repository\com\alibaba\druid-spring-boot-starter\1.1.24\druid-spring-boot-starter-1.1.24.jar
D:\mvn\repository\com\alibaba\druid\1.1.24\druid-1.1.24.jar
D:\mvn\repository\mysql\mysql-connector-java\8.0.22\mysql-connector-java-8.0.22.jar
D:\mvn\repository\com\automannn\natm\natm-component-security\1.1.2.9\natm-component-security-1.1.2.9.jar
D:\mvn\repository\org\springframework\boot\spring-boot-starter-security\2.3.5.RELEASE\spring-boot-starter-security-2.3.5.RELEASE.jar
D:\mvn\repository\org\apache\commons\commons-pool2\2.8.1\commons-pool2-2.8.1.jar
D:\mvn\repository\org\springframework\security\spring-security-config\5.3.5.RELEASE\spring-security-config-5.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\security\spring-security-oauth2-client\5.3.5.RELEASE\spring-security-oauth2-client-5.3.5.RELEASE.jar
D:\mvn\repository\com\nimbusds\oauth2-oidc-sdk\7.1.1\oauth2-oidc-sdk-7.1.1.jar
D:\mvn\repository\com\github\stephenc\jcip\jcip-annotations\1.0-1\jcip-annotations-1.0-1.jar
D:\mvn\repository\com\nimbusds\content-type\2.0\content-type-2.0.jar
D:\mvn\repository\net\minidev\json-smart\2.3\json-smart-2.3.jar
D:\mvn\repository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar
D:\mvn\repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar
D:\mvn\repository\com\nimbusds\lang-tag\1.4.4\lang-tag-1.4.4.jar
D:\mvn\repository\org\springframework\security\spring-security-oauth2-core\5.3.5.RELEASE\spring-security-oauth2-core-5.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\security\spring-security-oauth2-jose\5.3.5.RELEASE\spring-security-oauth2-jose-5.3.5.RELEASE.jar
D:\mvn\repository\com\nimbusds\nimbus-jose-jwt\8.19\nimbus-jose-jwt-8.19.jar
D:\mvn\repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar
D:\mvn\repository\org\jsoup\jsoup\1.8.3\jsoup-1.8.3.jar
D:\mvn\repository\com\aliyun\dysmsapi20170525\2.0.23\dysmsapi20170525-2.0.23.jar
D:\mvn\repository\com\aliyun\tea-util\0.2.16\tea-util-0.2.16.jar
D:\mvn\repository\com\google\code\gson\gson\2.8.6\gson-2.8.6.jar
D:\mvn\repository\com\aliyun\endpoint-util\0.0.7\endpoint-util-0.0.7.jar
D:\mvn\repository\com\aliyun\tea\1.2.0\tea-1.2.0.jar
D:\mvn\repository\com\squareup\okhttp3\okhttp\3.14.9\okhttp-3.14.9.jar
D:\mvn\repository\com\squareup\okio\okio\1.17.2\okio-1.17.2.jar
D:\mvn\repository\org\jacoco\org.jacoco.agent\0.8.4\org.jacoco.agent-0.8.4-runtime.jar
D:\mvn\repository\com\aliyun\tea-openapi\0.2.8\tea-openapi-0.2.8.jar
D:\mvn\repository\com\aliyun\credentials-java\0.2.4\credentials-java-0.2.4.jar
D:\mvn\repository\org\ini4j\ini4j\0.5.4\ini4j-0.5.4.jar
D:\mvn\repository\javax\xml\bind\jaxb-api\2.3.1\jaxb-api-2.3.1.jar
D:\mvn\repository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar
D:\mvn\repository\com\sun\xml\bind\jaxb-core\2.3.0\jaxb-core-2.3.0.jar
D:\mvn\repository\com\sun\xml\bind\jaxb-impl\2.3.0\jaxb-impl-2.3.0.jar
D:\mvn\repository\com\aliyun\alibabacloud-gateway-spi\0.0.1\alibabacloud-gateway-spi-0.0.1.jar
D:\mvn\repository\com\aliyun\tea-xml\0.1.5\tea-xml-0.1.5.jar
D:\mvn\repository\org\dom4j\dom4j\2.0.3\dom4j-2.0.3.jar
D:\mvn\repository\com\aliyun\openapiutil\0.2.0\openapiutil-0.2.0.jar
D:\mvn\repository\org\bouncycastle\bcpkix-jdk15on\1.65\bcpkix-jdk15on-1.65.jar
D:\mvn\repository\org\bouncycastle\bcprov-jdk15on\1.65\bcprov-jdk15on-1.65.jar
D:\mvn\repository\commons-codec\commons-codec\1.14\commons-codec-1.14.jar
D:\mvn\repository\org\apache\commons\commons-email\1.5\commons-email-1.5.jar
D:\mvn\repository\com\sun\mail\javax.mail\1.5.6\javax.mail-1.5.6.jar
D:\mvn\repository\javax\activation\activation\1.1\activation-1.1.jar
D:\mvn\repository\com\github\pagehelper\pagehelper-spring-boot-starter\1.2.12\pagehelper-spring-boot-starter-1.2.12.jar
D:\mvn\repository\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.0.1\mybatis-spring-boot-starter-2.0.1.jar
D:\mvn\repository\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.0.1\mybatis-spring-boot-autoconfigure-2.0.1.jar
D:\mvn\repository\org\mybatis\mybatis\3.5.1\mybatis-3.5.1.jar
D:\mvn\repository\com\github\pagehelper\pagehelper-spring-boot-autoconfigure\1.2.12\pagehelper-spring-boot-autoconfigure-1.2.12.jar
D:\mvn\repository\com\github\pagehelper\pagehelper\5.1.10\pagehelper-5.1.10.jar
D:\mvn\repository\com\github\jsqlparser\jsqlparser\2.0\jsqlparser-2.0.jar
D:\mvn\repository\org\mapstruct\mapstruct\1.4.1.Final\mapstruct-1.4.1.Final.jar
D:\mvn\repository\org\mapstruct\mapstruct-processor\1.4.1.Final\mapstruct-processor-1.4.1.Final.jar
D:\mvn\repository\com\automannn\natm\natm-component-dao-support\1.1.2.9\natm-component-dao-support-1.1.2.9.jar
E:\dev\natm-generator\generator-components\generator-component-velocity\target\classes
D:\mvn\repository\org\apache\velocity\velocity-engine-core\2.0\velocity-engine-core-2.0.jar
D:\mvn\repository\com\automannn\natm\natm-adapter\1.1.2.9\natm-adapter-1.1.2.9.jar
D:\mvn\repository\com\automannn\natm\natm-application\1.1.2.9\natm-application-1.1.2.9.jar
D:\mvn\repository\com\automannn\natm\natm-client\1.1.2.9\natm-client-1.1.2.9.jar
D:\mvn\repository\com\automannn\natm\natm-domain\1.1.2.9\natm-domain-1.1.2.9.jar
D:\mvn\repository\com\automannn\natm\natm-infrastructure\1.1.2.9\natm-infrastructure-1.1.2.9.jar
D:\mvn\repository\org\springframework\security\spring-security-core\5.3.5.RELEASE\spring-security-core-5.3.5.RELEASE.jar
D:\mvn\repository\com\automannn\natm\natm-component-service-support\1.1.2.9\natm-component-service-support-1.1.2.9.jar
D:\mvn\repository\org\aspectj\aspectjweaver\1.9.6\aspectjweaver-1.9.6.jar
D:\mvn\repository\org\springframework\spring-webmvc\5.2.10.RELEASE\spring-webmvc-5.2.10.RELEASE.jar
D:\mvn\repository\org\springframework\spring-aop\5.2.10.RELEASE\spring-aop-5.2.10.RELEASE.jar
D:\mvn\repository\org\springframework\spring-beans\5.2.10.RELEASE\spring-beans-5.2.10.RELEASE.jar
D:\mvn\repository\org\springframework\spring-core\5.2.10.RELEASE\spring-core-5.2.10.RELEASE.jar
D:\mvn\repository\org\springframework\spring-expression\5.2.10.RELEASE\spring-expression-5.2.10.RELEASE.jar
D:\mvn\repository\org\springframework\security\spring-security-web\5.3.5.RELEASE\spring-security-web-5.3.5.RELEASE.jar
D:\mvn\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar
D:\mvn\repository\org\springframework\session\spring-session-data-redis\2.3.1.RELEASE\spring-session-data-redis-2.3.1.RELEASE.jar
D:\mvn\repository\org\springframework\data\spring-data-redis\2.3.5.RELEASE\spring-data-redis-2.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\data\spring-data-keyvalue\2.3.5.RELEASE\spring-data-keyvalue-2.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\data\spring-data-commons\2.3.5.RELEASE\spring-data-commons-2.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\spring-tx\5.2.10.RELEASE\spring-tx-5.2.10.RELEASE.jar
D:\mvn\repository\org\springframework\spring-oxm\5.2.10.RELEASE\spring-oxm-5.2.10.RELEASE.jar
D:\mvn\repository\org\springframework\spring-context-support\5.2.10.RELEASE\spring-context-support-5.2.10.RELEASE.jar
D:\mvn\repository\org\springframework\session\spring-session-core\2.3.1.RELEASE\spring-session-core-2.3.1.RELEASE.jar
D:\mvn\repository\org\springframework\spring-jcl\5.2.10.RELEASE\spring-jcl-5.2.10.RELEASE.jar
D:\mvn\repository\org\springframework\boot\spring-boot-starter-data-redis\2.3.5.RELEASE\spring-boot-starter-data-redis-2.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\boot\spring-boot-starter\2.3.5.RELEASE\spring-boot-starter-2.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\boot\spring-boot\2.3.5.RELEASE\spring-boot-2.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\boot\spring-boot-starter-logging\2.3.5.RELEASE\spring-boot-starter-logging-2.3.5.RELEASE.jar
D:\mvn\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar
D:\mvn\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar
D:\mvn\repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar
D:\mvn\repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar
D:\mvn\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar
D:\mvn\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar
D:\mvn\repository\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar
D:\mvn\repository\io\lettuce\lettuce-core\5.3.5.RELEASE\lettuce-core-5.3.5.RELEASE.jar
D:\mvn\repository\io\netty\netty-common\4.1.53.Final\netty-common-4.1.53.Final.jar
D:\mvn\repository\io\netty\netty-handler\4.1.53.Final\netty-handler-4.1.53.Final.jar
D:\mvn\repository\io\netty\netty-resolver\4.1.53.Final\netty-resolver-4.1.53.Final.jar
D:\mvn\repository\io\netty\netty-buffer\4.1.53.Final\netty-buffer-4.1.53.Final.jar
D:\mvn\repository\io\netty\netty-codec\4.1.53.Final\netty-codec-4.1.53.Final.jar
D:\mvn\repository\io\netty\netty-transport\4.1.53.Final\netty-transport-4.1.53.Final.jar
D:\mvn\repository\io\projectreactor\reactor-core\3.3.11.RELEASE\reactor-core-3.3.11.RELEASE.jar
D:\mvn\repository\org\reactivestreams\reactive-streams\1.0.3\reactive-streams-1.0.3.jar
D:\mvn\repository\org\springframework\boot\spring-boot-starter-web\2.3.5.RELEASE\spring-boot-starter-web-2.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\boot\spring-boot-starter-json\2.3.5.RELEASE\spring-boot-starter-json-2.3.5.RELEASE.jar
D:\mvn\repository\com\fasterxml\jackson\core\jackson-databind\2.11.3\jackson-databind-2.11.3.jar
D:\mvn\repository\com\fasterxml\jackson\core\jackson-annotations\2.11.3\jackson-annotations-2.11.3.jar
D:\mvn\repository\com\fasterxml\jackson\core\jackson-core\2.11.3\jackson-core-2.11.3.jar
D:\mvn\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.3\jackson-datatype-jdk8-2.11.3.jar
D:\mvn\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.3\jackson-datatype-jsr310-2.11.3.jar
D:\mvn\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.3\jackson-module-parameter-names-2.11.3.jar
D:\mvn\repository\org\springframework\boot\spring-boot-starter-tomcat\2.3.5.RELEASE\spring-boot-starter-tomcat-2.3.5.RELEASE.jar
D:\mvn\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.39\tomcat-embed-core-9.0.39.jar
D:\mvn\repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar
D:\mvn\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.39\tomcat-embed-websocket-9.0.39.jar
D:\mvn\repository\org\springframework\spring-web\5.2.10.RELEASE\spring-web-5.2.10.RELEASE.jar
D:\mvn\repository\org\projectlombok\lombok\1.18.16\lombok-1.18.16.jar
D:\mvn\repository\com\baomidou\mybatis-plus-boot-starter\3.3.0\mybatis-plus-boot-starter-3.3.0.jar
D:\mvn\repository\com\baomidou\mybatis-plus\3.3.0\mybatis-plus-3.3.0.jar
D:\mvn\repository\com\baomidou\mybatis-plus-extension\3.3.0\mybatis-plus-extension-3.3.0.jar
D:\mvn\repository\com\baomidou\mybatis-plus-core\3.3.0\mybatis-plus-core-3.3.0.jar
D:\mvn\repository\com\baomidou\mybatis-plus-annotation\3.3.0\mybatis-plus-annotation-3.3.0.jar
D:\mvn\repository\org\mybatis\mybatis-spring\2.0.3\mybatis-spring-2.0.3.jar
D:\mvn\repository\org\springframework\boot\spring-boot-autoconfigure\2.3.5.RELEASE\spring-boot-autoconfigure-2.3.5.RELEASE.jar
D:\mvn\repository\org\springframework\boot\spring-boot-starter-jdbc\2.3.5.RELEASE\spring-boot-starter-jdbc-2.3.5.RELEASE.jar
D:\mvn\repository\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar
D:\mvn\repository\org\springframework\spring-jdbc\5.2.10.RELEASE\spring-jdbc-5.2.10.RELEASE.jar
D:\mvn\repository\org\apache\commons\commons-lang3\3.12.0\commons-lang3-3.12.0.jar
D:\automannn_apps\IntelliJ IDEA 2021.3.1\lib\idea_rt.jar
# 资源
- 资源可以分为两类:
location dependent
和location independent
# location dependent
- 可形象的理解为资源独立于程序
- 常见的如
new File("/root/resource/a.txt")
- 采用本地文件系统实现时,容易出现权限问题,以及集群同步问题
- 可以采用网络文件,分布式文件系统,是较优的解决方案
# location independent
- 可形象理解为资源依附于程序
- 最常用的实现方式为
class以及ClassLoader的getResource相关方法
- 资源的加载,也遵循双亲委派机制
# independent的实现方法
返回值 | 方法名 | Class类 | ClassLoader类 |
---|---|---|---|
URL | getResource(String name) | 有 | 有 |
InputStream | getResourceAsStream(String name) | 有 | 有 |
Enumeration | getResources(String name) | 无 | 有 |
URL | getSystemResource(String name) | 无 | 有 |
Enumeration | getSystemResources(String name) | 无 | 有 |
InputStream | getSystemResourceAsStream(String name) | 无 | 有 |
# Class获取资源
这里指的是直接通过Class调用,而非class.getClassLoader调用,后者实际上转为了
classLoader
获取资源开头以/开头,相对于classpath的路径资源
开头不以/开头,相对于当前class文件所在的目录的路径
public final class Class{
public java.net.URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResource(name);
}
return cl.getResource(name);
}
private String resolveName(String name) {
if (name == null) {
return name;
}
//xxx: 如果不以/开头,则拼接当前类所在的包路径作为目录
if (!name.startsWith("/")) {
Class<?> c = this;
while (c.isArray()) {
c = c.getComponentType();
}
String baseName = c.getName();
int index = baseName.lastIndexOf('.');
if (index != -1) {
name = baseName.substring(0, index).replace('.', '/')
+"/"+name;
}
} else {
//xxx: 如果以/开头,则要去除/
name = name.substring(1);
}
return name;
}
}
# ClassLoader获取资源
仅支持相对于classpath的路径,不能以/开头
以
/
开头的路径,则获取不到classpath
的文件关于这个现象的根本原因如下:
获取资源,主要有两类:
FileLoader
与JarLoader
,它们分别获取当前的classpath
的classes路径资源
,以及当前的classpath
的jar资源
jar是压缩资源的一种,记录了文件的索引信息,而文件获取,主要与URL机制有关系
class Test{ void doTest(){ String var1 = "automannn1.txt"; String var2 = "/automannn1.txt"; URL var4 = new URL(new URL("file:/D:/ProgramFiles/Java/jdk1.8.0_212/jre/classes/"), "."); URL var3 = new URL(new URL("file:/D:/ProgramFiles/Java/jdk1.8.0_212/jre/classes/automannnTest.txt"), var1); URL var5 = new URL(new URL("file:/D:/ProgramFiles/Java/jdk1.8.0_212/jre/classes/automannnTest.txt"), var2); //匹配 System.out.println(var3.getFile().startsWith(var4.getFile())); //不匹配 System.out.println(var5.getFile().startsWith(var4.getFile())); } }


