首页 > 代码库 > Struts2 自定义MVC框架
Struts2 自定义MVC框架
一、Model1与Model2:
Model1:就是一种纯jsp开发技术,将业务逻辑代码和视图渲染代码杂糅在一起。
Model2:Model2是在Model1的基础上,将业务逻辑的代码分离开来,单独形成一个Servlet,Model2也是基于MVC开发
二、MVC设计模式:
由3个部分组成,各部分作用如下:
Model:模型,主要用于数据和业务的处理
View:视图,用于数据的显示
Controller:控制器,用于进行流程控制
MVC设计模式的特点:
①一个模型可以对应多个视图
②显示与逻辑控制的分离
③分层控制,减轻了代码间的耦合
自定义MVC框架只需dom4j.jar包即可!
三、准备XML文档Framework.xml
注意点:
<!-- ELEMENT 表示元素 -->
<!-- ATTLIST 表示属性 -->
<!-- CDATA 表示字符串类型 -->
<!-- REQUIRED 表示此属性必须的写 -->
<!-- *代表多个 -->
<!-- IMPLIED 表示此属性可写 -->
<!DOCTYPE Framework[ <!ELEMENT Framework (actions)> <!ELEMENT actions (action*)> <!ELEMENT action (result*)> <!ATTLIST action name CDATA #REQUIRED class CDATA #REQUIRED > <!ATTLIST RESULT name CDATA #IMPLIED redirect (true|false) "false" > ]> <Framework> <actions> <action name="loginAction" class="cn.happy.action.LoginAction"> <result name="success">success.jsp</result> <result name="login">index.jsp</result> </action> </actions> </Framework>
四、定义自己的Action接口,用于存放结果集和要执行的方法
public interface Action { //定义两个静态字符串常量(逻辑视图名) public static final String SUCCESS="success"; public static final String LOGIN="login"; //定义一个抽象方法execute public String execute(HttpServletRequest request,HttpServletResponse response)throws Exception; }
五、定义ActionMapping类用于存放Action节点,即一个ActionMapping类可以视为配置文件中的一个action节点
public class ActionMapping { //根据action节点中的属性 以及action节点中的<result></result>节点定义三个私有属性 private String name;//action的名称 private String classname;//action对应程序中的类 private Map<String,String> results=new HashMap<String,String>(); //向results集合中添加数据的方法 public void addResult(String name,String value){ results.put(name, value); } //根据名称获取的方法 public String getResults(String name){ return results.get(name); } public Map<String, String> getResults() { return results; } public void setResults(Map<String, String> results) { this.results = results; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClassname() { return classname; } public void setClassname(String classname) { this.classname = classname; }
六、定义ActionMappingManager类用于管理ActionMapping,并通过dom4j解析Framework.xml配置文件。从而获取根节点,以及actions节点,并通过for循环遍历actions节点下的action节点拿到name和class的属性值,由于一个action节点下有多个result节点 及遍历action下所有的result节点,分别存入到actionMapping中的双列集合中,最后得到所有action节点的集合
public class ActionMappingManager { //actionMapping类的集合 private Map<String,ActionMapping> maps=new HashMap<String,ActionMapping>(); public ActionMapping getActionMapping(String name){ return maps.get(name); } //解析src下所有配置文件 public ActionMappingManager(String[]files){ for (String filename : files) { init(filename); } } //创建初始化方法,使用dom4j解析配置文件 public void init(String path){ try { //getResourceAsStream取得该资源输入流的引用保证程序可以从正确的位置抽取数据 InputStream is=this.getClass().getResourceAsStream("/"+path); //解析XML Document doc=new SAXReader().read(is); //获取根节点 Element root = doc.getRootElement(); //获取actions节点 Element actions =(Element)root.elementIterator("actions").next(); //使用for循环来 //遍历actions节点下的所有action节点 for (Iterator<Element> action=actions.elementIterator("action");action.hasNext();) { //获取到action节点 Element actionnext = action.next(); //分别获取到action节点中的name属性和class属性 String name=actionnext.attributeValue("name"); String classname=actionnext.attributeValue("class"); //将以上两个属性保存到ActionMapping类中 ActionMapping mapp=new ActionMapping(); mapp.setClassname(classname); mapp.setName(name); //由于一个action节点下有多个result节点 遍历action下所有的result节点 for (Iterator<Element> result=actionnext.elementIterator("result");result.hasNext();){ //获取到result节点 Element resultnext = result.next(); //提取result节点的name属性值和result节点中的值 String resultname= resultnext.attributeValue("name"); String resultvalue= http://www.mamicode.com/resultnext.getText();>
七、使用反射机制根据字符串类型的类名获取到具体的类--ActionManager
public class ActionManager { public static Action getActionClass(String classname){ Class clazz=null; Action action=null; //获取当前线程的加载类 try { clazz=Thread.currentThread().getContextClassLoader().loadClass(classname); } catch (ClassNotFoundException e) { e.printStackTrace(); } if(clazz==null){ try { //如果该线程中没有,那么使用class.forname方法获取 clazz=Class.forName(classname); } catch (ClassNotFoundException e) { e.printStackTrace(); } } if(action==null){ //将获取到的类型转换为action,调用无参构造函数,某种程度上相当于new,不过new需要指定类型 try { action =(Action)clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return action; }
八、定义Servlet类,详情见注释!注意点在web.xml中添加 <load-on-startup>节点,让程序一开始就初始化servlet
public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } ActionMappingManager man=null; public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取到ActionMapping对象 ActionMapping actionMapping=man.getActionMapping(getname(request)); //获取action接口利用反射机制 Action action = ActionManager.getActionClass(actionMapping.getClassname()); try { String message=action.execute(request, response); String results=actionMapping.getResults(message); response.sendRedirect(results); } catch (Exception e) { e.printStackTrace(); } } //获取请求路径名 public String getname(HttpServletRequest request) { //项目+请求地址 String requestURI =request.getRequestURI(); //项目名称 String contextPath=request.getContextPath(); //具体的请求 String path=requestURI.substring(contextPath.length()); String filename=path.substring(1,path.lastIndexOf(".")).trim(); return filename; } //重写servlet的init方法,让程序一开始就初始化servlet //由于一个项目src根目录下有可能有多个配置文件,不止一个,所以逐个解析 @Override public void init(ServletConfig config) throws ServletException { //初始化参数信息 String filename = config.getInitParameter("config"); String [] filenames=null; if(filename==null){ //如果没有别的参数信息,就将已经配好的放入数组中 filenames=new String[]{"Framework.xml"}; } else{ //拆分配置文件名称字符串 filenames=filename.split(","); } //使用init方法初始化 man=new ActionMappingManager(filenames); }
九、业务逻辑Action并实现Action接口,并重写自定义的execute方法
public class LoginAction implements Action{ public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String name=request.getParameter("name"); String pwd=request.getParameter("pwd"); if(name.equals("1")&&pwd.equals("1")){ return SUCCESS; } else{ return LOGIN; } }
十、编写登录界面
<body> <form action="loginAction.action" method="post"> 姓名:<input type="text" name="name"/><br/> 密码:<input type="text" name="pwd"/><br/> <input type="submit" value="http://www.mamicode.com/登录"> </form> </body>
实现效果:
Struts2 自定义MVC框架