通过前面几回反射机制的学习,此次用反射的知识写一个相似于Struts框架处理机制的小demo。html
在引入反射知识前,先简单介绍下Sturts框架和Servlet。
在没有一些Web框架以前,当咱们要写Java Web应用使用的就是Servlet。一个简单的Servletdemo就是以下所示。前端
public class HelloWorld extends HttpServlet { private String message; public void init() throws ServletException { message = "Hello World"; } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<h1>" + message + "</h1>"); } public void destroy() { } }
servlet会提供出来doGet和doPost,同时接收用户传入的参数,进行业务处理,再返回视图。那么Servlet如何与URL对应起来呢,答案就是在web.xml,绑定servlet和url之间的映射关系。java
<servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>HelloWorld</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorld</servlet-name> <url-pattern>/HelloWorld</url-pattern> </servlet-mapping>
映射、业务逻辑处理、视图返回所有在servlet中完成,耦合度比较高,随着url的增多,servlet会愈来愈多,须要在web.xml配置不少映射关系,不利于维护。同时servlet的入参以及返回的参数很依赖于当前运行的容器,自己也是线程不安全的,当入参很是多时,须要屡次调用getParm方法,代码很冗余。
以后Struts框架诞生,经过统一的ActionServlet处理具体的url请求和参数映射以及根据不一样的返回结果跳转不一样的视图,开发者只须要关心本身的业务逻辑,就能够实现web应用的开发。具体的Struts的配置文件,大体以下面XML所示。web
<?xml version="1.0" encoding="UTF-8"?> <struts> <action name="login" class="com.coderising.kailuncen.LoginAction"> <result name="success">/jsp/homepage.jsp</result> <result name="fail">/jsp/showLogin.jsp</result> </action> <action name="logout" class="com.coderising.kailuncen.LogoutAction"> <result name="success">/jsp/welcome.jsp</result> <result name="error">/jsp/error.jsp</result> </action> </struts>
咱们只须要分别实现视图和业务逻辑,再经过struts将他们绑定起来,就能够完成开发工做,也更便于理解,方便维护。有兴趣的读者能够自行深刻学习下servlet和struts的思想。后端
我想写的小demo就是利用读取xml,利用反射加载不一样的action,进行业务逻辑处理,最后输出返回的视图,整个逻辑思路仍是比较简单,纯当反射学习的练手。
首先是定义配置类,把xml中action对应的映射关系保存下来安全
private class ActionConfig { private String name; private String className; private Map<String, String> viewResult = new HashMap<>();
当初始化读取xml完毕后,获得以下结构,action的名字对应着具体的action配置app
Map<String, ActionConfig> actionConfigMap = new HashMap<>();
模拟Struts ActionServlet的运做方式框架
public View runAction(String actionName, Map<String, String> params) { String className = cfg.getClassName(actionName); if (className == null) { return null; } try { Class<?> clz = Class.forName(className); Object action = clz.newInstance(); ReflectionUtil.invokeSetMethods(action, params); String resultName = (String) clz.getDeclaredMethod("execute").invoke(action); Map<String, Object> result = ReflectionUtil.invokeGetMethods(action); String resultView = cfg.getViewResult(actionName, resultName); return new View(resultView, result);
经过actionName从配置类中拿到具体的执行类的全类名,其实Struts框架就是直接解析url,而后对应到xml配置的对应action名称,将url和具体的执行类绑定在一块儿。
以后是使用Class.forName建立类类型,而后建立对应的实例。ReflectionUtil里面作的事情就是,先获取action中对应的field的Name,而后从变量中,根据filed名称找对应的值,而后使用set方法对action的field进行赋值操做,就是LoginAction中的相关信息。jsp
public class LoginAction { private String name; private String password; private String message;
这一步就省去了使用servlet时,重复去get赋值的繁琐操做,利用反射机制,直接对成员变量进行赋值,开发者只须要将前端会传入的参数名称和后端类中的名称作好事先的确认便可。
而后就是经过反射调用execute方法,使用了Method.invoke方法。再次使用反射获取field的最新值,组成map返回,同时根据方法的返回值,去actionConfigMap中获取对应的view。
最后根据field的返回值map和view的名称组成最终展现的视图。学习
以上其实就是根据反射知识模仿的struts核心运行流程的小demo,整个web框架处理了很是多的其余的事情好比参数映射,安全,Json处理等,若是有兴趣,能够进一步作学习。