Mvc进阶(下)

Mvc进阶(下)

  • 1.前言
  • 2.上次代码弊端
    • 1.利用xml建模反射优化
      • 1.XMl文件
      • 2.对xml建模
    • 3.修改中央控制器
  • 3.再优化
    • 1.先优化Action子控制器
    • 4.优化传值问题
  • 4.总结

Mvc进阶(下)_第1张图片

1.前言

虽然前面文章深入解析Java自定义MVC框架的原理与实现讲述了Mvc框架,但是那只能算是比较低级的,还能够再优化,接下来我会再优化3次代码,让代码更为简洁,通用。

2.上次代码弊端

虽然简化了代码,但是代码并不 能够通用,MVC这种东西,最终是要打包成jar架包的,可是上一篇文章的代码优化并不能够打包成架包,现在开始第一次优化。

1.利用xml建模反射优化

1.XMl文件


DOCTYPE config
[ELEMENT config (action*)>

<!ELEMENT action (forward*)>
<!ATTLIST action 
path CDATA #REQUIRED

type CDATA #IMPLIED
>

]
>



	
	
	
<config>
	
	<action path="/book" type="com.niyin.com.BookAction">
		<forward name="list" path="/res.jsp" redirect="true" />
		<forward name="tolist" path="/res.jsp" redirect="false" />
	action>
	
	<action path="/order" type="com.niyin.com.Orderaction">
		<forward name="success" path="/index.jsp" redirect="true" />
		<forward name="failed" path="/register.jsp" redirect="false" />
	action>
	
	<action path="/bookAction" type="test.BookAction">
		<forward name="add" path="/bookAdd.jsp" redirect="true" />
		<forward name="del" path="/reg.jsp" redirect="false" />
		<forward name="list" path="/list.jsp" redirect="false" />
		<forward name="upd" path="/login.jsp" redirect="false" />
	action>
	
	<action path="/loginAction" type="test.action.LoginAction">
		<forward name="a" path="/index.jsp" redirect="false" />
		<forward name="b" path="/welcome.jsp" redirect="true" />
	action>
config>




2.对xml建模

package model;

import java.util.HashMap;
import java.util.Map;

public class ActionModel {
	private String path;
	private String type;
	private Map<String ,ForwardModel>fmp=new HashMap<String ,ForwardModel>();
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	
	public void push(ForwardModel forwardModel) {
		fmp.put(forwardModel.getName(), forwardModel);
		  
	}
	public  ForwardModel pop(String name) {
		
		
		return fmp.get(name);
		
	}
	

}

package model;

import java.util.HashMap;
import java.util.Map;

public class ConfigModel {
private Map<String,ActionModel>aMap=new HashMap<String,ActionModel>();



public void push(ActionModel actionModel) {
	
	aMap.put(actionModel.getPath(), actionModel);

}
public ActionModel pop(String path) {
	
	return aMap.get(path);
	
}
public static void main(String[] args) throws Exception {
	ConfigModel configModel =new ConfigMOdelFactory().build();
	ActionModel actionModel=configModel.pop("/loginAction");
	
	ForwardModel forwardModel =actionModel.pop("b");
	System.out.println(forwardModel.getPath());
}

}

package model;

import java.io.InputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ConfigMOdelFactory {

	public static ConfigModel build() throws Exception {
		ConfigModel configModel = new ConfigModel();

		InputStream in = ConfigMOdelFactory.class.getResourceAsStream("/config.xml");
		SAXReader sr = new SAXReader();
		Document doc = sr.read(in);
		List<Element> actionsEles = doc.selectNodes("/config/action");
		for (Element element : actionsEles) {
			// System.out.println(element.asXML());

			ActionModel actionmodel = new ActionModel();
			actionmodel.setPath(element.attributeValue("path"));
			actionmodel.setType(element.attributeValue("type"));

			List<Element> forwardEles = element.selectNodes("forward");
			for (Element forwardEle : forwardEles) {

				// System.out.println(forwardEle.asXML());
				ForwardModel forwardModel = new ForwardModel();
				forwardModel.setName(forwardEle.attributeValue("name"));
				forwardModel.setPath(forwardEle.attributeValue("path"));
				forwardModel.setRedirect(!"false".equals(forwardEle.attributeValue("redirect")));
				actionmodel.push(forwardModel);
			}
			configModel.push(actionmodel);
		}
		return configModel;

	}

	public static void main(String[] args) throws Exception {
		ConfigMOdelFactory.build();
	}
}

package model;

import java.util.HashMap;
import java.util.Map;

public class ForwardModel {

	private String name;
	private String path;
	private boolean redirect;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	public boolean isRedirect() {
		return redirect;
	}
	public void setRedirect(boolean redirect) {
		this.redirect = redirect;
	}
	
	
}

3.修改中央控制器

以前把所有的子控制器放到map集合中,现在所有的子控制器再config。xml中。

package com.niyin.framework;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import com.niyin.com.BookAction;
import com.niyin.com.Orderaction;

import model.ActionModel;
import model.ConfigMOdelFactory;
import model.ConfigModel;
import model.ForwardModel;

@WebServlet("*.action")
public class DispatherServlet extends HttpServlet {
	
	private ConfigModel configMOdel;
//	public Map actionMap=new HashMap();
	
		
		
	@Override
	public void init() throws ServletException {
//	actionMap.put("/book", new BookAction());
//	actionMap.put("/order", new Orderaction());
//	actionMap.put("/cat", new CatAction());
		try {
			configMOdel=ConfigMOdelFactory.build();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	String uri = request.getRequestURI();	
			
	uri=uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf("."));
//	Action action = actionMap.get(uri);
//	要通过uri=book/再configMOdel中找
	ActionModel actionModel = configMOdel.pop(uri);
	if (actionModel==null)
		throw new RuntimeException("action 没有配置");
	
 String type = actionModel.getType();
		Action action;
		try {
			action = (Action) Class.forName(type).newInstance();
			

		
	
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 

	
	
	
	}

}

把map集合取消,改为用模型的方式来代替map集合,如果要新增类的话只需要新增模型对象即可,不用再加入map集合中,让代码更易于维护和修改,也可以封装架包提供了可行性。

代码测试


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title heretitle>
head>
<body>
<p>版本1p>
<a href="Bookservletadd">增加a>
<a href="Bookservletupd">修改a>
<a href="Bookservletdel">减少a>
<a href="Bookservletlist">查询a>


<p>版本2p>
<a href="Bookservletadd?methodName=add">增加a>
<a href="Bookservletupd?methodName=upd">修改a>
<a href="Bookservletdel?methodName=del">减少a>
<a href="Bookservletlist?methodName=list">查询a>
<p>版本3p>
<a href="Bookservletadd?methodName=add">增加a>
<a href="Bookservletupd?methodName=upd">修改a>
<a href="Bookservletdel?methodName=del">减少a>
<a href="Bookservletlist?methodName=list">查询a>
<p>版本4p>
<a href="book.action?methodName=add">增加a>
<a href="book.action?methodName=upd">修改a>
<a href="book.action?methodName=del">减少a>
<a href="book.action?methodName=list">查询a>

版本4的弊端:中央控制器的action容器加载,不可以灵活配置

<p>版本五p>
<a href="order.action?methodName=add">增加a>
<a href="order.action?methodName=upd">修改a>
<a href="order.action?methodName=del">减少a>
<a href="order.action?methodName=list">查询a>
body>
html>

Mvc进阶(下)_第2张图片
控制台输出
Mvc进阶(下)_第3张图片

3.再优化

虽然上面代码优化后可以灵活配置了,但是使用重定向和转发有问题,查询必然转发,增删改使用重定向,如果频繁刷新页面,可能会出现重复提交数据。

1.先优化Action子控制器

package com.niyin.framework;

import java.io.IOException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Action {
	protected String excute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String methoed = request.getParameter("methodName");
//	private
		String res="";
		try {
			Method m = this.getClass().getDeclaredMethod(methoed, HttpServletRequest.class,HttpServletResponse.class);
			m.setAccessible(true);
			res=(String) m.invoke(this, request,response);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}	
}

把book里面的类型也改为String,并返回tolist,和list,通过返回值来判断它是需要重定向还是转发,并且还节约了代码。

package com.niyin.com;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.niyin.entity.Book;
import com.niyin.framework.Action;
import com.niyin.framework.ModelDrivern;

public class BookAction extends Action implements ModelDrivern<Book> {
private Book book=new Book();

	private String list(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("list");
//		response.sendRedirect("res.jsp");
		request.setAttribute("content", "你就会");
//		request.getRequestDispatcher("res.jsp").forward(request, response);
	return "list";
	}
	private String del(HttpServletRequest request, HttpServletResponse response) throws Exception {
	// TODO Auto-generated method stub
	System.out.println("del");
//	response.sendRedirect("res.jsp");
	request.setAttribute("content", "你就会");
	return "tolist";


}

private String upd(HttpServletRequest request, HttpServletResponse response) throws Exception {
	// TODO Auto-generated method stub
	System.out.println("upd");
//	response.sendRedirect("res.jsp");

	request.setAttribute("content", "你就会");
	return "tolist";

}

private String add(HttpServletRequest request, HttpServletResponse response) throws IOException {
	// TODO Auto-generated method stub
	System.out.println("add");
//	response.sendRedirect("res.jsp");
	request.setAttribute("content", "你就会");

	return "tolist";

}
@Override
public Book getModel() {
	System.out.println(book);
	
	return book;
}

}

优化中央控制器,通过模型对象获取·forward对象来判断该重定向还是转发。

package com.niyin.framework;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import com.niyin.com.BookAction;
import com.niyin.com.Orderaction;

import model.ActionModel;
import model.ConfigMOdelFactory;
import model.ConfigModel;
import model.ForwardModel;

@WebServlet("*.action")
public class DispatherServlet extends HttpServlet {
	
	private ConfigModel configMOdel;
//	public Map actionMap=new HashMap();
	
		
		
	@Override
	public void init() throws ServletException {
//	actionMap.put("/book", new BookAction());
//	actionMap.put("/order", new Orderaction());
//	actionMap.put("/cat", new CatAction());
		try {
			configMOdel=ConfigMOdelFactory.build();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	String uri = request.getRequestURI();	
			
	uri=uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf("."));
//	Action action = actionMap.get(uri);
//	要通过uri=book/再configMOdel中找
	ActionModel actionModel = configMOdel.pop(uri);
	
	      String res= action.excute(request, response);
	      
ForwardModel forwardModel = actionModel.pop(res);
	if (forwardModel!=null) {

		boolean redirect = forwardModel.isRedirect();
		String path = forwardModel.getPath();
	if (redirect) {
		response.sendRedirect(request.getContextPath()+path);
	}else {
		request.getRequestDispatcher(path).forward(request, response);
	}
	} 
		
	
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 

	
	
	
	}

}

运行结果
Mvc进阶(下)_第4张图片
结果是一样的说明优化成功。

4.优化传值问题

一般来说通过servlet拿到前端的值再把它传入数据库,这个过程要写很多重复代码,现在来优化一下,利用反射等等
1.先定义一个模型驱动接口

package com.niyin.framework;

/**
 * 
 * @author 匿瘾
 *
 * @param 
 * 模型驱动接口
 */
public interface ModelDrivern<T> {
T getModel();
	
	
}

2.让bookaction实现这个接口

package com.niyin.com;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.niyin.entity.Book;
import com.niyin.framework.Action;
import com.niyin.framework.ModelDrivern;

public class BookAction extends Action implements ModelDrivern<Book> {
private Book book=new Book();

	private String list(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("list");
//		response.sendRedirect("res.jsp");
		request.setAttribute("content", "你就会");
//		request.getRequestDispatcher("res.jsp").forward(request, response);
	return "list";
	}
	private String del(HttpServletRequest request, HttpServletResponse response) throws Exception {
	// TODO Auto-generated method stub
	System.out.println("del");
//	response.sendRedirect("res.jsp");
	request.setAttribute("content", "你就会");
	return "tolist";


}

private String upd(HttpServletRequest request, HttpServletResponse response) throws Exception {
	// TODO Auto-generated method stub
	System.out.println("upd");
//	response.sendRedirect("res.jsp");

	request.setAttribute("content", "你就会");
	return "tolist";

}

private String add(HttpServletRequest request, HttpServletResponse response) throws IOException {
	// TODO Auto-generated method stub
	System.out.println("add");
//	response.sendRedirect("res.jsp");
	request.setAttribute("content", "你就会");

	return "tolist";

}
@Override
public Book getModel() {
	System.out.println(book);
	
	return book;
}

}

3.优化中央控制器

在控制器内判断有没有实现接口,如果实现了就把值传进去。

package com.niyin.framework;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import com.niyin.com.BookAction;
import com.niyin.com.Orderaction;

import model.ActionModel;
import model.ConfigMOdelFactory;
import model.ConfigModel;
import model.ForwardModel;

@WebServlet("*.action")
public class DispatherServlet extends HttpServlet {
	
	private ConfigModel configMOdel;
//	public Map actionMap=new HashMap();
	
		
		
	@Override
	public void init() throws ServletException {
//	actionMap.put("/book", new BookAction());
//	actionMap.put("/order", new Orderaction());
//	actionMap.put("/cat", new CatAction());
		try {
			configMOdel=ConfigMOdelFactory.build();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	String uri = request.getRequestURI();	
			
	uri=uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf("."));
//	Action action = actionMap.get(uri);
//	要通过uri=book/再configMOdel中找
	ActionModel actionModel = configMOdel.pop(uri);
	if (actionModel==null)
		throw new RuntimeException("action 没有配置");
	
 String type = actionModel.getType();
		Action action;
		try {
			action = (Action) Class.forName(type).newInstance();
			
//			bookaction 有没有实现这个接口
			if (action instanceof ModelDrivern) {
				ModelDrivern md=(ModelDrivern) action;
				Object bean = md.getModel();
				Map<String, String[]> map = request.getParameterMap();
				BeanUtils.populate(bean, map);
//				把值封进去
				
			}
	      String res= action.excute(request, response);
	      
ForwardModel forwardModel = actionModel.pop(res);
	if (forwardModel!=null) {

		boolean redirect = forwardModel.isRedirect();
		String path = forwardModel.getPath();
	if (redirect) {
		response.sendRedirect(request.getContextPath()+path);
	}else {
		request.getRequestDispatcher(path).forward(request, response);
	}
	} 
		
	
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 

	
	
	
	}

}

最后通过degbug查看book里面是否有值判断是否成功的,传入了值。
结果:
Mvc进阶(下)_第5张图片
可以看到book里面是有值的,所以最后一个优化也成功了。

4.总结

通过建模xml和反射的方式优化代码,让代码以Mvc框架的形式出现,
MVC框架构思巧妙。让代码更为简洁。

你可能感兴趣的:(mvc)