1.创建一个maven工程,并生成web工程
pom文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.caojiulu</groupId>
<artifactId>jiulu-springmvc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
2.创建对应的注解:
package com.caojiulu.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 JiuluController {
String value() default "";
}
package com.caojiulu.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 JiuluAutowired {
String value() default "";
}
package com.caojiulu.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 JiuluRequestMapping {
String value() default "";
}
package com.caojiulu.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 JiuluRequestParam {
String value() default "";
}
package com.caojiulu.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 JiuluService {
String value() default "";
}
3.创建接口以及实现类:
package com.caojiulu.service;
public interface CaojiuluService {
String query(String name,String age);
}
package com.caojiulu.service.impl;
import com.caojiulu.annotation.JiuluService;
import com.caojiulu.service.CaojiuluService;
@JiuluService("CaojiuluServiceImpl")
public class CaojiuluServiceImpl implements CaojiuluService{
@Override
public String query(String name, String age) {
return "{name="+name+",age="+age+"}";
}
}
2.修改web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>jiulu-springmvc</display-name>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>com.caojiulu.service.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3.编写核心DispatcherServlet
package com.caojiulu.service.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.Arrays;
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.caojiulu.annotation.JiuluAutowired;
import com.caojiulu.annotation.JiuluController;
import com.caojiulu.annotation.JiuluRequestMapping;
import com.caojiulu.annotation.JiuluService;
import com.caojiulu.controller.CaoJiuluController;
import com.caojiulu.handlerAdapter.HandlerAdapterService;
public class DispatcherServlet extends HttpServlet{
List<String> classNames = new ArrayList<String>();
Map<String, Object> beans = new HashMap<String, Object>();
Map<String, Object> handlerMap = new HashMap<String, Object>();
@Override
public void init(ServletConfig config) throws ServletException {
//扫描package
scanPackage("com.caojiulu");
System.out.println(Arrays.asList(classNames));
//实例化
instance();
for (Map.Entry<String, Object> entry : beans.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
//ioc
ioc();
//建立path和method的映射关系
handlerMapping();
for (Map.Entry<String, Object> entry : handlerMap.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
private void handlerMapping() {
if(beans.entrySet().size()<=0){
System.out.println("没有类的实例化");
return ;
}
for (Map.Entry<String, Object> entry : beans.entrySet()) {
Object instance = entry.getValue();
Class<?> clazz = instance.getClass();
if(clazz.isAnnotationPresent(JiuluController.class)){
JiuluRequestMapping jiuluRequestMappingclass = clazz.getAnnotation(JiuluRequestMapping.class);
String classPath = jiuluRequestMappingclass.value();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(JiuluRequestMapping.class)){
JiuluRequestMapping annotation = method.getAnnotation(JiuluRequestMapping.class);
String value = annotation.value();
handlerMap.put(classPath+value, method);
}else{
continue;
}
}
}
}
}
private void ioc() {
if(classNames.size()<=0){
System.out.println("包扫描失败");
return ;
}
for (Map.Entry<String, Object> entry : beans.entrySet()) {
Object value = entry.getValue();
//获取对象的类型
Class<?> class1 = value.getClass();
if(class1.isAnnotationPresent(JiuluController.class)){
Field[] fields = class1.getDeclaredFields();
for (Field field : fields) {
if(field.isAnnotationPresent(JiuluAutowired.class)){
JiuluAutowired jiuluAutowired = field.getAnnotation(JiuluAutowired.class);
//field.set
String value2 = jiuluAutowired.value();
field.setAccessible(true);
try {
field.set(value, beans.get(value2));
} catch (IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
continue;
}
}
}else{
continue;
}
}
}
private void instance() {
if(classNames.size()<=0){
System.out.println("包扫描失败");
return ;
}
for (String className : classNames) {
String cn = className.replace(".class", "");
try {
Class<?> clazz = Class.forName(cn);
if(clazz.isAnnotationPresent(JiuluController.class)){
Object newInstance = clazz.newInstance();
JiuluRequestMapping annotation = clazz.getAnnotation(JiuluRequestMapping.class);
String value = annotation.value();
beans.put(value, newInstance);
}else if(clazz.isAnnotationPresent(JiuluService.class)){
Object newInstance = clazz.newInstance();
JiuluService annotation = clazz.getAnnotation(JiuluService.class);
String value = annotation.value();
beans.put(value, newInstance);
}else{
continue;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//jiulu-springmvc/jiulu/query
String requestURI = request.getRequestURI();
// /jiulu-springmvc
String contextPath = request.getContextPath();
String path = requestURI.replace(contextPath, "");
Method method = (Method)handlerMap.get(path);
//拿到控制类
CaoJiuluController jiuluController = (CaoJiuluController) beans.get("/"+path.split("/")[1]);
HandlerAdapterService ha = (HandlerAdapterService) beans.get("jiuluHandlerAdapter");
Object[] args = ha.hand(request, response, method, beans);
try {
method.invoke(jiuluController, args);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void scanPackage(String filePath) {
URL resource = this.getClass().getClassLoader().getResource("/"+filePath.replace(".", "/"));
String path = resource.getPath();
File file = new File(path);
String[] list = file.list();
for (String string : list) {
File file2 = new File(path+"/"+string);
if(file2.isDirectory()){
scanPackage(filePath +"."+string);
}else{
classNames.add(filePath+"."+file2.getName());
}
}
}
}
4.策略模式处理请求参数
package com.caojiulu.argumentResolver;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface ArgumentResolver {
public boolean support(Class<?> type, int paramIndex, Method method);
//参数解析方法
public Object argumentResolver(HttpServletRequest request,
HttpServletResponse response, Class<?> type,
int paramIndex,//参数索引下坐标,有很多注解,你得知道是哪个参数的注解,每个参数的索引顺序不一样
Method method);
}
package com.caojiulu.argumentResolver;
import java.lang.reflect.Method;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.caojiulu.annotation.JiuluService;
@JiuluService("httpServletRequestArgumentResolver")
public class HttpServletRequestArgumentResolver implements ArgumentResolver{
@Override
public boolean support(Class<?> type, int paramIndex, Method method) {
return ServletRequest.class.isAssignableFrom(type);
}
@Override
public Object argumentResolver(HttpServletRequest request, HttpServletResponse response, Class<?> type,
int paramIndex, Method method) {
return request;
}
}
package com.caojiulu.argumentResolver;
import java.lang.reflect.Method;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.caojiulu.annotation.JiuluService;
@JiuluService("httpServletResponseArgumentResolver")
public class HttpServletResponseArgumentResolver implements ArgumentResolver{
@Override
public boolean support(Class<?> type, int paramIndex, Method method) {
return ServletResponse.class.isAssignableFrom(type);
}
@Override
public Object argumentResolver(HttpServletRequest request, HttpServletResponse response, Class<?> type,
int paramIndex, Method method) {
return response;
}
}
package com.caojiulu.argumentResolver;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.caojiulu.annotation.JiuluRequestParam;
import com.caojiulu.annotation.JiuluService;
@JiuluService("requestParamArgumentResolver")
public class RequestParamArgumentResolver implements ArgumentResolver{
@Override
public boolean support(Class<?> type, int paramIndex, Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Annotation[] annotations = parameterAnnotations[paramIndex];
for (Annotation annotation : annotations) {
if(JiuluRequestParam.class.isAssignableFrom(annotation.getClass())){
return true;
}
}
return false;
}
@Override
public Object argumentResolver(HttpServletRequest request, HttpServletResponse response, Class<?> type,
int paramIndex, Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Annotation[] annotations = parameterAnnotations[paramIndex];
for (Annotation annotation : annotations) {
if(JiuluRequestParam.class.isAssignableFrom(annotation.getClass())){
JiuluRequestParam jiuluRequestParam = (com.caojiulu.annotation.JiuluRequestParam) annotation;
String value = jiuluRequestParam.value();
return request.getParameter(value);
}
}
return null;
}
}
5.处理器的实现
package com.caojiulu.handlerAdapter;
import java.lang.reflect.Method;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface HandlerAdapterService {
public Object[] hand(HttpServletRequest request,//拿request请求里的参数
HttpServletResponse response,Method method,Map<String,Object> beans);
}
package com.caojiulu.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.caojiulu.annotation.JiuluService;
import com.caojiulu.argumentResolver.ArgumentResolver;
@JiuluService("jiuluHandlerAdapter")
public class JiuluHandlerAdapter implements HandlerAdapterService{
@Override
public Object[] hand(HttpServletRequest request, HttpServletResponse response, Method method,
Map<String, Object> beans) {
Class<?>[] parameterTypes = method.getParameterTypes();
Object[] args = new Object[parameterTypes.length];
Map<String, Object> argumentResolvers = getBeansOfType(beans,ArgumentResolver.class);
int paramIndex = 0 ;
int i = 0;
for (Class<?> param : parameterTypes) {
for (Map.Entry<String, Object> entry : argumentResolvers.entrySet()) {
ArgumentResolver ar = (ArgumentResolver) entry.getValue();
if(ar.support(param, paramIndex, method)){
args[i++] = ar.argumentResolver(request, response, param, paramIndex, method);
}
}
paramIndex ++;
}
return args;
}
private Map<String, Object> getBeansOfType(Map<String, Object> beans, Class<ArgumentResolver> class1) {
Map<String, Object> resultBeans = new HashMap<String,Object>();
for (Map.Entry<String, Object> entry : beans.entrySet()) {
Class<?>[] interfaces = entry.getValue().getClass().getInterfaces();
if(interfaces!=null & interfaces.length>0){
for (Class<?> class2 : interfaces) {
if(class2.isAssignableFrom(class1)){
resultBeans.put(entry.getKey(), entry.getValue());
}
}
}
}
return resultBeans;
}
}
6.运行测试情况:
完成手写springmvc!