All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
link.jfire.mvc.core.EasyMvcDispathServlet Maven / Gradle / Ivy
package link.jfire.mvc.core;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import link.jfire.baseutil.collection.set.LightSet;
import link.jfire.baseutil.order.AescComparator;
import link.jfire.baseutil.reflect.ReflectUtil;
import link.jfire.baseutil.simplelog.ConsoleLogFactory;
import link.jfire.baseutil.simplelog.Logger;
import link.jfire.baseutil.verify.Verify;
import link.jfire.core.JfireContext;
import link.jfire.core.JfireContextImpl;
import link.jfire.core.bean.Bean;
import link.jfire.mvc.annotation.ActionClass;
import link.jfire.mvc.annotation.ActionMethod;
import link.jfire.mvc.config.MvcStaticConfig;
import link.jfire.mvc.interceptor.ActionInterceptor;
import link.jfire.mvc.interceptor.impl.DataBinderInterceptor;
import link.jfire.mvc.interceptor.impl.UploadInterceptor;
import link.jfire.mvc.util.ActionFactory;
import link.jfire.mvc.util.BeetlRender;
import link.jfire.mvc.util.HotwrapClassLoader;
import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.resource.WebAppResourceLoader;
/**
* 充当路径分发器的类,用来根据地址规则转发数据请求
*
* @author 林斌([email protected] )
*
*/
@WebServlet(name = "EasyMvcDispathServlet", value = "/*", loadOnStartup = 1, asyncSupported = true)
@MultipartConfig
public class EasyMvcDispathServlet extends HttpServlet
{
/**
*
*/
private static final long serialVersionUID = 6091581255799463902L;
private Logger logger = ConsoleLogFactory.getLogger();
private JfireContext jfireContext;
private ActionCenter actionCenter;
private String contextUrl;
private ActionInterceptor[] interceptors;
private ServletContext servletContext;
private RequestDispatcher staticResourceDispatcher;
private BeetlRender render;
private File configFile;
private File monitorFile;
private String[] reloadPackages;
private WatchService watcher;
private boolean devMode = false;
@Override
public void init(ServletConfig servletConfig) throws ServletException
{
logger.info("初始化Context-mvc Servlet");
servletContext = servletConfig.getServletContext();
staticResourceDispatcher = getStaticResourceDispatcher();
contextUrl = servletContext.getContextPath();
try
{
configFile = new File(this.getClass().getClassLoader().getResource("mvc.json").toURI());
}
catch (Exception e)
{
throw new RuntimeException("解析配置文件异常", e);
}
if (servletConfig.getInitParameter("debug") != null && servletConfig.getInitParameter("debug").equals("true"))
{
logger.warn("以debug模式启动服务器");
devMode = true;
String monitorPath = servletConfig.getInitParameter("monitorPath");
reloadPackages = servletConfig.getInitParameter("reloadPackages").split(",");
monitorFile = new File(monitorPath);
initWatcher(monitorFile);
}
jfireContext = new JfireContextImpl();
initMvc();
}
/**
* 初始化mvc需要的所有的类和实例
*/
private void initMvc()
{
jfireContext.readConfig(configFile);
jfireContext.addSingletonEntity("servletContext", servletContext);
addDefaultInterceptors();
initTemplate();
initInterceptor();
actionCenter = new ActionCenter(initUrlActionMap(render, contextUrl).toArray(new Action[0]));
}
private RequestDispatcher getStaticResourceDispatcher()
{
RequestDispatcher requestDispatcher = null;
if ((requestDispatcher = servletContext.getNamedDispatcher(MvcStaticConfig.COMMON_DEFAULT_SERVLET_NAME)) != null)
{
}
else if ((requestDispatcher = servletContext.getNamedDispatcher(MvcStaticConfig.RESIN_DEFAULT_SERVLET_NAME)) != null)
{
}
else if ((requestDispatcher = servletContext.getNamedDispatcher(MvcStaticConfig.WEBLOGIC_DEFAULT_SERVLET_NAME)) != null)
{
}
else if ((requestDispatcher = servletContext.getNamedDispatcher(MvcStaticConfig.WEBSPHERE_DEFAULT_SERVLET_NAME)) != null)
{
}
else
{
throw new RuntimeException("找不到默认用来处理静态资源的处理器");
}
return requestDispatcher;
}
private void addDefaultInterceptors()
{
jfireContext.addBean(DataBinderInterceptor.class);
jfireContext.addBean(UploadInterceptor.class);
}
/**
* 初始化Beancontext容器,并且抽取其中的ActionClass注解的类,将action实例化
*/
private List initUrlActionMap(BeetlRender render, String contextUrl)
{
Bean[] beans = jfireContext.getBeanByAnnotation(ActionClass.class);
Bean[] listenerBeans = jfireContext.getBeanByInterface(ActionInitListener.class);
LightSet tmp = new LightSet<>();
for (Bean each : listenerBeans)
{
tmp.add((ActionInitListener) each.getInstance());
}
ActionInitListener[] listeners = tmp.toArray(ActionInitListener.class);
List list = new ArrayList<>();
for (Bean each : beans)
{
list.addAll(initAction(each, listeners, render, contextUrl));
}
return list;
}
private List initAction(Bean bean, ActionInitListener[] listeners, BeetlRender render, String contextUrl)
{
Class> src = bean.getOriginType();
ActionClass actionClass = src.getAnnotation(ActionClass.class);
String modelUrl = null;
if (actionClass.value().equals("/"))
{
modelUrl = contextUrl;
}
else
{
modelUrl = actionClass.value().equals("") ? '/' + src.getSimpleName() : '/' + actionClass.value();
modelUrl = contextUrl + modelUrl;
}
Verify.False(modelUrl.contains("*"), "顶级url不能包含*");
// 这里需要使用原始的类来得到方法,因为如果使用增强后的子类,就无法得到正确的方法名称以及方法上的注解信息
Method[] methods = ReflectUtil.getAllMehtods(bean.getOriginType());
List list = new ArrayList<>();
for (Method each : methods)
{
if (each.isAnnotationPresent(ActionMethod.class))
{
Action action = ActionFactory.buildAction(each, modelUrl, bean, render, bean.getType());
list.add(action);
for (ActionInitListener listener : listeners)
{
listener.init(action);
}
}
}
return list;
}
public void initInterceptor()
{
Bean[] beans = jfireContext.getBeanByInterface(ActionInterceptor.class);
interceptors = new ActionInterceptor[beans.length];
for (int i = 0; i < beans.length; i++)
{
interceptors[i] = (ActionInterceptor) beans[i].getInstance();
}
Arrays.sort(interceptors, new AescComparator());
}
private void initTemplate()
{
initBeetlTemplate();
}
private void initBeetlTemplate()
{
WebAppResourceLoader loader = new WebAppResourceLoader();
Configuration configuration = null;
try
{
configuration = Configuration.defaultConfiguration();
}
catch (IOException e)
{
e.printStackTrace();
}
render = new BeetlRender(new GroupTemplate(loader, configuration));
jfireContext.addSingletonEntity(render.getClass().getName(), render);
}
private void initWatcher(File monitorDir)
{
Set dirs = new HashSet<>();
getChildDirs(monitorDir, dirs);
Set paths = new HashSet<>();
for (File each : dirs)
{
paths.add(Paths.get(each.getAbsolutePath()));
}
try
{
watcher = FileSystems.getDefault().newWatchService();
for (Path each : paths)
{
each.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
private void getChildDirs(File parentDir, Set dirSets)
{
dirSets.add(parentDir);
for (File each : parentDir.listFiles())
{
if (each.isDirectory())
{
getChildDirs(each, dirSets);
}
}
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
if (devMode)
{
while (true)
{
WatchKey key = watcher.poll();
if (key == null)
{
break;
}
for (WatchEvent> event : key.pollEvents())
{
Kind> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW)
{// 事件可能lost or discarded
continue;
}
try
{
long t0 = System.currentTimeMillis();
ClassLoader classLoader = new HotwrapClassLoader(monitorFile, reloadPackages);
jfireContext = (JfireContext) classLoader.loadClass("link.jfire.core.JfireContextImpl").newInstance();
jfireContext.addSingletonEntity(ClassLoader.class.getSimpleName(), classLoader);
jfireContext.setClassLoader(classLoader);
initMvc();
logger.debug("热部署,耗时:{}", System.currentTimeMillis() - t0);
if (!key.reset())
{
break;
}
break;
}
catch (InstantiationException | IllegalAccessException | ClassNotFoundException e)
{
throw new RuntimeException(e);
}
}
}
}
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
request.setCharacterEncoding(MvcStaticConfig.encode);
response.setCharacterEncoding(MvcStaticConfig.encode);
Action action = actionCenter.getAction(request);
if (action == null)
{
staticResourceDispatcher.forward(request, response);
return;
}
try
{
for (ActionInterceptor each : interceptors)
{
if (each.interceptor(request, response, action) == false)
{
logger.debug("发生异常{}" + each.getClass().getName());
return;
}
}
response.setContentType(action.getContentType());
Object result = action.invoke((Object[]) request.getAttribute(DataBinderInterceptor.DATABINDERKEY));
action.getView().render(request, response, result);
}
catch (Throwable e)
{
logger.error("访问action出现异常,action为{}", action.getRequestUrl(), e);
response.sendError(500, e.getLocalizedMessage());
}
}
}