正文
经过前面几次反射机制的学习,这次用反射的知识写一个类似于Struts框架处理机制的小demo。
Servlet 和 Sturts
在引入反射知识前,先简单介绍下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之间的映射关系。
<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所示。
<?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
我想写的小demo就是利用读取xml,利用反射加载不同的action,进行业务逻辑处理,最后输出返回的视图,整个逻辑思路还是比较简单,纯当反射学习的练手。
首先是定义配置类,把xml中action对应的映射关系保存下来
private class ActionConfig {
private String name;
private String className;
private Map<String, String> viewResult = new HashMap<>();
当初始化读取xml完毕后,得到如下结构,action的名字对应着具体的action配置
Map<String, ActionConfig> actionConfigMap = new HashMap<>();
模拟Struts ActionServlet的运作方式
public View runAction(String actionName, Map<String, String> params) {
String className = cfg.getClassName(actionName);
if