这篇文章卡了大概一周,一个是没时间,只能带娃加锻炼间隙挤点时间,一个是碰到了问题卡住了。本篇实现反射调用ashx实现类的基础结构。
首先申明ashx的接口,所有的ashx实现类继承实现该接口的基类
package appcode;
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;
//http执行请求接口
public interface IBaseHttpHandler {
/// <summary>
/// 执行请求
/// </summary>
/// <param name="request">请求对象</param>
/// <param name="response">响应对象</param>
public void ProcessRequest(HttpServletRequest request, HttpServletResponse response);
}
然后实现第一个不需要会话的基类
package appcode;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.lang.Class;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarFile;
import java.util.jar.JarEntry;
import LIS.Core.MultiPlatform.LISContext;
import appcode.IBaseHttpHandler;
//实现不带会话的请求基类
public class BaseHttpHandlerNoSession implements IBaseHttpHandler {
///请求对象
public HttpServletRequest Request=null;
///响应对象
HttpServletResponse Response=null;
///输出数据到前台
private void Write(PrintWriter writer,String str)
{
writer.println(str);
writer.flush();
writer.close();
}
/// <summary>
/// 执行请求
/// </summary>
/// <param name="request">请求对象</param>
/// <param name="response">响应对象</param>
public void ProcessRequest(HttpServletRequest request, HttpServletResponse response)
{
try {
Request = request;
Response = response;
//前台传入的要调用的方法
String method = LISContext.GetRequest(request, "Method");
if (method != "") {
//得到方法
Method m = this.getClass().getMethod(method);
if (m != null) {
//执行
Object ret = m.invoke(this);
PrintWriter writer = response.getWriter();
if (ret == null) {
Write(writer, "");
} else {
Write(writer, (String) ret);
}
} else {
//没有指定名称的方法
}
} else {
//没按要求传调用方法
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
然后实现主中间件中转调用实现的ashx
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.util.*;
@javax.servlet.annotation.WebServlet(name = "MianMiddleware")
public class MianMiddleware extends javax.servlet.http.HttpServlet {
/// <summary>
/// 缓存路径和类型,允许多线程读一个线程写
/// </summary>
private static ConcurrentHashMap<String, Class> hsType = new ConcurrentHashMap<>();
///执行post请求
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String url=request.getRequestURI();
//解析得到类名
String className = url.split("\\.")[0];
PrintWriter writer = response.getWriter();
//反射得到类型
Object objDeal = GetObjectByConfString(className,writer);
//转换处理接口
if(objDeal!=null)
{
//转换成接口
appcode.IBaseHttpHandler baseDeal=(appcode.IBaseHttpHandler)objDeal;
baseDeal.ProcessRequest(request,response);
}
else
{
Write(writer,"为找到名称为:"+className+"的处理类");
}
}
/// <summary>
/// 通过配置得当对象
/// </summary>
/// <param name="confStr">配置/UI/sys/ashx/ashCommonNoSession</param>
/// <returns></returns>
public static Object GetObjectByConfString(String confStr,PrintWriter writer) {
try {
//取第一部分
if (confStr.charAt(0) == '/') {
confStr = confStr.substring(1);
}
if (!hsType.containsKey(confStr)) {
URL urlBase = new File("D:\\Java业余\\jbase\\Lib\\appcode.jar").toURI().toURL();
//自己生成jar包路径
URL url = new File("D:\\Java业余\\jbase\\Lib\\AshDemo.jar").toURI().toURL();
URL[] urls = new URL[]{urlBase,url};
//加载程序集,这里很重要,一定要指定父加载器,否则加载的类和父加载器的类不认为是一个类
URLClassLoader loader = new URLClassLoader(urls, MianMiddleware.class.getClassLoader());
ClassLoader loader1=Thread.currentThread().getContextClassLoader();
//加载类
Class c = loader.loadClass("AshDemo.ashDemo");
//先写死,后面执行编译和从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的逻辑
@Override
protected 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();
}
}
然后实现一个ashx的demo
测试
本次碰到的卡壳问题就是通过URLClassLoader加载的类和创建的对象无法转换成接口类型。明明是一个类型,运行总是报错无法转换。各方资料查看加上自己尝试,发现要指定URLClassLoader类加载器的父加载器,这样父加载器加载的类就不会被重复加载导致类型不匹配了。
下个阶段就是实现文件变化监控和比对ashx实现类代码和jar包时间自动编译jar包供反射调用了。为下图的每个ashx的Java类生成jar包供反射使用而达到脚本化的目的,这样就可以实现业务脚本化和虚拟M层,用虚拟M来兼容打印和仪器接口等。
卡壳问题没人询问是真痛苦,卡过去了收获不少,有些事看着简单,动手做多多少少还是有些意外的