项目目录结构:
maven引入servlet包
javax.servlet
javax.servlet-api
3.0.1
provided
1:编写自定义注解
MyAutowired
package com.zhjie.mySpring.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAutowired {
String value() default "";
}
MyController
package com.zhjie.mySpring.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyController {
String value() default "";
}
MyRequestMapping
package com.zhjie.mySpring.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
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 MyRequestMapping {
String value() default "";
}
MyRequestParam
package com.zhjie.mySpring.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyRequestParam {
String value() default "";
}
MyService
package com.zhjie.mySpring.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyService {
String value() default "";
}
2:定义service层
TestService
package com.zhjie.mySpring.service;
public interface TestService {
String query(String name,String age);
}
TestServiceImpl
package com.zhjie.mySpring.service.impl;
import com.zhjie.mySpring.annotation.MyService;
import com.zhjie.mySpring.service.TestService;
@MyService("TestServiceImpl")
public class TestServiceImpl implements TestService{
public String query(String name, String age) {
return "name="+name+";age="+age;
}
}
3:定义controller层
TestController
package com.zhjie.mySpring.controller;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhjie.mySpring.annotation.MyAutowired;
import com.zhjie.mySpring.annotation.MyController;
import com.zhjie.mySpring.annotation.MyRequestMapping;
import com.zhjie.mySpring.annotation.MyRequestParam;
import com.zhjie.mySpring.service.TestService;
@MyController
@MyRequestMapping("/user")
public class TestController {
@MyAutowired("TestServiceImpl")
private TestService testService;
/**
*
* Title: query
* Description: 查询
* @param request
* @param response
* @param name
* @param age
*/
@MyRequestMapping("/query")
public void query(HttpServletRequest request,HttpServletResponse response,@MyRequestParam("name") String name,@MyRequestParam("age") String age){
PrintWriter writer;
try {
writer = response.getWriter();
String result = testService.query(name, age);
writer.write(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4:定义DispatcherServlet
package com.zhjie.mySpring.servlet;
import java.io.File;
import java.io.IOException;
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.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhjie.mySpring.annotation.MyAutowired;
import com.zhjie.mySpring.annotation.MyController;
import com.zhjie.mySpring.annotation.MyRequestMapping;
import com.zhjie.mySpring.annotation.MyService;
import com.zhjie.mySpring.controller.TestController;
import com.zhjie.mySpring.handlerAdapter.HandlerAdapterService;
/**
*
* Title: DispatcherServlet
* Description: servlet核心处理类
* @author zhjie
* @date 2020年2月23日
*/
public class DispatcherServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
// 存在当前加载的所有的类
List classNames = new ArrayList();
// 存放实例化对象
Map beans = new HashMap();
//存放controller里的方法和路径的映射
Map methodMap = new HashMap();
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("init...............");
//1:扫描所有的class获取需要实例化的类
doScanPackage("com.zhjie.mySpring");
//2:获取需要实例化的类
doInstance();
//3:ioc 将有controller层有Autowired注解的对象注入到controller
doIoc();
//4:获取controller里的路径和方法的映射
methodMapping();
}
/**
*
* Title: doScanPackage
* Description: 扫描所有类
* @param basePackage
*/
private void doScanPackage(String basePackage) {
//获取class文件路径 如:file:/E:/Eclipse_Maven/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/spring-mvc/WEB-INF/classes/com/zhjie/mySpring/
URL resource = this.getClass().getClassLoader().getResource("/" + basePackage.replaceAll("\\.", "/"));
String fileStr = resource.getFile();
System.out.println(fileStr);
File file = new File(fileStr);
String[] listFiles = file.list();
//从根路径开始递归查找出所有.class文件
for(String path: listFiles){
File filePath = new File(fileStr + path);
if(filePath.isDirectory()){
doScanPackage(basePackage+"."+path);
}else{
classNames.add(basePackage+"."+filePath.getName());
}
}
}
/**
*
* Title: doInstance
* Description: 实例化
*/
private void doInstance() {
if(classNames.size()<=0){
System.out.println("没有扫描到类。。。。。。");
return;
}
//通过反射实例化对象
for(String classPath: classNames){
String className = classPath.replace(".class", "");
try {
Class> clazz = Class.forName(className);
//判断这个类是否有MyController注解
if(clazz.isAnnotationPresent(MyController.class)){
//获取注解对象
MyRequestMapping myRequestMapping = clazz.getAnnotation(MyRequestMapping.class);
//实例化
Object instance = clazz.newInstance();
beans.put(myRequestMapping.value(), instance);
}else if(clazz.isAnnotationPresent(MyService.class)){
//获取注解对象
MyService myService = clazz.getAnnotation(MyService.class);
//实例化
Object instance = clazz.newInstance();
beans.put(myService.value(), instance);
}else{
continue;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
*
* Title: doIoc
* Description: IOC
*/
private void doIoc() {
if(beans.size()<=0){
System.out.println("没有实例化的对象。。。");
return;
}
for(String key : beans.keySet()){
// 获取实例
Object instance = beans.get(key);
//根据实例获取class对象
Class> clazz = beans.get(key).getClass();
if(clazz.isAnnotationPresent(MyController.class)){
//获取该对象所有定义的成员变量
Field[] fields = clazz.getDeclaredFields();
if(fields.length>0){
for(Field field: fields){
if(field.isAnnotationPresent(MyAutowired.class)){
//获取成员变量的注解对象
MyAutowired myAutowired = field.getAnnotation(MyAutowired.class);
String value = myAutowired.value();
// 由于此类成员变量设置为private,需要强行设置
field.setAccessible(true);
try {
//注入对象实例
field.set(instance, beans.get(value));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}else{
continue;
}
}
}else{
continue;
}
}
}
}
/**
*
* Title: methodMapping
* Description: 获取controller里的方法和路径的映射
*/
private void methodMapping() {
if(beans.isEmpty()){
System.out.println("没有实例化对象。。。");
return;
}
for(String key : beans.keySet()){
//获取实例对象
Object instance = beans.get(key);
//获取class对象
Class> clazz = instance.getClass();
//判断类上是否controller层
if(clazz.isAnnotationPresent(MyController.class)){
//判断类上是否有MyRequestMapping注解
MyRequestMapping myRequestMapping = clazz.getAnnotation(MyRequestMapping.class);
//获取controller上的路径
String clazzPath = myRequestMapping.value();
//获取controller类的所有方法
Method[] methods = clazz.getMethods();
if(methods.length>0){
for(Method method : methods){
//判断方法上是否有MyRequestMapping注解
if(method.isAnnotationPresent(MyRequestMapping.class)){
//获取方法上的路径
MyRequestMapping requestMapping = method.getAnnotation(MyRequestMapping.class);
String methodPath = requestMapping.value();
//key值 类上的路径加上发放上的路径,value值为方法对象
methodMap.put(clazzPath+methodPath, method);
}else{
continue;
}
}
}else{
continue;
}
}else{
continue;
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//所有请求转发到post
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost...");
//获取请求地址 如:spring-mvc/user/query
String uri = req.getRequestURI();
//截取请求地址
//首先获取项目上下文
String context = req.getContextPath();
//请求路径
String path = uri.replace(context, "");
//通过path获取需要执行的方法
Method method = (Method) methodMap.get(path.substring(0,path.length()-1));
//获取该类的实例化对象
TestController controller = (TestController) beans.get("/" + path.split("/")[1]);
// 处理参数
HandlerAdapterService ha = (HandlerAdapterService) beans.get("myHandlerAdapter");
Object[] args = ha.handle(req, resp, method, beans);
try {
// 通过反射来实现方法的调用
method.invoke(controller, args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
5:web.xml引入servlet
DispatcherServlet
com.zhjie.mySpring.servlet.DispatcherServlet
0
DispatcherServlet
/
6:使用策略模式来解析参数
HandlerAdapterService
package com.zhjie.mySpring.handlerAdapter;
import java.lang.reflect.Method;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* Title: HandlerAdapterService
* Description: 参数处理接口
* @author zhjie
* @date 2020年2月22日
*/
public interface HandlerAdapterService {
public Object[] handle(HttpServletRequest req, HttpServletResponse resp,
Method method, Map beans);
}
MyHandlerAdapter
package com.zhjie.mySpring.handlerAdapter;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhjie.mySpring.annotation.MyService;
import com.zhjie.mySpring.argumentParsing.ArgumentParsing;
/**
*
* Title: MyHandlerAdapter
* Description: 参数处理
* @author zhjie
* @date 2020年2月23日
*/
@MyService("myHandlerAdapter")
public class MyHandlerAdapter implements HandlerAdapterService {
/**
* 参数处理
* method 方法对象
* beans 存放所有实例化对象
*/
public Object[] handle(HttpServletRequest req, HttpServletResponse resp,
Method method, Map beans) {
//获取方法中定义的参数
Class>[] paramClazzs = method.getParameterTypes();
// 定义一个返回参数的结果集
Object[] args = new Object[paramClazzs.length];
//Object[] args = {req, resp, "zhjie", "18"};
// 定义一个ArgumentResolver实现类的Map
Map argumentResolvers = getBeansOfType(beans, ArgumentParsing.class);
//定义参数索引
int paramIndex = 0;
//定义数组下标索引
int i = 0;
// 开始处理参数
for(Class> paramClazz: paramClazzs) {
//哪个参数对应了哪个参数解析类,用策略模式来找
for(Map.Entry entry : argumentResolvers.entrySet()) {
ArgumentParsing ar = (ArgumentParsing)entry.getValue();
if (ar.support(paramClazz, paramIndex, method)) {
args[i++] = ar.argumentResolver(req,
resp,
paramClazz,
paramIndex,
method);
}
}
paramIndex++;
}
return args;
}
/**
* 从beans中获取所有实现ArgumentResolver接口类的实例
* @param beans IOC容器中全部的bean
* @param intfType 定义的ArgumentResolver类
* @return
*/
private Map getBeansOfType(Map beans,
Class intfType) {
Map resultBeans = new HashMap();
for(Map.Entry map: beans.entrySet()) {
// 获取满足ArgumentResolver接口的bean
Class>[] intfs = map.getValue().getClass().getInterfaces();
if(intfs != null && intfs.length >0) {
for(Class> intf: intfs) {
// 将满足的bean存储在resultBeans中
if(intf.isAssignableFrom(intfType)) {
resultBeans.put(map.getKey(), map.getValue());
}
}
}
}
return resultBeans;
}
}
ArgumentParsing
package com.zhjie.mySpring.argumentParsing;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface ArgumentParsing {
/**
* 判断当前的类是继承于ArgumentResolver
* @param type 当前参数注解的类对象
* @param paramIndex 参数下标
* @param method 当前的方法
* @return
*/
public boolean support(Class> type, int paramIndex, Method method);
/**
*
* @param request
* @param response
* @param type
* @param paramIndex
* @param method
* @return
*/
public Object argumentResolver(HttpServletRequest request,
HttpServletResponse response, Class> type,
int paramIndex,
Method method);
}
HttpServletRequestArgumentParsing
package com.zhjie.mySpring.argumentParsing;
import java.lang.reflect.Method;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhjie.mySpring.annotation.MyService;
@MyService("httpServletRequestArgumentParsing")
public class HttpServletRequestArgumentParsing implements ArgumentParsing {
public boolean support(Class> type, int paramIndex, Method method) {
return ServletRequest.class.isAssignableFrom(type);
}
public Object argumentResolver(HttpServletRequest request,
HttpServletResponse response, Class> type, int paramIndex,
Method method) {
return request;
}
}
HttpServletResponseArgumentParsing
package com.zhjie.mySpring.argumentParsing;
import java.lang.reflect.Method;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhjie.mySpring.annotation.MyService;
@MyService("httpServletResponseArgumentParsing")
public class HttpServletResponseArgumentParsing implements ArgumentParsing {
public boolean support(Class> type, int paramIndex, Method method) {
return ServletResponse.class.isAssignableFrom(type);
}
public Object argumentResolver(HttpServletRequest request,
HttpServletResponse response, Class> type, int paramIndex,
Method method) {
return response;
}
}
RequestParamArgumentParsing
package com.zhjie.mySpring.argumentParsing;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhjie.mySpring.annotation.MyRequestParam;
import com.zhjie.mySpring.annotation.MyService;
@MyService("requestParamArgumentParsing")
public class RequestParamArgumentParsing implements ArgumentParsing {
public boolean support(Class> type, int paramIndex, Method method) {
// type = class java.lang.String
// @MyRequestParam("name")String name
//获取当前方法的参数
Annotation[][] an = method.getParameterAnnotations();
Annotation[] paramAns = an[paramIndex];
for (Annotation paramAn : paramAns) {
//判断传进的paramAn.getClass()是不是 MyRequestParam 类型
if (MyRequestParam.class.isAssignableFrom(paramAn.getClass())) {
return true;
}
}
return false;
}
public Object argumentResolver(HttpServletRequest request,
HttpServletResponse response, Class> type, int paramIndex,
Method method) {
//获取当前方法的参数
Annotation[][] an = method.getParameterAnnotations();
Annotation[] paramAns = an[paramIndex];
for (Annotation paramAn : paramAns) {
//判断传进的paramAn.getClass()是不是 MyRequestParam 类型
if (MyRequestParam.class.isAssignableFrom(paramAn.getClass())) {
MyRequestParam cr = (MyRequestParam) paramAn;
String value = cr.value();
return request.getParameter(value);
}
}
return null;
}
}
7:启动项目
浏览器访问地址:http://localhost:8080/spring-mvc/user/query/?name=zhjie&age=18
8:运行结果