Java : JDK 1.8 IDE : IDEA 2019 构建工具 : Gradle
image
image
image
public class TomcatServer { private Tomcat tomcat; private String[] args; public TomcatServer(String[] args) { this.args = args; } public void startServer() throws LifecycleException { // instantiated Tomcat tomcat = new Tomcat(); tomcat.setPort(6699); tomcat.start(); Context context = new StandardContext(); context.setPath(""); context.addLifecycleListener(new Tomcat.FixContextListener()); // register Servlet DispatcherServlet dispatcherServlet = new DispatcherServlet(); Tomcat.addServlet(context, "dispatcherServlet", dispatcherServlet).setAsyncSupported(true); context.addServletMappingDecoded("/", "dispatcherServlet"); tomcat.getHost().addChild(context); Thread awaitThread = new Thread(() -> TomcatServer.this.tomcat.getServer().await(), "tomcat_await_thread"); awaitThread.setDaemon(false); awaitThread.start(); } }
@Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { try { MappingHandler mappingHandler = HandlerManager.getMappingHandlerByURI(((HttpServletRequest) req).getRequestURI()); if (mappingHandler.handle(req, res)) { return; } } catch (IllegalAccessException | InstantiationException | InvocationTargetException | ClassNotFoundException e) { e.printStackTrace(); } }
public class MappingHandler { private String uri; private Method method; private Class<?> controller; private String[] args; public MappingHandler(String uri, Method method, Class<?> controller, String[] args) { this.uri = uri; this.method = method; this.controller = controller; this.args = args; } }
public class HandlerManager { public static Map<String, MappingHandler> handleMap = new HashMap<>(); public static void resolveMappingHandler(List<Class<?>> classList) { for (Class<?> cls : classList) { if (cls.isAnnotationPresent(Controller.class)) { parseHandlerFromController(cls); } } } private static void parseHandlerFromController(Class<?> cls) { Method[] methods = cls.getDeclaredMethods(); for (Method method : methods) { if (!method.isAnnotationPresent(RequestMapping.class)) { continue; } String uri = method.getDeclaredAnnotation(RequestMapping.class).value(); List<String> paramNameList = new ArrayList<>(); for (Parameter parameter : method.getParameters()) { if (parameter.isAnnotationPresent(RequestParam.class)) { paramNameList.add(parameter.getDeclaredAnnotation(RequestParam.class).value()); } } String[] params = paramNameList.toArray(new String[paramNameList.size()]); MappingHandler mappingHandler = new MappingHandler(uri, method, cls, params); HandlerManager.handleMap.put(uri, mappingHandler); } } public static MappingHandler getMappingHandlerByURI(String uri) throws ClassNotFoundException { MappingHandler handler = handleMap.get(uri); if (null == handler) { throw new ClassNotFoundException("MappingHandler was not exist!"); } else { return handler; } } }
public boolean handle(ServletRequest req, ServletResponse res) throws IllegalAccessException, InstantiationException, InvocationTargetException, IOException { String requestUri = ((HttpServletRequest) req).getRequestURI(); if (!uri.equals(requestUri)) { return false; } // read parameters. Object[] parameters = new Object[args.length]; for (int i = 0; i < args.length; i++) { parameters[i] = req.getParameter(args[i]); } // instantiated Controller. Object ctl = BeanFactory.getBean(controller); // invoke method. Object response = method.invoke(ctl, parameters); res.getWriter().println(response.toString()); return true; }
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Controller { } @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface RequestMapping { String value(); } @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface RequestParam { String value(); }
public class ClassScanner { public static List<Class<?>> scanClasses(String packageName) throws IOException, ClassNotFoundException { List<Class<?>> classList = new ArrayList<>(); String path = packageName.replace(".", "/"); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Enumeration<URL> resources = classLoader.getResources(path); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); if (resource.getProtocol().contains("jar")) { // get Class from jar package. JarURLConnection jarURLConnection = (JarURLConnection) resource.openConnection(); String jarFilePath = jarURLConnection.getJarFile().getName(); classList.addAll(getClassesFromJar(jarFilePath, path)); } else { // todo other way. } } return classList; } private static List<Class<?>> getClassesFromJar(String jarFilePath, String path) throws IOException, ClassNotFoundException { List<Class<?>> classes = new ArrayList<>(); JarFile jarFile = new JarFile(jarFilePath); Enumeration<JarEntry> jarEntries = jarFile.entries(); while (jarEntries.hasMoreElements()) { JarEntry jarEntry = jarEntries.nextElement(); String entryName = jarEntry.getName(); if (entryName.startsWith(path) && entryName.endsWith(".class")) { String classFullName = entryName.replace("/", ".").substring(0, entryName.length() - 6); classes.add(Class.forName(classFullName)); } } return classes; } }
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Autowired { } @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Bean { }
public class BeanFactory { private static Map<Class<?>, Object> classToBean = new ConcurrentHashMap<>(); public static Object getBean(Class<?> cls) { return classToBean.get(cls); } public static void initBean(List<Class<?>> classList) throws Exception { List<Class<?>> toCreate = new ArrayList<>(classList); while (toCreate.size() != 0) { int remainSize = toCreate.size(); for (int i = 0; i < toCreate.size(); i++) { if (finishCreate(toCreate.get(i))) { toCreate.remove(i); } } if (toCreate.size() == remainSize) { throw new Exception("cycle dependency!"); } } } private static boolean finishCreate(Class<?> cls) throws IllegalAccessException, InstantiationException { if (!cls.isAnnotationPresent(Bean.class) && !cls.isAnnotationPresent(Controller.class)) { return true; } Object bean = cls.newInstance(); for (Field field : cls.getDeclaredFields()) { if (field.isAnnotationPresent(Autowired.class)) { Class<?> fieldType = field.getType(); Object reliantBean = BeanFactory.getBean(fieldType); if (null == reliantBean) { return false; } field.setAccessible(true); field.set(bean, reliantBean); } } classToBean.put(cls, bean); return true; } }
public class IlssApplication { public static void run(Class<?> cls, String[] args) { TomcatServer tomcatServer = new TomcatServer(args); try { tomcatServer.startServer(); List<Class<?>> classList = ClassScanner.scanClasses(cls.getPackage().getName()); BeanFactory.initBean(classList); HandlerManager.resolveMappingHandler(classList); } catch (Exception e) { e.printStackTrace(); } } }
jar { manifest { attributes "Main-Class": "io.ilss.framework.Application" } from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } }
@Bean public class NumberService { public Integer calNumber(Integer num) { return num; } }
@Controller public class TestController { @Autowired private NumberService numberService; @RequestMapping("/getNumber") public String getSalary(@RequestParam("name") String name, @RequestParam("num") String num) { return numberService.calNumber(11111) + name + num ; } }
public class Application { public static void main(String[] args) { IlssApplication.run(Application.class, args); } }
gradle clean install java -jar mvc-test/build/libs/mvc-test-1.0-SNAPSHOT.jar
http://localhost:6699/getNumber?name=aaa&num=123
image