论述网站建设整个流程,做代理,做网站的用多少钱,速成网站怎么做经过晚上和早上的努力#xff0c;终于补上框架最后一块了#xff0c;业务脚本侦听变化后自动编译jar包和调用#xff0c;实现维护成本低#xff0c;开发效率高的框架的基本体系。
实现自动编译jar包的类
package appcode;import org.w3c.dom.Document;
import org.w3c.do…经过晚上和早上的努力终于补上框架最后一块了业务脚本侦听变化后自动编译jar包和调用实现维护成本低开发效率高的框架的基本体系。
实现自动编译jar包的类
package appcode;import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.nio.file.Paths;
import java.util.concurrent.ConcurrentHashMap;
import java.util.*;
import java.io.*;
import org.apache.commons.io.FileUtils;
import java.nio.charset.StandardCharsets;
import java.nio.charset.*;public class AutoBuild {/// summary/// 缓存路径和类型允许多线程读一个线程写/// /summaryprivate static ConcurrentHashMapString, Boolean Building new ConcurrentHashMap();/// summary/// 编译指定路径的java代码/// /summary/// param namebasePath根路径/param/// param namecodepath类代码路径/param/// param nameproname工程名称不带后缀的/param/// param namestandprofilepath标准工程文件全路径/param/// returns返回空成功非空就是失败原因/returnspublic static String Build(String basePath,String codepath, String proname, String standprofilepath){Process proc null;try{//有编译的退出if (Building.containsKey(codepath)){System.out.println(codepath已经有进程在编译了退出本次编译);return ;}try{if (!Building.containsKey(codepath)){AutoBuild.HashTryAdd(Building, codepath, true);}}catch (Exception ex){System.out.println(编译并发ex.getMessage());}//编译临时总目录String buildPath Paths.get(basePath, AutoBuildTmp).toString();File directory new File(buildPath);//没有编译的临时目录就创建if (!directory.exists()) {directory.mkdirs();}//构建项目编译文件夹String proBuildPath Paths.get(buildPath, proname).toString();File directoryPro new File(proBuildPath);//没有编译的临时目录就创建if (!directoryPro.exists()) {directoryPro.mkdirs();}File fi new File(codepath);//编译目录类全名String clsFullName Paths.get(proBuildPath, fi.getName()).toString();System.out.println(拷贝: codepath 到: clsFullName);ListString lines FileUtils.readLines(fi, UTF-8);StringBuilder sbNewCodenew StringBuilder();String jarRootPathproBuildPath;System.out.println(包名称: proname);String [] arrproname.split(\\.);String pakName;if(arr.length1){for(int p0;parr.length-1;p){jarRootPathPaths.get(jarRootPath,arr[p]).toString();//创建jar包目录结构File directoryProJarChild new File(jarRootPath);//没有编译的临时目录就创建if (!directoryProJarChild.exists()) {directoryProJarChild.mkdirs();}if(pakName){pakNamearr[p];}else{pakName.arr[p];}}}sbNewCode.append(package pakName;System.lineSeparator());for (String line : lines) {sbNewCode.append(lineSystem.lineSeparator());}WriteText2File(clsFullName,sbNewCode.toString());//复制类代码//copyFile(new File(codepath), new File(clsFullName));String cmmand javac;StringBuilder retsb new StringBuilder();//得到javac编译命令串String cmdStrGetJavacStr(basePath,standprofilepath,fi.getName());System.out.println(编译命令: cmdStr);System.out.println(运行路径: directoryPro);// 创建进程并执行命令Process process Runtime.getRuntime().exec(cmdStr,null,directoryPro);// 获取命令行程序的输出结果BufferedReader reader new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line reader.readLine()) ! null) {retsb.append(line);}// 等待命令行程序执行完毕int exitCodeprocess.waitFor();// 关闭资源reader.close();System.out.println(编译返回: exitCode);//编译完成if (exitCode 0){// 获取目录中的所有文件和子目录File[] files directoryPro.listFiles();// 遍历文件和子目录for (File file : files) {if (!file.isDirectory()) {if (file.getName().endsWith(.class)) {copyFile(new File(file.toString()),new File(Paths.get(jarRootPath,file.getName()).toString()));}}}String pakStrjar cf proname.jar arr[0];System.out.println(打包命令: pakStr);System.out.println(打包运行路径: directoryPro);//打包jar包Process processPak Runtime.getRuntime().exec(pakStr,null,directoryPro);// 等待命令行程序执行完毕int exitCodePakprocessPak.waitFor();System.out.println(打包返回: exitCodePak);if (exitCodePak 0){String jarOutPathPaths.get(proBuildPath,proname.jar).toString();String jarBinPathPaths.get(basePath,BinAshx,proname.jar).toString();System.out.println(从: jarOutPath拷贝到:jarBinPath);//拷贝生成的jar包到BinAshxcopyFile(new File(jarOutPath), new File(jarBinPath));}//删除源文件//DeleteFile(new File(proBuildPath));return ;}String retstr retsb.toString();return retstr;}catch (Exception ex){return ex.getMessage();}finally{if (Building.containsKey(codepath)){Building.remove(codepath);}}}/// summary/// 解决多线程写并发/// /summary/// param namehs/param/// param namekey/param/// param namevalue/parampublic static void HashTryAdd(ConcurrentHashMapString, Boolean hs, String key, Boolean value){try{//更新类型if (!hs.containsKey(key)){hs.put(key, value);}}catch (Exception ex){System.out.println(并发编译捕获的正常日志忽略ex.getMessage());//更新类型if (!hs.containsKey(key)){hs.put(key, value);}}}///拷贝文件public static void copyFile(File srcFile, File destFile) {//判断原文件是否存在if (!srcFile.exists()) {throw new IllegalArgumentException(源文件 srcFile 不存在);}//判断原文件是否为一个文件if (!srcFile.isFile()) {throw new IllegalArgumentException(srcFile 不是一个文件);}try {FileInputStream in new FileInputStream(srcFile);FileOutputStream out new FileOutputStream(destFile);/*** 读取原文件以字节流的形式读到byte数组1024个字节1KB* 循环读取* in.read()读到bytes数组中位置从0-bytes.length*/byte[] bytes new byte[10 * 1024];int b; //b为读取到的字节长度while ((b in.read(bytes, 0, bytes.length)) ! -1) {//写入out.write(bytes, 0, b);out.flush();}//关闭in.close();out.close();}catch (IOException e) {e.printStackTrace();}}///删除文件和目录public static void DeleteFile(File file){//判断文件不为null或文件目录存在if (file null || !file.exists()){return;}//取得这个目录下的所有子文件对象File[] files file.listFiles();//遍历该目录下的文件对象for (File f: files){//判断子目录是否存在子目录,如果是文件则删除if (f.isDirectory()){DeleteFile(f);}else {f.delete();}}}///得到javac编译命令///basePath:根地址///standprofilepath:依赖jar包工程地址///javaName:java类文件名称private static String GetJavacStr(String basePath,String standprofilepath,String javaName){String retStrjavac -encoding UTF-8 -classpath ;try {//判断配置是否存在File file new File(standprofilepath);if (!file.exists()) {System.out.println(standprofilepath 文件不存在,请确认!);return ;}//解析xmlDocumentBuilderFactory factory DocumentBuilderFactory.newInstance();DocumentBuilder builder factory.newDocumentBuilder();Document document builder.parse(file);// 获得根节点Element rootElement document.getDocumentElement();// 获得根节点下的所有子节点NodeList students rootElement.getChildNodes();String classPath;for (int i 0; i students.getLength(); i) {// 由于节点多种类型而一般我们需要处理的是元素节点Node childNode students.item(i);// 元素节点就是非空的子节点也就是还有孩子的子节点if (childNode.getNodeType() Node.ELEMENT_NODE) {Element childElement (Element) childNode;//不是对象配置元素就忽略if (childElement.getNodeName() ! orderEntry) {continue;}//解析得到包名String name childElement.getAttribute(name);String oneJarPathPaths.get(basePath,name.jar).toString();if(classPath){classPathoneJarPath;}else{classPath;oneJarPath;}}}retStrclassPath javaName;return retStr;}catch (Exception ex) {System.out.println(standprofilepath ex.getMessage());ex.printStackTrace();}return ;}/*** 将文本写入文件** param filePath 文件全路径* param text 文本**/public static void WriteText2File(String filePath, String text) {// 创建文件File file new File(filePath);if (!file.exists()) {try {// 创建文件父级目录File parentFile file.getParentFile();if (!parentFile.exists()) {parentFile.mkdirs();}// 创建文件file.createNewFile();}catch (IOException e) {e.printStackTrace();}}// 将文本写入文件WriteText2File(file, text);}/*** 将文本写入文件** param file 文件对象* param text 文本**/public static void WriteText2File(File file, String text) {BufferedWriter writer null;try {FileOutputStream writerStream new FileOutputStream(file);writer new BufferedWriter(new OutputStreamWriter(writerStream, UTF-8));writer.write(text);writer.flush();}catch (IOException e) {e.printStackTrace();}finally {if (writer ! null) {try {writer.close();} catch (IOException e) {e.printStackTrace();}}}}}
然后实现目录Java监控调用编译
import java.io.*;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;//监控文件
public class FileListener extends FileAlterationListenerAdaptor {//启动Overridepublic void onStart(FileAlterationObserver observer) {super.onStart(observer);}//新建目录Overridepublic void onDirectoryCreate(File directory){}//目录修改Overridepublic void onDirectoryChange(File directory){}//目录删除Overridepublic void onDirectoryDelete(File directory){}//创建文件Overridepublic void onFileCreate(File file) {String compressedPath file.getAbsolutePath();if(compressedPath.contains(AutoBuildTmp)){return;}if (file.canRead()) {String confStr compressedPath.replace(MainInit.BllJavaBasePath, ).replace(\\, /).split(\\.)[0];MainMiddleware.GetObjectByConfString(confStr,null,,compressedPath);}}//修改文件Overridepublic void onFileChange(File file) {String compressedPath file.getAbsolutePath();if(compressedPath.contains(AutoBuildTmp)){return;}String confStr compressedPath.replace(MainInit.BllJavaBasePath, ).replace(\\, /).split(\\.)[0];MainMiddleware.GetObjectByConfString(confStr,null,,compressedPath);}//删除文件Overridepublic void onFileDelete(File file) {}//停止Overridepublic void onStop(FileAlterationObserver observer) {super.onStop(observer);}
}
文件侦听器
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.HiddenFileFilter;import java.io.File;//监控文件
public class FileMonitor {//监视器private FileAlterationMonitor monitor;//构造函数public FileMonitor(long interval){monitor new FileAlterationMonitor(interval);}/*** 给文件添加监听** param path 文件路径* param listener 文件监听器*/public void monitor(String path, FileAlterationListener listener) {IOFileFilter directories FileFilterUtils.and(FileFilterUtils.directoryFileFilter(),HiddenFileFilter.VISIBLE);IOFileFilter files FileFilterUtils.and(FileFilterUtils.fileFileFilter(),FileFilterUtils.suffixFileFilter(.java));IOFileFilter filter FileFilterUtils.or(directories, files);FileAlterationObserver observer new FileAlterationObserver(new File(path),filter);monitor.addObserver(observer);observer.addListener(listener);}//停止public void stop() throws Exception {monitor.stop();}//启动public void start() throws Exception {monitor.start();}
}主初始化实现java脚本监控
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
import java.nio.file.*;
import java.io.*;public class MainInit {//是否已经执行了初始化private static boolean HasInitfalse;//网站根地址private static String webBasePath;//业务脚本根地址public static String BllJavaBasePath;//执行初始化public static void TryInit(String basePath) {//只初始化一次if (HasInit true) {return;}HasInit true;webBasePath basePath;File fiBasenew File(basePath);String parentPathfiBase.getParent();File fiParentnew File(parentPath);String codeBasePathbasePath;//开发环境if(fiParent.getName().equals(artifacts)){//到out一级File fiParent1new File(fiParent.getParent());//到WebUI一级File fiParent2new File(fiParent1.getParent());codeBasePathPaths.get(fiParent2.toString(),web).toString()File.separator;}//用容器的配置xml初始化容器LIS.Core.Context.ObjectContainer.InitIoc(basePath);try{BllJavaBasePathcodeBasePath;System.out.println(监控目录:codeBasePath);FileMonitor fileMonitor new FileMonitor(5000);fileMonitor.monitor(codeBasePath, new FileListener());fileMonitor.start();}catch (Exception ex) {ex.printStackTrace();}}
}
主中间件调整
import appcode.IBaseHttpHandler;import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.concurrent.ConcurrentHashMap;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;import java.util.*;javax.servlet.annotation.WebServlet(name MianMiddleware)
public class MainMiddleware extends javax.servlet.http.HttpServlet {/// summary/// 缓存路径和类型允许多线程读一个线程写/// /summaryprivate static ConcurrentHashMapString, Class hsType new ConcurrentHashMap();///网站根地址public static String WebBasePath;///执行post请求Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//得到网站根路径if(WebBasePath){WebBasePath getServletContext().getRealPath(/);}//尝试执行初始化主逻辑MainInit.TryInit(WebBasePath);response.setContentType(text/html);request.setCharacterEncoding(UTF-8);response.setCharacterEncoding(UTF-8);String urlrequest.getRequestURI();//解析得到类名String className url.split(\\.)[0];PrintWriter writer response.getWriter();//取第一部分if (className.charAt(0) /) {className className.substring(1);}int indexclassName.indexOf(/);classNameclassName.substring(index1);//反射得到类型Object objDeal GetObjectByConfString(className,writer,WebBasePath,);//转换处理接口if(objDeal!null){//转换成接口appcode.IBaseHttpHandler baseDeal(appcode.IBaseHttpHandler)objDeal;baseDeal.ProcessRequest(request,response);}else{Write(writer,未找到名称为:className的处理类);}}/// summary/// 通过配置得当对象/// /summary/// param nameconfStr配置UI/login/ashx/AshDemo/param/// param namewriter输出/param/// param namebasePathWeb根/param/// param nameisBuild是否是编译/param/// returns/returnspublic static Object GetObjectByConfString(String confStr,PrintWriter writer,String basePath,String javaBllClsPath) {try {//根if(basePath){basePathWebBasePath;}System.out.println(confStr:confStr);//不包含类型或者要强行编译就进行编译if (!hsType.containsKey(confStr)||javaBllClsPath!) {String [] nameArrconfStr.split(/);String classFullName ;//类代码全路径String classCodePath basePath;for (int i 0; i nameArr.length; i){//类代码文件全名classCodePath Paths.get(classCodePath, nameArr[i]).toString();//类带命名空间的全名if(classFullName!){classFullName . nameArr[i];}else{classFullName nameArr[i];}}//类代码地址后面实现用脚本编译用classCodePath classCodePath .java;if(javaBllClsPath!){classCodePathjavaBllClsPath;}String standardPathPaths.get(basePath,Conf,StandAshxProj.iml).toString();//编译返回String buildRetappcode.AutoBuild.Build(basePath,classCodePath,classFullName,standardPath);System.out.println(buildRet:buildRet);//编译的jar名字String clsJarPath Paths.get(basePath, BinAshx, classFullName .jar).toString();System.out.println(加载jar包:clsJarPath);//自己生成jar包路径URL url new File(clsJarPath).toURI().toURL();URL[] urls new URL[]{url};//加载程序集这里很重要一定要指定父加载器否则加载的类和父加载器的类不认为是一个类URLClassLoader loader new URLClassLoader(urls, MainMiddleware.class.getClassLoader());//加载类Class c loader.loadClass(classFullName);//先写死后面执行编译和从jar包反射hsType.put(confStr, c);}Class c hsType.get(confStr);//创建对象Object o c.newInstance();return o;}catch (Exception ex) {ex.printStackTrace();}return null;}//get直接走post的逻辑Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doPost(request,response);}///输出数据到前台private static void Write(PrintWriter writer,String str){writer.println(str);writer.flush();writer.close();}} 自动编译的临时目录结构
自动生成的jar包 在idea里面改业务脚本代码后用浏览器访问就能立即生效简单高效适用于服务型系统。整个涉及到目录文件监控、驱动javac和jar打包、反射重复加载类、文件读写等。