简单mvc---模拟Springmvc
1、注解篇
Auwowrited
package org.aaron.mvc.annaotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AaronAutowrited { String value() default "";
}
Controller
package org.aaron.mvc.annaotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AaronController { String value() default "";
}
RequestMapping
package org.aaron.mvc.annaotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AaronRequestMapping { String value() default "";
}
RequestParam
package org.aaron.mvc.annaotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AaronRequestParam { String value() default "";
}
Service
package org.aaron.mvc.annaotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AaronService { String value() default "";
}
2、DispatcherServlet
package org.aaron.mvc.servlet; import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.aaron.mvc.annaotation.AaronAutowrited;
import org.aaron.mvc.annaotation.AaronController;
import org.aaron.mvc.annaotation.AaronRequestMapping;
import org.aaron.mvc.annaotation.AaronRequestParam;
import org.aaron.mvc.annaotation.AaronService;
import org.omg.CORBA.Request; public class DispatcherServlet extends HttpServlet { List<String> classNames = new ArrayList<String>();// 全类名路径
// //org.aaron.mvc.service.impl+类名 Map<String,Object> beans = new HashMap<>(); Map<String,Object> handlerMap = new HashMap<>();
/**
*
*/
private static final long serialVersionUID = 1L; public void init(ServletConfig config) {
// ioc
// 扫描所有的bean----->扫描所有的class文件
scanPackage("org.aaron"); // spring的做法是写在配置文件中
// 根据类创建对象
doInstance();
doIoc();
buildUrlMapping();//根据url 建立关系 method
} // 扫描文件
private void scanPackage(String basePackage) {
URL url = this.getClass().getClassLoader().getResource("/" + basePackage.replaceAll("\\.", "/"));// 获取工作空间的编译路径
System.err.println(url);
String fileStr = url.getFile();
File file = new File(fileStr);// 拿到目录下的文件和文件夹
String[] filesStr = file.list(); // Aaron
for (String path : filesStr) { File filePath = new File(fileStr + path);// org.aaron.mvc
if (filePath.isDirectory()) {// 判断是文件还是文件夹 文件夹 递归继续找 scanPackage(basePackage + "." + path);
} else { classNames.add(basePackage + "." + filePath.getName());// org.aaron.mvc.xxx.xxxx.class
}
}
} // 根据扫描的类名 实例化
private void doInstance() {
if (classNames.size() <= 0) {
System.err.println("扫描失败");
return;
}
// 遍历 扫描到class文件
for (String className : classNames) {
String cn = className.replace(".class", "");
try {
Class<?> clazz = Class.forName(cn); // 获取到org.aaron.
if (clazz.isAnnotationPresent(AaronController.class)) {// 判断是不是有控制场注解
Object instance = clazz.newInstance();// 创建类 实例化的对象
AaronRequestMapping requestMapping = clazz.getAnnotation(AaronRequestMapping.class);//拿到 mapping 注解
String rm = requestMapping.value();//获取到mapping的value
beans.put(rm, instance);//
}else if (clazz.isAnnotationPresent(AaronService.class)){ AaronService aaronService = clazz.getAnnotation(AaronService.class);
Object instance = clazz.newInstance();
beans.put(aaronService.value(),instance);//
}else{
continue;
} } catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
//把service 注入到Controller
public void doIoc(){
if(beans.entrySet().size()<=0){ System.err.println("没有实例化的类");
}
//遍历map的实例化的类
for(Map.Entry<String, Object> entry: beans.entrySet()){
Object instace = entry.getValue();
Class<?> clazz = instace.getClass();
if(clazz.isAnnotationPresent(AaronController.class)){ Field[] fields =clazz.getDeclaredFields();
for(Field field : fields){
if(field.isAnnotationPresent(AaronAutowrited.class)){//判断当前遍历是否有注解
AaronAutowrited aaronAutowrited = field.getAnnotation(AaronAutowrited.class);
String key = aaronAutowrited.value();//获取到 注解的value
field.setAccessible(true);//因为是private 无法修改值
try {
field.set(instace, beans.get(key));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
continue;
} }
}else{
continue;
} }
} private void buildUrlMapping(){ if(beans.entrySet().size()<=0){//没有类的实例化
System.err.println("没有类的实例化");
return;
}
for(Map.Entry<String, Object> entry : beans.entrySet()){
Object instance = entry.getValue();
Class<?> clazz = instance.getClass();
if(clazz.isAnnotationPresent(AaronController.class)){ AaronRequestMapping aaronRequestMapping = clazz.getAnnotation(AaronRequestMapping.class);
String classPath = aaronRequestMapping.value();//拿到类上的mapping
Method[] methods = clazz.getMethods();//拿到类的方法
for(Method method : methods){
if(method.isAnnotationPresent(AaronRequestMapping.class)){//判断了方法上面是否有注解
AaronRequestMapping methodMapping = method.getAnnotation(AaronRequestMapping.class);
String methodPath = methodMapping.value();//获取到注解的value
handlerMap.put(classPath+methodPath, method); }else{
continue;
} }
}else{
continue;
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
System.err.println("test1");
this.doPost(req, resp);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
//获取请求路径 /项目名/ctrl/method
String uri = req.getRequestURI();
String content = req.getContextPath();//获取项目名
String path = uri.replace(content, "");//ctrl/method
Method method = (Method)handlerMap.get(path);
Object instance = (Object)beans.get("/"+path.split("/")[1]);// ctrl
Object[] agrs = hand(req,resp,method);
try {
method.invoke(instance, agrs);
} 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();
}
super.doPost(req, resp);
}
//处理参数
private static Object[] hand(HttpServletRequest req, HttpServletResponse resp,Method method){
//拿到当前执行的方法有哪些参数
Class<?>[] paramClazzs = method.getParameterTypes();
//根据参数的个数 new一个存放参数的数组
Object[] args = new Object[paramClazzs.length];
int arg_i = 0 ;
int index = 0;
for(Class<?> paramClazz : paramClazzs){
if(ServletRequest.class.isAssignableFrom(paramClazz)){ args[arg_i++] = req;
}
if(ServletResponse.class.isAssignableFrom(paramClazz)){ args[arg_i++] = resp;
}
Annotation[] paramAns = method.getParameterAnnotations()[index];
if(paramAns.length>0){
for(Annotation paramAn : paramAns){
if(AaronRequestParam.class.isAssignableFrom(paramAn.getClass())){
AaronRequestParam rp = (AaronRequestParam)paramAn;
args[arg_i++] = req.getParameter(rp.value()); } } }
index++;
}
return args; } }
3、实战篇
controller代码
package org.aaron.mvc.ctrl; import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.aaron.mvc.annaotation.AaronAutowrited;
import org.aaron.mvc.annaotation.AaronController;
import org.aaron.mvc.annaotation.AaronRequestMapping;
import org.aaron.mvc.annaotation.AaronRequestParam;
import org.aaron.mvc.service.TestService; @AaronController
@AaronRequestMapping("/Aaron")
public class TestCtrl { @AaronAutowrited("TestServiceImpl")
private TestService service; @AaronRequestMapping("/query")
public void query(HttpServletRequest request,HttpServletResponse response,
@AaronRequestParam("name") String name, @AaronRequestParam("age") String age){
String result = service.query(name, age);
try {
PrintWriter out; response.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
out = response.getWriter(); out.write(result);
out.close(); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
service接口
package org.aaron.mvc.service; public interface TestService { String query(String name,String age);
}
service接口实现
package org.aaron.mvc.service.impl; import org.aaron.mvc.annaotation.AaronService;
import org.aaron.mvc.service.TestService; @AaronService("TestServiceImpl")
public class TestServiceImpl implements TestService{ public String query(String name, String age) {
// TODO Auto-generated method stub
return "当前用户:"+name+"年龄"+age ;
} }
简单mvc---模拟Springmvc的更多相关文章
- 使用Java元注解和反射实现简单MVC框架
Springmvc的核心是DispatcherServlet来进行各种请求的拦截,进而进行后续的各种转发处理.流程图如下: 说明:客户端发出一个http请求给web服务器,web服务器对http请求进 ...
- 手写一个简单版的SpringMVC
一 写在前面 这是自己实现一个简单的具有SpringMVC功能的小Demo,主要实现效果是; 自己定义的实现效果是通过浏览器地址传一个name参数,打印“my name is”+name参数.不使用S ...
- PhantomJS实现最简单的模拟登录方案
以前写爬虫,遇到需要登录的页面,一般都是通过chrome的检查元素,查看登录需要的参数和加密方法,如果网站的加密非常复杂,例如登录qq的,就会很蛋疼 在后面,有了Pyv8,就可以把加密的js文件扔给它 ...
- telnet简单操作 模拟请求
telnet简单操作 模拟请求 一: 二: 三: 按照以上操作即可!
- 简单MVC理解与实现
MVC基本概念 MVC大家不陌生,包含模型(Model).视图(View).控制器(Controller),其中模型用于基本业务逻辑的实现,视图用于响应结果的表示,控制器用于模型控制和请求分派.先放上 ...
- [模拟回调] demo1模拟用字符串调用js函数 demo2模拟springmvc controller回调页面js函数
demo1. 模拟用字符串调用js 函数 function dataQuery() { var strFun = "testCallBack"; var strParam = &q ...
- I.MX6 简单电路模拟USB设备的插入
/**************************************************************************** * I.MX6 简单电路模拟USB设备的插入 ...
- C++动态数组简单的模拟二元堆
//C++动态数组简单的模拟二元堆 #include<iostream> using namespace std; class BinaryHeap { private: int cap; ...
- 洛谷[Luogu] 普及村-简单的模拟总结
题目列表 注明:Level值代表在本难度下的排行.(纯粹本蒟蒻主观评判)注明:Level值代表在本难度下的排行.(纯粹本蒟蒻主观评判)注明:Level值代表在本难度下的排行.(纯粹本蒟蒻主观评判) P ...
- 简单mvc框架核心笔记
简单mvc框架核心笔记 看了thinkphp5的源码,模仿写了一个简单的框架,有一些心得笔记,记录一下 1.目录结构 比较简单,没有tp那么复杂,只是把需要的核心类写了一些. 核心类库放在mykj里, ...
随机推荐
- 题解 P3620 【[APIO/CTSC 2007]数据备份】
直接贪心(每次选最小)的话显然不对...样例都过不了... 选两个办公楼的时候,显然不能跨越另一个楼,这样不优... 于是 先把原数列处理成n-1个的数(每一个办公楼和上一个的距离),存在a[]中 题 ...
- 解决win10下IIS下"对路径...的访问被拒绝
解决方案如下: 1.右击文件夹,安全,添加IUSR和IIS_IUSRS安全控制权限. 2.右击文件夹,常规,查看是否只读.将只读属性去掉.
- 热情组——项目冲刺 Day4
项目相关 作业相关 具体描述 班级 班级链接 作业要求 链接地址 团队名称 热情组 作业目标 实现软件制作,以及在福大的传播 Github链接 链接地址 SCRUM部分: 成员昵称 昨日目标 开始时间 ...
- 工作中常用的Linux命令介绍与实践
前言 做后端开发的同学,一般都会接触到服务器,而我们现在的系统用的比较多的服务器系统就是linux了,平时多多少少也会接触到一些linux下的shell命令.我们来介绍下linux一些常用的命令和使用 ...
- Loj #3044. 「ZJOI2019」Minimax 搜索
Loj #3044. 「ZJOI2019」Minimax 搜索 题目描述 九条可怜是一个喜欢玩游戏的女孩子.为了增强自己的游戏水平,她想要用理论的武器武装自己.这道题和著名的 Minimax 搜索有关 ...
- 排列组合(包括n中随机抽取m个)
有些情况我们需要获取一个数组中的所有排列组合情况,或者获取一部分数据进行随机组合,这个在python中有一个模块可以实现.具体情况如下 :::::::::::::::::::::::::::::::: ...
- 前端开发vscode必备插件
VSCode 插件 Atom one Dark Theme Atom Dark主题 Auto Close Tag 自动关闭标签 Auto Rename Tag 自动重命名标签 Beautify 格式化 ...
- 提高性能,MySQL 读写分离环境搭建(一)
这是松哥之前一个零散的笔记,整理出来分享给大伙! MySQL 读写分离在互联网项目中应该算是一个非常常见的需求了.受困于 Linux 和 MySQL 版本问题,很多人经常会搭建失败,今天松哥就给大伙举 ...
- Nginx-Tomcat 等运维常用服务的日志分割-logrotate
目录 一 .Nginx-Tomcat 等常用服务日志分析 Nginx 日志 Tomcat日志 MongoDB 日志 Redis 日志 二 .日志切割服务 logrotate 三.日志切割示例 Ngin ...
- Spring Boot 静态页面跳转
本篇博客仅为自己提个醒:如何跳转页面而不麻烦控制器. 当我们创建 Spring Boot 项目时(勾选了 Thymeleaf 和 Web),目录结构会是如下: 其中图二是我创建了一个 h ...