对于简单的小项目,使用非框架的MVC方式开发是比较优先的灵活的选择,生产环境由于对合作开发、项目维护、升级有着较高的要求因此需要引入框架。在开发中,随着项目的增加,大量的Servlet引入导致项目变得难以维护,因此有了这篇文章,是我对Servlet的一个简单封装,目的是
减轻代码间的耦合
减少web.xml的配置
加深对MVC框架的理解
写到最后发现其实就是Struts1的原理。废话不多说,进入正文讲解。
/**
* tomcat销毁的时候执行
*/
public void contextDestroyed(ServletContextEvent servletContextEvent) {
//回收所有映射
servletContextEvent.getServletContext().setAttribute("mappings", null);
}
/**
* tomcat启动时候执行
*/
public void contextInitialized(ServletContextEvent servletContextEvent) {
Map<String, String> map = new HashMap<>();
map.put("userAction", "com.snowalker.action.UserAction");
//添加所有映射
servletContextEvent.getServletContext().setAttribute("mappings", map);
}
此处,在上下文初始化方法中map.put("userAction", "com.snowalker.action.UserAction");表示用户自定义的action类的注册,并放入Application域中。
private ServletContext servletContext;
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException {
/**
* 1、从 application域中获取map
*/
HttpServletRequest request = (HttpServletRequest)arg0;
HttpServletResponse response = (HttpServletResponse)arg1;
Map<String, String> map = (HashMap<String, String>)this.servletContext.getAttribute("mappings");
/**
* 2、获取浏览器中的url,把url解析出来
* http://localhost:8080/itheima09_servlet_super/userAction.action
* ---->userAction
*/
//mapping = userAction
String mapping = ServletUtils.parse(request.getRequestURI());
String value = map.get(mapping); //value就是action的类的全名
try {
Class class1 = Class.forName(value); //获取到对应类的Class对象
Method method = class1.getMethod("execute", HttpServletRequest.class,HttpServletResponse.class);
//调用了action中的方法
String jspName = (String)method.invoke(class1.newInstance(), request,response);
request.getRequestDispatcher(jspName).forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
public void init(FilterConfig fConfig) throws ServletException {
//初始化时候加载servletContext
servletContext = fConfig.getServletContext();
}
注意:这里需要获取Application也就是servletContext对象,实验中通过HttpServletRequest获取不到,因此通过在Filter初始化时执行的生命周期方法init中的config中获取到应用上下文。
public static String parse(String url) {
String[] array = url.split("/");
//截取通过/分隔的字符串数组的最后一个元素从0到.之前的部分子字符串
String mapping = array[array.length -1].substring(0, array[array.length-1].indexOf(".")) ;
return mapping;
}
public class UserAction {
public String execute(HttpServletRequest request,HttpServletResponse response){
return "index.jsp";
}
}
<listener>
<description>监听器</description>
<listener-class>com.snowalker.servlet.listener.ServletListener</listener-class>
</listener>
<filter>
<description>过滤器</description>
<display-name>DispacheFilter</display-name>
<filter-name>DispacheFilter</filter-name>
<filter-class>com.snowalker.servlet.filter.DispacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>DispacheFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
运行项目访问:
http://localhost:8080/itheima09_servlet_super/userAction.action
显示出index.jsp的内容
到这里,我们完成了一个简单的Servlet的封装,较少了大量Servlet的定义,web.xml的体积大大减小。
项目中大量使用了Java反射技术,通过动态方法调用的方式进行业务逻辑的执行。
通过本项目模拟了一个简单MVC框架的原理,加深了对于复杂框架原理的理解。