自己动手实现IOC和MVC(七)

12 篇文章 0 订阅

相信大家都用过struts或者spring mvc这样的mvc框架,先来介绍一下mvc吧,

MVC是三个单词的缩写,分别为: 模型(Model),视图(View)和控制Controller)。 MVC模式的目的就是实现Web系统的职能分工。 Model层实现系统中的业务逻辑,通常可以用JavaBean或EJB来实现。 View层用于与用户的交互,通常用JSP来实现。 Controller层是Model与View之间沟通的桥梁,它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。

mvc带来的好处 ,google一下一大箩筐,这里就不说了。

其实没个mvc底层的实现就是一个大的servlet ,来拦截我们得请求 ,分发到不同处理操作,然后跳转到相应的视图,当然这些都可配置的,mvc这个project我们也会机遇java annotation的方式来实现的

我们知道spring 通过java annotation就可以注释一个类为action ,在方法上添加上一个java annotation 就可以配置请求的路径了 ,那么我们得实现也参考这个过程来完成我们要做的事情

①定义请求路径的java annotation

RequestMapping.java

package com.ajunframework.servlet.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 
 * @author ajun
 * @http://blog.csdn.net/ajun_studio
 */
@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
@Inherited  
public @interface RequestMapping {

	public String value() default "";
}
此时请求的路径 ,我们可以做一个解析 ,然后找到你的action类中方法上的注释和你解析出来的路径一致,说名就是这个方法,接着我们利用java反射机制调用这个类得方法,就可以了,接着这个方法会返回一个路径,就是我们跳转的视图返回给我们总的servlet ,就行跳转。

这些功能改怎么实现呢?

首先考虑你返回的视图的路径,其中还有包含的数据怎么办呢?还有就是服务器端跳转还是客户端跳转呢?

此时我们要定义一个视图类,对这些操作属性进行封装,其中包括条状的路径 、展现到页面的数据(这里只是做request范围内的)、跳转方式。

下面是视图类得封装代码:

package com.ajunframework.servlet.view;

import com.ajunframework.servlet.constant.DispatchActionConstant;

/**
 * @author ajun
 * @http://blog.csdn.net/ajun_studio  
 **/
public class View {

	private String url;//跳转路径
	
	private String dispathAction = DispatchActionConstant.FORWARD;//跳转方式
	

	public View(String url) {
		this.url = url;
	}
	
	public View(String url,String name,Object value) {
		this.url = url;
		ViewData view = new ViewData();
		view.put(name, value);
	}
	
	
	public View(String url,String name,String dispathAction ,Object value) {
		this.dispathAction = dispathAction;
		this.url = url;
		ViewData view = new ViewData();//请看后面的代码
		view.put(name, value);
	}
	
	
	public String getUrl() {
		return url;
	}
	
	
	public void setUrl(String url) {
		this.url = url;
	}

	public String getDispathAction() {
		return dispathAction;
	}

	public void setDispathAction(String dispathAction) {
		this.dispathAction = dispathAction;
	}

	
}
request范围的数据存储类ViewData.java

package com.ajunframework.servlet.view;

import javax.servlet.http.HttpServletRequest;

import com.ajunframework.servlet.WebContext;
/**
 * @author ajun
 * @http://blog.csdn.net/ajun_studio  
 **/
public class ViewData {
	
	private HttpServletRequest request;
	
	
	public ViewData() {
		initRequestAndResponse();
	}

	private void initRequestAndResponse(){
		this.request = WebContext.requestHodler.get();//下面会介绍
	}
	
	public void put(String name,Object value){
		this.request.setAttribute(name, value);
	}
	
	
}
还有就是我们在每次请求的时候,到达action里的时候 我们会用ViewData.put()往request中存数据,而action中并没有request的情况如何处理呢?

下面我提供一个在进入action之前进行初始化request的类WebContext.java

package com.ajunframework.servlet;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
 * @author ajun
 * @http://blog.csdn.net/ajun_studio  
 **/
public class WebContext {

	public static ThreadLocal<HttpServletRequest> requestHodler = new ThreadLocal<HttpServletRequest>();
   
	public HttpServletRequest getRequest(){
           return requestHodler.get();
    }
   
	public HttpSession getSession(){
           return requestHodler.get().getSession();
    }
   
	public ServletContext getServletContext(){
           return requestHodler.get().getSession().getServletContext();
    }
}

通过这个类 ,你可以当前请求的request或者session相关请求类的实例变量,线程间互不干扰的,因为用到了ThreadLocal这个类。

下面来介绍一下servlet的实现,这是无论是get post请求都会调用我封转的方法 ,这个方法,会根据你请求的url,找到你对象的action ,然后调用其中方法注释和改url配置的方法,同事返回View视图类,接着根据View中的路径,返回到相应的视图。

为了方便这里我用到了我们写的ioc,用于在servlet初始化的过程中,实例化和注入相关的class,供我们调用。这里耦合在一起了 ,不是很好。。。

DispatchServlet.java

package com.ajunframework.servlet;

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

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

import com.ajunframework.beans.applicationContext.AnnotationClassPathApplicationContext;
import com.ajunframework.beans.factory.AnnotationBeanFactory;
import com.ajunframework.beans.factory.RequestMapingMap;
import com.ajunframework.beans.utils.BeanUtils;
import com.ajunframework.servlet.annotation.RequestMapping;
import com.ajunframework.servlet.constant.DispatchActionConstant;
import com.ajunframework.servlet.view.View;
/**
 * @author ajun
 * @http://blog.csdn.net/ajun_studio  
 **/
public class DispatchServlet extends HttpServlet {
	private static final long serialVersionUID = 5325307163972641802L;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		/*String configPth=config.getInitParameter("configFile");
		InputStream in =config.getServletContext().getResourceAsStream(configPth);
		Properties p = new Properties();
		try {
			p.load(in);
		} catch (IOException e) {
			e.printStackTrace();
		} */
		AnnotationClassPathApplicationContext.getAnnotationClassPathApplicationContext().init();//初始化bean
	}


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

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.excute(request, response);
	}
	
	private void excute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		
		WebContext.requestHodler.set(request);//初始化当前请求的request
		String lasturl = pareRequestURI(request);//person/list,解析url
		String className = RequestMapingMap.getRequesetMap().get(lasturl);
		Object actionClass = AnnotationBeanFactory.getBeanFactory().getBean(className);
		Method [] methods = BeanUtils.findDeclaredMethods(actionClass.getClass());
		Method method = null;
		for(Method m:methods){//循环方法,找匹配的方法进行执行
			if(m.isAnnotationPresent(RequestMapping.class)){
				String anoPath = m.getAnnotation(RequestMapping.class).value();
				if(anoPath!=null && !"".equals(anoPath.trim()) && lasturl.equals(anoPath.trim())){
					method = m;
					break;
				}
			}
		}
		try {
			if(method!=null){
				View view = (View)method.invoke(actionClass, request,response);//执行action的方法
				if(view.getDispathAction().equals(DispatchActionConstant.FORWARD)){//不同的跳转方式
					request.getRequestDispatcher(view.getUrl()).forward(request, response);
				}else if(view.getDispathAction().equals(DispatchActionConstant.REDIRECT)){
					response.sendRedirect(view.getUrl());
				}else{
					request.getRequestDispatcher(view.getUrl()).forward(request, response);
				}
				
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		
	}
	
	private String pareRequestURI(HttpServletRequest request){
		String path = request.getContextPath()+"/";// /ajun
		String requestUri = request.getRequestURI();// ajun/person/list.ajun
		String midUrl = requestUri.replaceFirst(path, "");
		String lasturl = midUrl.substring(0, midUrl.lastIndexOf("."));//person/list
		return lasturl;
	}

}


web.xml对这个servlet的配置

<?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>DispatchServlet</servlet-name>
    <servlet-class>com.ajunframework.servlet.DispatchServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>DispatchServlet</servlet-name>
    <url-pattern>*.ajun</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>


这里还用到了一个跳转方式的常量类介绍给大家DispatchActionConstant.java

package com.ajunframework.servlet;

/**
 * 跳转常量
 * @author ajun
 *
 */
public class DispatchActionConstant {

	public static String FORWARD = "forward";//服务器跳转
	
	public static String REDIRECT = "redirect";//客户端跳转
}

现在这个简单的mvc已经实现了,下一节做个测试。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飓风zj

感谢打赏,thanks

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值