学生管理系统 项目总结

采用的MVC三层架构

 

知识点:

1.    框架(中央控制器)

作用:

注解:利用注解将每个Action类加上标注,访问时通过客户端发送的访问地址来判断要执行哪个Action 。这里需要用到控制器(一个Servlet,中央控制器),在web.xml文件中配置这个Servlet的范围,在客户端发送的地址中带.do的都栏截。

 

这个Servlet在应用启动时就启动,在init(servlet启动时)方法中 遍历应用下所有的带有指定注解的类。将类实例化后放入MAP中,MAP中的key为地址标注(在客户端发送的请求地址中获得),value就是对应的类。下次截获客户请求地址时,截取地址匹配这个MAP中的key 。 如果能找到,利用反射的方试执行指定的方法。方法的名称也是从客户端请求URL中请求参数中获得。

 

注意:当我们加载类时,需要加载类中父类和使用到的其它的类。定义一个类继承于ClassLoader, 将加载器转入,指定父加载器。然后写一个方法,方法内读取类文件成字节码,给内存。然后用ClassLoader的defineClass方法将内存的字节码转成一个Class对象

 

package com.itheima.framework;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

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

import com.itheima.bean.privilege.Employee;
import com.itheima.service.privilege.SecurityService;
import com.itheima.utils.ClassFactory;
import com.itheima.utils.WebUtils;

public class ControllerServlet extends HttpServlet {
	// 定义一个map,用于存放action与路径
	public static Map<String, Object> map = new HashMap<String, Object>();

	@Override
	public void init() throws ServletException {
		// 获取classes目录
		String classpath = this.getServletContext().getRealPath(
				"/WEB-INF/classes");
		File file = new File(classpath);
		scan(file);
	}

	private void scan(File file) {

		if (file.isFile()) {
			if (file.getName().endsWith("class")) {
				final String filepath = file.getPath();
				MyLoader myLoader = new MyLoader(
						ControllerServlet.class.getClassLoader());
				Class clazz = myLoader.myDefineClass(filepath);
				Control contrl = (Control) clazz.getAnnotation(Control.class);
				if (contrl != null) {
					Object action;
					try {
						action = clazz.newInstance();
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
					String uri = contrl.value();
					map.put(uri, action);
				}
			}
		} else {
			File[] files = file.listFiles();
			for (File f : files) {
				scan(f);
			}
		}
	}

	class MyLoader extends ClassLoader {
		public MyLoader(ClassLoader parent) {
			super(parent);
		}

		public Class myDefineClass(String filepath) {

			try {
				InputStream in = new FileInputStream(filepath);
				ByteArrayOutputStream bout = new ByteArrayOutputStream();

				byte[] buffer = new byte[1024];
				int len = -1;
				while ((len = in.read(buffer)) != -1) {
					bout.write(buffer, 0, len);
				}
				byte[] boutArr = bout.toByteArray();
				Class clazz = super.defineClass(null, boutArr, 0,
						boutArr.length);

				return clazz;
			} catch (FileNotFoundException e) {
				throw new RuntimeException("没有找到相对应的类文件");
			} catch (IOException e) {
				throw new RuntimeException("读取类文件时发生错误");
			}
		}
	}

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

		request.setCharacterEncoding("UTF-8");

		String uri = request.getRequestURI();
		uri = uri
				.substring(request.getContextPath().length(), uri.length() - 3);
		Object action = map.get(uri);
		String methodType = request.getParameter("method");

		Method method;
		try {
			method = action.getClass().getMethod(methodType,
					HttpServletRequest.class, HttpServletResponse.class);

		} catch (Exception e) {
			throw new RuntimeException("没有找到与之对应的方法");
		}

		try {

			Permission permission = method.getAnnotation(Permission.class);
			
			if (permission==null || checkPrivilege(permission, request)) {

				method.invoke(action, request, response);
			} else {

				request.setAttribute("message", "你没有权限访问该页面,请联系管理员");
				request.setAttribute("returnURL", request.getContextPath()
						+ "/control/common/message.do?method=main");
				WebUtils.forward("/WEB-INF/pages/common/message.jsp", request,
						response);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private boolean checkPrivilege(Permission permission,
			HttpServletRequest request) {

		SecurityService securityService = ClassFactory.newInstance()
				.createClassNewInstance(SecurityService.class);
		List list = securityService.checkEmployeeFoPrivilege(permission);

		Employee employee = (Employee) request.getSession().getAttribute(
				"employee");

		boolean flag = false;
		for (Object obj : list) {

			if (employee.getId().equals((String) obj)) {

				flag = true;
			}
		}
		return flag;
	}

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

		doGet(request, response);
	}

}

 

2.    实现Dao与Service,Service与Servlet之间的解耦:

写一个工厂类,如:

XxxDaoFactory中有一个静态方法newInstance()用于得到该工厂类的实例。提供一个方法用于得到目标类的实例对象。如:

XxxDaogetXxxDao(Class clazz) 传进来的class为目标类的实现的接口。通过这个Class得到className,然后通过这个Name值拿到配置文件中的这个Name对应的目标类全名称。

代码如下:

public class ClassFactory {

	private static final ClassFactory factory = new ClassFactory();

	private Properties prop = new Properties();

	private ClassFactory() {

		try {
			prop.load(ClassFactory.class.getClassLoader().getResourceAsStream(
					"classConfig.properties"));
		} catch (IOException e) {
			throw new RuntimeException("类工厂读取配置文件失败");
		}
	}

	public static ClassFactory newInstance() {

		return factory;
	}

	public <T> T createClassNewInstance(Class<T> classType) {

		String name = classType.getSimpleName();
		String className = prop.getProperty(name);

		try {
			return (T) Class.forName(className).newInstance();
		} catch (Exception e) {
			throw new RuntimeException("类工厂创建类对象失败");
		}
		}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值