表示层(视图层,显示层)
业务逻辑层
数据访问层(持久层)
是一种架构思想,其核心思想将项目划分成三种不同模块,分别是模型,视图,控制器
View : JSP 负责显示
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) //设置这个注解是给方法使用的
@Retention(RetentionPolicy.RUNTIME) //设置注解的存在时间为运行时
public @interface RequestMapping {
//设置传入的参数
public String value(); //设置一个参数 ,必须传入参数 如果添加 default "" ,那么默认的参数就是空字符串
//public String method() default "get"; //设置method参数,默认的是get方法
}
import java.lang.reflect.Method;
public class Handler{
private Method method; // 方法
private Object object; // Object对象,用于反射调用方法method
public Handler(Method method, Object object){
super();
this.method = method;
this.object = object;
}
public Method getMethod(){
return method;
}
public void setMethod(Method method){
this.method = method;
}
public Object getObject(){
return object;
}
public void setObject(Object object){
this.object = object;
}
@Override
public String toString(){
return "Handler [method=" + method + ", object=" + object + "]";
}
}
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean class="cn.controller.UserController"></bean> <bean class="cn.controller.DeptController"></bean> </beans>
解析config.xml的文件,使用的是Dom4j
在pom.xml中导入依赖
<!-- 读取xml文件的jar包 --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency>
解析xml文件的工具类
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import cn.reflect.ReflectDemo;
/**
* 读取XML文件的工具类
* @author chenjiabing
*
*/
public class XMLUtils{
/**
* 读取xml文件中的内容,使用的jar包是dom4j
* @return xml配置文件中的所有bean的对象
*/
public static List<Object> getBeans()throws Exception{
SAXReader reader=new SAXReader();
InputStream inputStream=ReflectDemo.class.getClassLoader().getResourceAsStream("config.xml"); //获取输入流
Document document=reader.read(inputStream);
//得到根节点
Element beansEle=document.getRootElement();
//得到根节点下面的所有子节点
List<Element> elements=beansEle.elements();
List<Object> beans=new ArrayList<Object>(); //保存bean中的class属性创建的对象
//遍历子节点
for (Element element : elements) {
//得到class属性的值
String className=element.attributeValue("class");
//直接使用遍历的className创建对象并且保存在集合中
Class cls=Class.forName(className);
Object bean=cls.newInstance();
beans.add(bean); //将创建的对象添加到集合中
}
return beans;
}
}
package cn.reflect;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import cn.annoation.RequestMapping;
public class HandlerMapping{
private Map<String, Handler> map = new HashMap<String, Handler>(); // 创建一个Map存储path和Handler
/**
* 初始化方法,将指定类的带有注解的方法放入Map中
* @param beans 对象集合
*/
public void init(List<Object> beans){
for (Object bean : beans) {
Class cls=bean.getClass();
//获取所有方法
Method[] methods=cls.getDeclaredMethods();
for (Method method : methods) {
RequestMapping requestMapping=method.getAnnotation(RequestMapping.class);
//如果方法上面存在RequestMapping注解
if (requestMapping!=null) {
String path=requestMapping.value(); //获取注解上的地址
Handler handler=new Handler(method, bean); //创建handler对象
map.put(path, handler); //存放键值对
}
}
}
}
/**
* 根据给定的path返回一个Handler对象
*
* @param path
* 指定的路径,map中的key
* @return Handler 对象
*/
public Handler getHandler(String path){
return map.get(path);
}
}
redirect:add.do
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ViewResolver{
/**
* 视图解析器
* @param returnValue controller方法的返回值
*/
public void process(Object returnValue, HttpServletRequest request,
HttpServletResponse response) {
String path=(String)returnValue;
try {
//判断是转发还是重定向
if (path.startsWith("redirect:")) { //重定向
response.sendRedirect(request.getContextPath()+"/"+path.split(":")[1]);
}else { //转发
request.getRequestDispatcher("/WEB-INF/"+path+".jsp").forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Scanner;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.reflect.Handler;
import cn.reflect.HandlerMapping;
import cn.reflect.ViewResolver;
import cn.utils.XMLUtils;
/**
* Servlet implementation class DispatcherServlet
*/
public class DispatcherServletextends HttpServlet{
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
List<Object> beans;
try {
beans = XMLUtils.getBeans();// 获取xml配置文件中所有bean的对象
HandlerMapping handlerMapping = new HandlerMapping();
String uri = request.getRequestURI(); // 请求地址
String appName = request.getContextPath(); // 工程名
String path = uri.replace(appName, ""); // 获取注解的path
handlerMapping.init(beans); // 初始化
Handler handler = handlerMapping.getHandler(path); // 获取指定的Handler
Method method = handler.getMethod();
Object object = handler.getObject();
Class[] paramTypes = method.getParameterTypes(); // 获取方法中的参数类型
Object returnValue=null; //申明目标方法的返回值
// 如果调用的方法有参数
if (paramTypes.length > 0) {
Object[] args = new Object[paramTypes.length]; //创建参数列表
for (int i = 0; i < args.length; i++) {
Class cls = paramTypes[i];
// 判断类型是request或者response
if (cls == HttpServletRequest.class) {
args[i] = request;
} else if (cls == HttpServletResponse.class) {
args[i] = response;
}
}
returnValue=method.invoke(object, args);
} else {
returnValue=method.invoke(handler.getObject()); // 调用方法执行
}
//有返回值,要么转发,要么重定向
if (returnValue!=null) {
//通过视图解析器对象,处理转发或者重定向
ViewResolver viewResolver=new ViewResolver();
viewResolver.process(returnValue,request,response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}