DispatcherServlet
DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自己定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理,是配置spring MVC的第一步。 DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。
简单地说就是承上启下,核心中的核心。
手写一个DispatcherServlet
理清职责: 简化版的SpringMVC
DispatcherServlet:
package core
.web
;
import java
.io
.IOException
;
import java
.io
.InputStream
;
import java
.lang
.reflect
.Method
;
import java
.util
.ArrayList
;
import java
.util
.List
;
import javax
.servlet
.ServletException
;
import javax
.servlet
.http
.HttpServlet
;
import javax
.servlet
.http
.HttpServletRequest
;
import javax
.servlet
.http
.HttpServletResponse
;
import org
.dom4j
.Document
;
import org
.dom4j
.Element
;
import org
.dom4j
.io
.SAXReader
;
import core
.common
.Handler
;
import core
.common
.HandlerMapping
;
public class DispatcherSerlvet extends HttpServlet {
private static final long serialVersionUID
= 1L
;
private HandlerMapping handlerMapping
;
@Override
public void init() throws ServletException
{
SAXReader saxReader
= new SAXReader();
String configLocation
= getInitParameter("configLocation");
InputStream in
= getClass().getClassLoader().getResourceAsStream(configLocation
);
try {
Document doc
= saxReader
.read(in
);
Element root
= doc
.getRootElement();
List
<Element> elements
= root
.elements();
List
<Object>beans
= new ArrayList<Object>();
for (Element element
: elements
) {
String className
= element
.attributeValue("class");
System
.out
.println("className:"+className
);
Object bean
= Class
.forName(className
).newInstance();
beans
.add(bean
);
}
System
.out
.println("beans:"+beans
);
handlerMapping
= new HandlerMapping();
handlerMapping
.process(beans
);
} catch (Exception e
) {
e
.printStackTrace();
throw new ServletException(e
);
}
}
@Override
protected void service(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
String path
= req
.getRequestURI().substring(req
.getContextPath().length());
Handler handler
= handlerMapping
.getHandler(path
);
if (handler
==null
) {
System
.out
.println("请求路径为:"+path
+"没有提供对应的处理器");
resp
.sendError(404);
return;
}
Method method
= handler
.getMethod();
Object obj
= handler
.getObj();
try {
Class
[]types
= method
.getParameterTypes();
Object rv
= null
;
if (types
.length
>0) {
Object
[]params
= new Object[types
.length
];
for (int i
= 0; i
< types
.length
; i
++) {
if (types
[i
]==HttpServletRequest
.class) {
params
[i
]=req
;
}
if (types
[i
]==HttpServletResponse
.class) {
params
[i
]=resp
;
}
}
rv
= method
.invoke(obj
, params
);
}else {
rv
= method
.invoke(obj
);
}
String viewName
= rv
.toString();
System
.out
.println("viewName:"+viewName
);
if (viewName
.startsWith("redirect:")) {
String redirectPath
= req
.getContextPath()+"/"+viewName
.substring("redirect:".length());
resp
.sendRedirect(redirectPath
);
}else {
req
.getRequestDispatcher("/WEB-INF/"+viewName
+".jsp").forward(req
,resp
);
}
} catch (Exception e
) {
e
.printStackTrace();
throw new ServletException(e
);
}
}
}
RequestMapping注解:
package core
.annotation
;
import java
.lang
.annotation
.ElementType
;
import java
.lang
.annotation
.Retention
;
import java
.lang
.annotation
.RetentionPolicy
;
import java
.lang
.annotation
.Target
;
@Retention(RetentionPolicy
.RUNTIME
)
@Target({ElementType
.METHOD
,ElementType
.TYPE
})
public @
interface RequestMapping {
public String
value();
}
HandlerMapping:
package core
.common
;
import java
.lang
.reflect
.Method
;
import java
.util
.HashMap
;
import java
.util
.List
;
import java
.util
.Map
;
import core
.annotation
.RequestMapping
;
public class HandlerMapping {
private Map
<String, Handler>map
= new HashMap<String, Handler>();
public Handler
getHandler(String path
) {
return map
.get(path
);
}
public void process(List
<Object> beans
) {
System
.out
.println("HandlerMapping.process()");
for (Object obj
: beans
) {
RequestMapping rm1
= obj
.getClass().getAnnotation(RequestMapping
.class);
String path1
= "";
if (rm1
!=null
) {
path1
= rm1
.value();
}
Method
[]methods
= obj
.getClass().getDeclaredMethods();
for (Method method
: methods
) {
RequestMapping rm
= method
.getAnnotation(RequestMapping
.class);
if (rm
!=null
) {
String path
= rm
.value();
System
.out
.println("path:"+path
);
Handler handler
= new Handler();
handler
.setObj(obj
);
handler
.setMethod(method
);
map
.put(path1
+path
, handler
);
}
}
}
System
.out
.println("map:"+map
);
}
}
Handler:
package core
.common
;
import java
.lang
.reflect
.Method
;
public class Handler {
private Object obj
;
private Method method
;
public Object
getObj() {
return obj
;
}
public void setObj(Object obj
) {
this.obj
= obj
;
}
public Method
getMethod() {
return method
;
}
public void setMethod(Method method
) {
this.method
= method
;
}
}
核心就是这四个类,其他自便。 web.xml文件供参考,注意: 1、设置配置文件名 2、设置load on startup 3、设置请求拦截路径
<?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">
<servlet>
<servlet-name>DispatcherSerlvet
</servlet-name>
<servlet-class>core.web.DispatcherSerlvet
</servlet-class>
<init-param>
<param-name>configLocation
</param-name>
<param-value>smartmvc.xml
</param-value>
</init-param>
<load-on-startup>1
</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherSerlvet
</servlet-name>
<url-pattern>*.do
</url-pattern>
</servlet-mapping>
</web-app>
另外还有很多Springmvc的功能可以实现,比如