MVC框架
这篇文章主要是对MVC框架利用反射原理具体实现
MVC在人机交互具体如下图
实现代码如下
controllerServlet层
package com.yf.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.alibaba.fastjson.JSON;
import com.yf.util.ReflectUtil;
import com.yf.util.StringUtil;
import constant.TypeConstant;
@WebServlet(loadOnStartup = 1, urlPatterns = "*" + TypeConstant.URI_SUFFIX)
public class ControlServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
// 设置请求头,避免跨域问题
resp.setHeader("Access-Control-Allow-Origin", "*");
// 获取上下文对象
ServletContext ctx = req.getSession().getServletContext();
// 获取请求路径
String uri = req.getRequestURI();
// 对请求资源进行分割
String[] uristr = uri.split("/");
// 获取模型类名
String modelname = StringUtil.UpperCaseFirst(uristr[uristr.length - 2]) + TypeConstant.MODEL_SUFFIX;
// 获取模型对象的方法名
String methodname = uristr[uristr.length - 1].replace(TypeConstant.URI_SUFFIX, "");
// 获取模型对象
Object modelobj = ctx.getAttribute(modelname);
// 判断模型对象是否存在
if (modelobj == null) {
System.out.println("模型对象不存在");
return;
}
// 利用获取方法
Method method = ReflectUtil.findMethod(modelobj.getClass(), methodname);
// 判断是否存
if (method == null) {
System.out.println("方法不存在");
return;
}
// 获取调用方法的参数列表
Class<?>[] parameterType = method.getParameterTypes();
// 创建集合用来保存参数类型
List<Object> paramlist = new ArrayList<>();
if (parameterType != null && parameterType.length != 0) {
// 把对应的参数类型保存在list集合里
for (Class<?> paramtype : parameterType) {
if (paramtype == HttpServletRequest.class) {
paramlist.add(req);
}
if (paramtype == HttpServletResponse.class) {
paramlist.add(resp);
}
if (paramtype == HttpSession.class) {
paramlist.add(req.getSession());
}
}
}
// 获取方法的返回值类型
Class<?> returnType = method.getReturnType();
try {
// 通过对象去调用方法
Object result = method.invoke(modelobj, paramlist.toArray());
// 判断返回值结果是否为空
if (result != null) {
// 判断方法类型是否为void
if (returnType != void.class) {
// 获取返回值类型
Class<?> backtype = result.getClass();
// 判断返回值类型是不是String
if (backtype == String.class) {
String resultstr = String.valueOf(result);
// 判断返回值是不是redirect开头,如果是,则重定向
if (resultstr.startsWith(TypeConstant.REDIRECT_PREFIX)) {
resp.sendRedirect(resultstr.replace(TypeConstant.REDIRECT_PREFIX, ""));
} else {
req.getRequestDispatcher(resultstr).forward(req, resp);
}
} else {
resp.setContentType("application/json; charset=utf-8");
PrintWriter pw = resp.getWriter();
// 将返回结果转换json,显示在页面上
pw.print(JSON.toJSON(result));
}
}
}
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
利用反射原理和监听器,获取所有的Model层
package com.yf.applicationListener;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import constant.TypeConstant;
@WebListener
public class ApplicationListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void contextInitialized(ServletContextEvent evt) {
// TODO Auto-generated method stub
// 获取上下文对象
ServletContext ctx = evt.getServletContext();
String classpath = "";
try {
//获取路径
classpath = URLDecoder.decode(Thread.currentThread().getContextClassLoader().getResource("").getPath(),
"utf-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 获取路径,并且把.替换成/
String modelFilePath = classpath + TypeConstant.MODEL_PACKAGE.replace(".", File.separator);
// 获取所有的model并放入一个String数组里面
String[] modelfiles = new File(modelFilePath).list();
// 判断路径不为空或长度不为0
if (modelFilePath != null && modelFilePath.length() != 0) {
// 变量所有的数组
for (String modelFilename : modelfiles) {
String name = modelFilename.substring(0, modelFilename.indexOf("."));
// 将所有model对象存入上下文对象
try {
System.out.println(name);
//TypeConstant.MODEL_PACKAGE 定义的常量类中的数据;
ctx.setAttribute(name, Class.forName(TypeConstant.MODEL_PACKAGE + "." + name).newInstance());
System.out.println(ctx.getAttribute(name));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
model层:只能进行数据之间的传输
package com.yf.model;
import javax.servlet.http.HttpServletRequest;
import com.yf.bean.PageBean;
import com.yf.service.HeroService;
import com.yf.service.imp.HeroServiceImpl;
public class HeroModel {
// 对Sevice对象初始化
HeroService heroservice = new HeroServiceImpl();
public PageBean getHeros(HttpServletRequest req) {
// 获取客户端的数据
int id = Integer.parseInt(req.getParameter("powerid"));
int startnum = Integer.parseInt(req.getParameter("page"));
int pagesize = Integer.parseInt(req.getParameter("rows"));
System.out.println(id);
// 调用Sevice层中实现的方法
return heroservice.getPagingHeroes(id, startnum, pagesize);
}
}
service接口中实现的方法:这里主要是对数据库的访问与处理业务逻辑,并返回给model层
//下面方法是我查询用mysql数据库进行的分页操作
public class HeroServiceImpl implements HeroService {
// 使用动态代理得到接口对象
HeroDao herodao = DaoProxy.getDaoInstance(HeroDao.class);
@Override
public PageBean getPagingHeroes(int powerId, int pageNo, int pageSize) {
PageBean pagebean = new PageBean();
pagebean.setTotal(herodao.getHeroCountByPowerId(powerId));
pagebean.setRows(herodao.selectHero(powerId, (pageNo - 1) * pageSize, pageSize));
return pagebean;
}
结论:
在MVC模式中要理解其中:
Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,主要提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。主要使用的技术:数据模型:实体类(JavaBean),数据访问:JDBC,Hibernate等。
View(视图):负责进行模型的展示,一般就是我们见到的用户界面,比如JSP,Html等
Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。主要使用的技术:servlet,Struts中的Action类等,
每个都担任着不同的任务,然后相互合作一样