`

MVC框架原理(简单模拟)

    博客分类:
  • JAVA
阅读更多
一个简单的MVC框架

1、ActionMap,action name与action object之间的映射

public class ActionMap {

private Map<String, Object> actionMap = new HashMap<String, Object>();

public Object getAction(String actionName){
return actionMap.get(actionName);
}

public void initFromProperties(Configuration conf) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
System.out.println("Init actionMap from Properties " + conf.getFileName() + " ...");
Set<Entry<Object, Object>> keyValues = conf.entrySet();
for(Entry<Object, Object> keyValue : keyValues){
this.actionMap.put(keyValue.getKey().toString(), Class.forName(keyValue.getValue().toString()).newInstance());

}
System.out.println("Init actionMap success, Total size " + this.actionMap.size());
}
}

2、NormalUrl是用来解析url中的Servlet path中的action name与method name的(本来还有一个RestfulUrl的,但又不想在这里实现),约定为 http://www.unclepeng.com:XXXX/appName/actionName/methodName/...
public class NormalUrl { 

public static final String  DEFAULT_METHOD_NAME = "index"; 

private String actionName; 

private String methodName; 

private int level = 2; 

public String getActionName() { 
return actionName; 
} 

public String getMethodName() { 
return methodName; 
} 

public static NormalUrl fromServletPath(String str){ 
if(str.startsWith("/")){ 
str = str.substring(1); 
} 
String[] strs = StringUtils.split(str, '/', true); 
NormalUrl url = new NormalUrl(); 
if(strs == null || strs.length == 0){ 
throw new IllegalArgumentException(String.format("Illegal Servlet path %s", str)); 
} 
url.actionName = StringUtils.split(strs[0], '.', true)[0]; 
if(strs.length > 1){ 
url.methodName = StringUtils.split(strs[1], '.', true)[0]; 
}else{ 
url.methodName = DEFAULT_METHOD_NAME; 
url.level = 1; 
} 
return url; 
} 

public int getLevel() { 
return level; 
} 

public void setLevel(int level) { 
this.level = level; 
} 
} 
[、code]
3、核心DispatcherServlet,在init的时候初始化actionMap,在doGet方法中根据servlet path解析出对应的actionName与methodName,再找到对应的Action Object,然后invoke method 
public class DispatcherServlet extends HttpServlet { 

private static final long serialVersionUID = - 8330920476525405610L; 

    public static final String INCLUDE_PATH_INFO = 
        "javax.servlet.include.path_info"; 

public DispatcherServlet() { 
super(); 
} 

private ActionMap actionMap = new ActionMap(); 

public static int FILE_NOT_FOUND = 404; 

public void destroy() { 
super.destroy(); 
this.actionMap = null; 
} 

public void doGet(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException { 
//Split URL 
String path = request.getServletPath(); 

NormalUrl url = NormalUrl.fromServletPath(path); 
String actionName = url.getActionName(); 
String methodName = url.getMethodName(); 

//Get action by name, if not found, response 404 
Object action = this.actionMap.getAction(actionName); 
if(action == null){//action not found 
System.err.println(String.format("Action named '%s' not found", actionName)); 
response.sendError(FILE_NOT_FOUND); 
} 

//Invoke action method, and forward if invoke result not returns null 
try{ 
Method method = action.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); 
Object o = method.invoke(action, new Object[]{request, response}); 
if(o!= null){ 
if(url.getLevel() == 2){ 
request.getRequestDispatcher("../" + (String)o).forward(request, response); 
}else{ 
request.getRequestDispatcher((String)o).forward(request, response); 
} 
return; 
} 
}catch(Exception e){ 
e.printStackTrace(); 
response.sendError(FILE_NOT_FOUND); 
return; 
} 
} 

public void doPut(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException { 
doGet(request, response); 
} 

public void doDelete(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException { 
doGet(request, response); 
} 

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

public void init() throws ServletException { 
        ServletConfig servletConfig = this.getServletConfig();          
        String mvcConfigFilePath = servletConfig.getInitParameter("mvc_config");  
        Configuration conf = null; 
        if(mvcConfigFilePath != null){//case 1, use properites configuration 
        try { 
conf = new PropertiesConfiguration(mvcConfigFilePath); 
actionMap.initFromProperties(conf); 
return; 
} catch (Exception e) { 
e.printStackTrace(); 
System.exit(1); 
} 
        }else{//case 2, use packages setting 
        String realPath = this.getServletContext().getRealPath("/"); 
        String packagesPath = servletConfig.getInitParameter("action_packages"); 
        String[] packagePathArray = StringUtils.split(packagesPath, ',', true); 
        for(String packagePath : packagePathArray){ 
        
        } 
        } 
} 

} 

4、web.xml配置
<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.5" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 
<servlet>   
    <servlet-name>Dispatcher</servlet-name>   
    <servlet-class>com.upeng.webcommons.mvc.DispatcherServlet</servlet-class>   
    <init-param>   
        <param-name>mvc_config</param-name>   
        <param-value>mvc.properties</param-value>   
    </init-param>   
  </servlet>   
  <servlet-mapping>   
    <servlet-name>Dispatcher</servlet-name>   
    <url-pattern>*.do</url-pattern>   
  </servlet-mapping> 
</web-app> 

5、示例Action
public class ProductAction { 

public String index(HttpServletRequest request, HttpServletResponse response){ 
return "product.jsp"; 
} 
} 


6、mvc.properties配置
product =com.upeng.webcommons.test.ProductAction 

7、Test
http://localhost:222/webcommons/product/index.do 或者 http://localhost:222/webcommons/product.do,其中的product为action名,index为action中的方法名,当没指定方法时,默认选择action中的index方法

总结与选型过程:
1、本来想实现基于类的MVC,类似struts2,然后把对应的url parameter注入到action的field中,这样做好处是能跟servletAPI完全解耦,坏处是为每次请求以反射的方式生成一个临时的action object,效率上要打些折扣。

2、也想过实现类似mvc.net 1.0中的把action实现成sigton,然后实现基于方法的MVC把对应的url parameter注入到方法的参数里然后回调,这样做要求action中不能有重名的方法,另外在查找方法的时候要做一次遍历,稍微比直接指定method name跟parameterTypes式的查找慢了那么一点。
但是还需要把string型的url parameters转型为方法参数对应的类型效率上又打了一点点的折扣。综合考虑下便又打消了这个念头

3、这还只是一个MVC雏形,初步实现了url到action乃到action中的method之间的mapping,当然,也可以添加对参数检验,错误处理、国际化等的支持。
分享到:
评论

相关推荐

    用servlet模拟struts_mvc框架

    然而,为了理解MVC框架的基本工作原理,我们可以使用Servlet来模拟Struts的行为。 首先,我们要知道MVC的三个核心组件: 1. **Model(模型)**:负责业务逻辑处理和数据操作。在实际项目中,这通常由JavaBean或EJB...

    写你自己的MVC框架

    本教程将引导你如何创建自己的MVC框架。 **一、模型(Model)** 模型是MVC框架的核心部分,负责处理业务逻辑和数据操作。在自定义MVC框架中,你需要设计一个抽象的`Model`类或接口,作为所有业务模型的基础。模型...

    asp.net3.5 MVC框架

    ### ASP.NET 3.5 MVC框架知识点解析 #### 一、概述 ASP.NET MVC 是一种用于构建动态网站的开源框架,它遵循模型-视图-控制器(Model-View-Controller, MVC)架构模式。该模式将业务逻辑与表示层分离,从而提高开发...

    ASP.NET MVC 5 框架揭秘源码.rar

    ASP.NET MVC 5框架是微软推出的用于构建动态、数据驱动的Web应用程序的开源框架,它基于Model-View-Controller(MVC)设计模式。在这个框架中,开发人员可以清晰地分离业务逻辑、用户界面和数据处理,从而实现更加...

    简单模拟Sping MVC

    这个简单的模拟项目旨在帮助开发者深入理解Spring MVC的工作原理,通过使用Java注解来实现核心功能。以下是对Spring MVC核心概念及模拟实现的详细解释。 1. **模型(Model)**:在Spring MVC中,模型通常由Java对象...

    ASP.NET+MVC5++框架揭秘

    这个框架结合了ASP.NET的强大力量和MVC(Model-View-Controller)设计模式的优势,为开发者提供了丰富的工具集,使得创建复杂的Web应用变得更为简单。本文将深入探讨ASP.NET MVC5的关键特性、工作原理以及如何利用C#...

    简单自定义框架-帮助你理解SSH框架的原理

    1. **Struts**:作为MVC框架,Struts负责处理HTTP请求,调度控制器,以及视图渲染。在自定义框架中,你可以模仿Struts的动作调度和拦截器机制。 2. **Spring**:Spring提供依赖注入和AOP,是整个系统的核心。在我们...

    ASP.NET MVC 2.0 简单实例(无数据库,一看就懂)

    ASP.NET MVC 2.0 是一个用于构建动态网站的开源框架,它基于Model-View-Controller(MVC)设计模式,由微软开发...通过这个“无数据库”的实例,你可以专注于MVC框架的基础概念,从而为后续的复杂项目打下坚实的基础。

    MVC3项目增删改查的简单示例

    总之,这个MVC3项目的增删改查示例涵盖了Web开发的基本流程,它帮助初学者理解MVC框架的工作原理,熟悉数据库操作,以及如何构建动态网页。通过实际动手操作,学习者可以迅速提升自己的技能,为进一步的Web开发奠定...

    springboot MVC简单demo

    SpringBoot MVC简单Demo详解 SpringBoot是Spring框架的一个简化版,它旨在简化Spring应用程序的初始搭建...通过学习和实践这个简单的Demo,你可以进一步深入理解SpringBoot MVC的工作原理,从而更高效地开发Web应用。

    spring mvc 参数绑定漏洞

    此外,开发者还应关注Spring的安全更新,及时升级Spring MVC框架以修补已知的安全漏洞。通过结合代码审查、单元测试和安全扫描工具,可以在开发过程中尽早发现并修复潜在的参数绑定漏洞。 对于学习和排查此类问题,...

    基于spring-MVC的在线测试系统(客观题)

    该在线测试系统是一个使用Spring-MVC框架构建的简单示例,旨在模拟实际的在线考试环境,尤其是处理客观题型。Spring-MVC是Spring框架的一部分,它提供了模型-视图-控制器(MVC)的设计模式,使得开发人员能够更有效...

    javaWeb SSM框架简易登录

    总的来说,SSM框架的简易登录功能涵盖了前端请求处理、后端业务逻辑、数据库交互以及测试等多个方面,对新手来说,这是一个很好的实践项目,能够帮助他们理解JavaWeb开发的基本流程和SSM框架的协同工作原理。...

    MVC Contrib实例源码

    **MVC Contrib** 是一个针对ASP.NET MVC框架的开源扩展库,它提供了许多额外的功能和工具,以增强ASP.NET MVC的开发体验。这个压缩包包含了MVC Contrib项目的实例源码和相关组件,对于理解MVC Contrib的工作原理以及...

    Automa o Web realizada无站点Todo MVC utilizando o框架Cypress.zip

    【标题】"Automa o Web realizada无站点Todo MVC utilizando o框架Cypress.zip" 提供了一个关于使用Cypress框架进行Web自动化测试的项目,重点在于实现一个无服务器(serverless)的Todo MVC应用。Todo MVC是一种...

    自定义Ajax框架,struts框架的模拟,特效代码

    然后,模拟Struts框架的目的是为了理解和学习其工作原理,或者在特定场景下替代它。Struts框架的关键组件包括: 1. **Action**:业务逻辑的入口点,负责处理用户的请求。 2. **ActionForm**:用于收集和验证表单...

    servlet模拟struts1工作原理

    总之,模拟Struts1的过程是一个很好的学习方式,它帮助开发者理解MVC模式和框架如何协调工作,同时也能提升对Servlet的理解。实际开发中,虽然Struts1已经被Struts2和其他现代框架取代,但了解其工作原理对理解和...

    Spring 2.0 MVC的应用

    Spring 2.0 MVC框架是Java Web开发中的一个重要里程碑,它极大地简化了企业级应用程序的构建,特别是对于处理HTTP请求和响应的Web层。在这个"FirstSpringWebApp"项目中,我们将深入探讨Spring MVC的核心概念和它在...

Global site tag (gtag.js) - Google Analytics