In writing an MVC framework, you need to scan the components from the package and register them with the container, and the JDK does not provide the out-of-the-box methods that can be implemented by itself.
Function:
Given a package name, it is programmed to get all the class files under the package (and all its child packages). For example, enter the package name com.myapp.util
, output the fully qualified name of the class under the package com.myapp.util.StringUtils
, and com.app.util.ImageUtils
so on.
Ideas:
Some Web servers unzip the jar package while the deployment is running, so the class file is in the normal file directory. If the Web server does not press the JAR package, the class file is directly present in the jar package. For the former, simply navigate to the directory where the class file is located, then read the class file name, and for the latter, you need to locate the directory where the jar package is located and then use JarInputStream
the Read jar package to get the class name.
Realize:
This is copied from the written project code directly, if you want to run this code, you need to change all the Logger.debug
System.out.println()
/** * This scanner are used to find out all classes in a package. * Created by WHF on 15-2-26. * / Public class Classpathpackagescanner implements Packagescanner { PrivateLogger Logger = Loggerfactory.getlogger (Classpathpackagescanner.class);PrivateString Basepackage;PrivateClassLoader cl;/** * Construct An instance and specify the base package it should scan. * @param basepackage The base package to scan. */ Public Classpathpackagescanner(String basepackage) { This. basepackage = Basepackage; This. CL = GetClass (). getClassLoader (); }/** * Construct An instance with the base package and class loader. * @param basepackage The base package to scan. * @param CL Use this class load to locate the package. */ Public Classpathpackagescanner(String Basepackage, ClassLoader cl) { This. basepackage = Basepackage; This. CL = CL; }/** * Get All fully qualified names located on the specified package * and its sub-package. * * @return A List of fully qualified names. * @throws ioexception * * @Override PublicList<string>getfullyqualifiedclassnamelist()throwsIOException {Logger.info ("Start scanning all classes under package {}", basepackage);returnDoscan (Basepackage,NewArraylist<> ()); }/** * Actually perform the scanning procedure. * * @param basepackage * @param namelist A list to contain the result. * @return A List of fully qualified names. * * @throws ioexception * * PrivateList<string>Doscan(String basepackage, list<string> namelist)throwsIOException {//Replace dots with splashesString Splashpath = Stringutil.dottosplash (basepackage);//Get file pathURL url = cl.getresource (Splashpath); String FilePath = Stringutil.getrootpath (URL);//Get classes in the. //If The Web server unzips the jar file, then the classes would exist in the form of //Normal file in the directory. //If The Web server does not unzip the jar file and then classes'll exist in jar file.list<string> names =NULL;//contains the name of the class file. E.g, apple.class'll be stored as "Apple" if(Isjarfile (FilePath)) {//Jar file if(Logger.isdebugenabled ()) {Logger.debug ("{} is a jar package", FilePath); } names = Readfromjarfile (FilePath, Splashpath); }Else{//Directory if(Logger.isdebugenabled ()) {Logger.debug ("{} is a directory", FilePath); } names = Readfromdirectory (FilePath); } for(String name:names) {if(Isclassfile (name)) {//namelist.add (Basepackage + "." + stringutil.trimextension (name));Namelist.add (Tofullyqualifiedname (name, basepackage)); }Else{//This is a directory //Check this directory for more classes //Do recursive invocationDoscan (Basepackage +"."+ Name, namelist); } }if(Logger.isdebugenabled ()) { for(String n:namelist) {Logger.debug ("Find {}", n); } }returnNameList; }/** * Convert Short class name to fully qualified name. * e.g., String-java.lang.String * / PrivateStringTofullyqualifiedname(String shortname, String basepackage) {StringBuilder SB =NewStringBuilder (Basepackage); Sb.append ('. '); Sb.append (Stringutil.trimextension (shortname));returnSb.tostring (); }PrivateList<string>Readfromjarfile(String jarpath, String splashedpackagename)throwsIOException {if(Logger.isdebugenabled ()) {Logger.debug ("read class from Jar package: {}", Jarpath); } Jarinputstream Jarin =NewJarinputstream (NewFileInputStream (Jarpath)); Jarentry entry = Jarin.getnextjarentry (); list<string> NameList =NewArraylist<> (); while(NULL! = Entry) {String name = Entry.getname ();if(Name.startswith (Splashedpackagename) && isclassfile (name)) {Namelist.add (name); } entry = Jarin.getnextjarentry (); }returnNameList; }PrivateList<string>readfromdirectory(String Path) {File File =NewFile (path); string[] names = File.list ();if(NULL= = names) {return NULL; }returnArrays.aslist (names); }Private Boolean Isclassfile(String name) {returnName.endswith (". Class"); }Private Boolean Isjarfile(String name) {returnName.endswith (". Jar"); }/** * for test purpose. */ Public Static void Main(string[] args)throwsException {Packagescanner scan =NewClasspathpackagescanner ("Cn.fh.lightning.bean"); Scan.getfullyqualifiedclassnamelist (); }}
The above code uses the StringUtils
class, as follows:
Public class stringutil { Private Stringutil() { }/** * "FILE:/HOME/WHF/CN/FH", "/home/whf/cn/fh" * "JAR:FILE:/HOME/WHF/FOO.JAR!CN/FH", "/HOME/WHF/FO" O.jar "* * Public StaticStringGetrootpath(URL URL) {String FILEURL = Url.getfile ();intpos = Fileurl.indexof ('! ');if(-1= = pos) {returnFILEURL; }returnFileurl.substring (5, POS); }/** * "cn.fh.lightning", "cn/fh/lightning" * @param name * @return * * Public StaticStringDottosplash(String name) {returnName.replaceall ("\\.","/"); }/** * "Apple.class", "Apple" * * Public StaticStringtrimextension(String name) {intpos = Name.indexof ('. ');if(-1! = pos) {returnName.substring (0, POS); }returnName }/** */application/home/home * @param uri * @return */ Public StaticStringTrimuri(String URI) {String trimmed = uri.substring (1);intSplashindex = Trimmed.indexof ('/');returnTrimmed.substring (Splashindex); }}
Execution Result:
How Java scans all classes under the specified package