一个简单的mvc实现
程序员文章站
2022-07-01 10:55:55
...
从一本书上看到一个mvc的简单实现,有点像struts2,大家分享一下
1、核心一个FrontController拦截所有请求,web.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>FrontController</servlet-name>
<servlet-class>am.core.FrontController</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/classes/am-config.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FrontController</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
FrontController:
package am.core;
import java.io.IOException;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import am.common.Const;
import am.util.ConfigXMLParser;
public class FrontController extends HttpServlet {
private static final Log log=LogFactory.getLog(ConfigXMLParser.class);
/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occure
*/
public void init() throws ServletException {
ServletContext context=this.getServletContext();
String config_file=this.getServletConfig().getInitParameter("config");
String dispatcher_name=this.getServletConfig().getInitParameter("dispatcher");
if(config_file==null||config_file.equals(""))
config_file="/WEB-INF/classes/am-config.xml";
if(dispatcher_name==null||dispatcher_name.equals(""))
dispatcher_name=Const.DEFAULT_DISPATCHER;
try{
Map<String,ActionModel> resources=ConfigXMLParser.newInstance().parse(config_file,context);
System.out.println(resources);
context.setAttribute(Const.ACTIONS_ATTR, resources);
log.info("初始化配置文件成功");
}catch(Exception e){
log.error("初始化配置文件失败");
e.printStackTrace();
}
try{
Class c=Class.forName(dispatcher_name);
Dispatcher dispatcher=(Dispatcher)c.newInstance();
context.setAttribute(Const.DISPATCHER_ATTR, dispatcher);
log.info("初始化Dispatcher成功");
}catch(Exception e){
log.error("初始化Dispatcher失败");
e.printStackTrace();
}
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.process(request, response);
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.process(request, response);
}
protected void process(HttpServletRequest request,
HttpServletResponse response)throws ServletException,IOException{
ServletContext context=this.getServletContext();
String reqURL=request.getRequestURL().toString();
int i=reqURL.lastIndexOf(".");
String contextPath=request.getContextPath();
int j=reqURL.indexOf(contextPath);
String path=reqURL.substring(contextPath.length()+j,i);
request.setAttribute(Const.REQUEST_ATTR, path);
Dispatcher dispatcher=(Dispatcher)context.getAttribute(Const.DISPATCHER_ATTR);
String nextPage=dispatcher.getNextUrl(request, response, context);
RequestDispatcher forwarder=request.getRequestDispatcher("/"+nextPage);
forwarder.forward(request,response);
}
}
am-config.xml为配置文件,结构如下:
<?xml version="1.0" encoding="UTF-8"?>
<actions>
<action path="/login" class="am.action.LoginAction">
<forward name="success" url="hello.jsp"/>
<forward name="error" url="login.jsp"/>
</action>
</actions>
FrontController拦截所有请求,根据请求URL解析出path,根据path由Dispatcher执行具体action,返回nextpage。
ActionDispatcher如下:
package am.core;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import am.common.Const;
public class ActionDispatcher implements Dispatcher {
private ServletContext context;
private static final Log log=LogFactory.getLog(ActionDispatcher.class);
public String getNextUrl(HttpServletRequest request,
HttpServletResponse response, ServletContext context) {
setServletContext(context);
Map<String,ActionModel> actions=
(Map<String,ActionModel>)context.getAttribute(Const.ACTIONS_ATTR);
String reqPath=(String)request.getAttribute(Const.REQUEST_ATTR);
ActionModel actionModel=actions.get(reqPath);
String forward_name="";
ActionForward actionForward;
try{
Class c=Class.forName(actionModel.getClassName());
Action action=(Action)c.newInstance();
if(ValuesSetter.setValues(request, action)){
forward_name=action.execute(request, response, context);
}else{
forward_name=Action.ERROR;
}
}catch(Exception e){
log.error("can not find action"+actionModel.getClassName());
}
actionForward=actionModel.getForwards().get(forward_name);
if(actionForward==null){
log.error("can not find page for forward "+forward_name);
return null;
}else{
return actionForward.getViewUrl();
}
}
public void setServletContext(ServletContext context) {
// TODO Auto-generated method stub
this.context = context;
}
}
实现原理和struts差不多,有助于我们理解struts,具体代码可见附件。