springmvc
一个dispatchservlet分发到对应的类里面的方法;
对应的类里面的方法,由一个集合映射;
spring
IOC,控制反转,由class反射实例化
实际操作:
第一步,创建个maven的web项目;
第二步,dispatchservlet的创建
由这一步产生的其他步骤
1、创建等下要用到的标签
这里就搞两个。一个controller,一个RequestMapping
@java.lang.annotation.Target(value = { java.lang.annotation.ElementType.TYPE })
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Documented
public @interface Controller {
String value() default "";
}
@java.lang.annotation.Target(value = { java.lang.annotation.ElementType.TYPE,java.lang.annotation.ElementType.METHOD })
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Documented
public @interface RequestMapping {
String value() default "";
}
2、配置到web.xml
<servlet>
<description></description>
<display-name>DispatchServlet</display-name>
<servlet-name>DispatchServlet</servlet-name>
<servlet-class>DispatchServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>application.properties</param-value>
</init-param>
<load-on-start>1</load-on-start>
</servlet>
<servlet-mapping>
<servlet-name>DispatchServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
2、编写DispatchServlet类继承javax.servlet.http.httpservlet
这里面涉及几个重要变量。全部围着它们转;
web.xml里面servlet对应的配置属性<init-param>;location对应的就是param的name;来获取对应的文件的路径真实值
private static final String LOCATION = "contextConfigLocation";
采用properties工具类把配置的文件加载放进properties实例里面;
private java.util.Properties properties = new java.util.Properties();
通过scan标签把每一个类对应的类名都存到集合里面
private java.util.ArrayList<String> classNameArrayList = new java.util.ArrayList<String>();
通过楼上把每个类对应的class,反射实例化的对象存起来,也是一个集合
private java.util.HashMap<String, java.lang.Object> beanHashMap = new java.util.HashMap<String,java.lang.Object>();
每个方法对应的映射存到一个集合。也是通过标签
private java.util.HashMap<String, java.lang.reflect.Method> urlToMethodHashMap = new java.util.HashMap<String,java.lang.reflect.Method>();
先初始化一切准备动作;
楼上的全部变量都得初始化;
四步,
加载配置内容用到第一第二变量;
递归遍历指定包目录下的所有文件,把所有的类名放到集合里;
遍历楼上类名称集合,根据名称class.forname实例化全部对象;
遍历楼上实例对象集合,把每个类实例,先是否继承controller,收集对应mapping的value值。同理实例对应全部method遍历,也是收集对应的mapping的value值。在存入集合。这就是url到method的集合。
public void init(javax.servlet.ServletConfig servletConfig) {
doLoadConfig(servletConfig.getInitParameter(LOCATION));
doScanPackage(properties.getProperty("scanPackage"));
doInstance();
initHandlerMapping();
}
public void doLoadConfig(String location) {
java.io.InputStream inputStream = null;
inputStream = this.getClass().getClassLoader().getResourceAsStream(location);
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public void doScanPackage(String packageName) {
java.net.URL url = this.getClass().getClassLoader().getResource("/"+packageName.replaceAll("\\.", "/"));
java.io.File files = new java.io.File(url.getFile());
for(java.io.File file : files.listFiles()) {
if(file.isDirectory()) {
this.doScanPackage(packageName+"."+file.getName());
}else {
classNameArrayList.add((packageName+"."+file.getName()).replace(".class", "").trim());
}
}
}
private void doInstance() {
if(this.classNameArrayList.size()==0)return;
try {
for(java.lang.String className :this.classNameArrayList) {
java.lang.Class<?> target = java.lang.Class.forName(className);
if(target.isAnnotationPresent(Controller.class)) {
this.beanHashMap.put(target.getName().toLowerCase(), target.newInstance());
}
}
}catch(java.lang.ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public void initHandlerMapping() {
if(this.beanHashMap.isEmpty()) return;
java.util.Iterator<java.util.Map.Entry<String,java.lang.Object>> iterator = this.beanHashMap.entrySet().iterator();
while(iterator.hasNext()) {
java.util.Map.Entry<java.lang.String, java.lang.Object> entry = iterator.next();
java.lang.Object object = entry.getValue();
Class<?> target = object.getClass();
if(!target.isAnnotationPresent(Controller.class)) {
continue;
}
String objectUrlValue = "";
if(target.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = target.getAnnotation(RequestMapping.class);
objectUrlValue = requestMapping.value();
}
for(java.lang.reflect.Method method : target.getMethods()) {
if(!method.isAnnotationPresent(RequestMapping.class)) continue;
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String methodUrlValue = requestMapping.value();
String url = objectUrlValue + methodUrlValue;
urlToMethodHashMap.put(url, method);
}
}
}
到这里准备的初始化的代码都敲好了。
就差,来一个请求,怎么处理,分发到对应的类实例里面的方法
第三步:写分发的代码,
获取对应的类和方法的url
根据url在楼上的urltomethod的集合里面查询出对应的bean
把request的对应的parametermap全部一一匹配到对应method的对应变量。也就是依据变量名称。url里面变量也是=区分的
反射method调用。把对应的实例的class和对应参数给它。那就通了。
private void doDispatch(javax.servlet.http.HttpServletRequest request,javax.servlet.http.HttpServletResponse response) {
if(this.urlToMethodHashMap.isEmpty()) return;
String requestUri = request.getRequestURI();
String contextPath = request.getContextPath();
requestUri = requestUri.replace(contextPath, "").replaceAll("/+", "/");
if(!this.urlToMethodHashMap.containsKey(requestUri)) {
try {
response.getWriter().println("not founded");
} catch (IOException e) {
e.printStackTrace();
}
return;
}
java.util.Map<String, String[]> objectParameterMap = request.getParameterMap();
java.lang.reflect.Method method = this.urlToMethodHashMap.get(requestUri);
java.lang.Class<?>[] methodParameterTypes = method.getParameterTypes();
java.lang.Object[] objectsValue = new Object[methodParameterTypes.length];
for(int i=0;i<methodParameterTypes.length;i++) {
java.lang.Class<?> methodParameterClass = methodParameterTypes[i];
if(methodParameterClass == javax.servlet.http.HttpServletRequest.class) {
objectsValue[i] = request;
}
if(methodParameterClass == javax.servlet.http.HttpServletResponse.class) {
objectsValue[i] = response;
}
if(methodParameterClass == String.class) {
for(java.util.Map.Entry<String, String[]> temp : objectParameterMap.entrySet()) {
if(methodParameterClass.getName()==temp.getKey()) {
objectsValue[i] = temp.getValue();
}
}
}
}
try {
method.invoke(this.beanHashMap.get(method.getDeclaringClass().getName().toLowerCase()), objectsValue);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doDispatch(request,response);
}