web.xml定义
<!-- spring bean 配置 -->
<context-param>
<param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener><!-- 启动时,扫描注解,把定义的url和相应的处理class数据缓存-->
<listener> <listener-class>com.util.listener.ContextLoaderListener</listener-class> </listener><!-- 过滤 字符编码过滤 -->
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>com.util.filter.CharCodeFilter</filter-class> <init-param> <param-name>characterEncoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping><!-- 请求派发servlet -->
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>com.util.dispatcher.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <servlet>1请求派发,web容器启动时扫描url注解
public class ContextLoaderListener implements ServletContextListener {
Logger log =LoggerFactory.getLogger(ContextLoaderListener.class); @Override public void contextDestroyed(ServletContextEvent arg0) { // TODO Auto-generated method stub log.info("context destroyed"); } @Override public void contextInitialized(ServletContextEvent arg0) { try { new ContextRootName().setContextRootName(arg0.getServletContext().getContextPath()); //注解扫描new AnnotationScanner().sannClasses();
//执行完controller后跳转试图的配置
new AnalysisView().AnalysisActionViewProperties();
} catch (ClassNotFoundException e) { log.error(e.getMessage()); } log.info("context inited"); }}2.1.1注解扫描
public class AnnotationScanner { private static List<String> packages = new ArrayList<String>(); static{ packages.add("com.wqf.action.impl"); } /** 要扫描的路径 */ private static List<String> paths = null; //TODO 扫描到需要的类方法需要更改 public void sannClasses() throws ClassNotFoundException{ String rootPath=getClass().getResource("/").getFile().toString(); paths = getPaths(); for(String path:paths){ File rootFile = new File(path); File [] files = rootFile.listFiles(); String packageName = path.replace(rootPath, "").replace('/', '.') + "."; for(File f: files) { String className = f.getName().substring(0, f.getName().indexOf(".class")); Class<?> clazz = Class.forName(packageName+className); parseClass(clazz); } } } public void parseClass(Class<?> clazz) { String url1= ""; String url2= ""; Annotation[] annotations = clazz.getAnnotations(); for(Annotation annotation:annotations){ if(annotation.annotationType().getSimpleName().equals("NameSpace")){ NameSpace nameSpace = (NameSpace)annotation; url1 = nameSpace.nameSpace(); } } Method[] methods = clazz.getDeclaredMethods(); for(Method method:methods){ Annotation[] methodannotations = method.getAnnotations(); for(Annotation annotation:methodannotations){ if(annotation.annotationType().getSimpleName().equals("RequestMapping")){ RequestMapping requestMapping = (RequestMapping)annotation; url2 = requestMapping.mapping(); MapClassMethodBean data = new MapClassMethodBean(); data.setBean(clazz); data.setM(method); String url = modifyUrl(url1 + url2); RequestData.setData(url, data); } } } } private static String modifyUrl(String url){ return url; } //TODO 拿到路径要改为从xml配置文件读取 private List<String> getPaths(){ String rootPath=getClass().getResource("/").getFile().toString(); List<String> stringList = new ArrayList<String>(); for(String scanPackage:packages){ String tmpPath = scanPackage.replace('.', '/'); stringList.add(rootPath + tmpPath); } return stringList; }}
2.1.2controller和跳转到jsp页面的配置
///firstAction/test.do = test.jsp
public class AnalysisView {
private String viewPath = "/resource/viewNamesProp"; public void AnalysisActionViewProperties() { Properties prop = new Properties(); FileInputStream in; try { String rootPath=getClass().getResource("/").getFile().toString(); in = new FileInputStream(rootPath + viewPath); prop.load(in); Iterator<String> it = prop.stringPropertyNames().iterator(); while (it.hasNext()) { String key=it.next(); ViewNameData.setData(key, prop.getProperty(key)); } in.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}3.核心派发servlet
public class DispatcherServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; Logger log = LoggerFactory.getLogger(DispatcherServlet.class); IBaseAction action = null; private String JSP = "jsp"; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // log.error("禁止get请求"); // return; doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /** * 判断请求类型分给不同的Class进行派发 */// String suffix = "";// if(actionName.indexOf(".") != -1){ // suffix = actionName.substring(actionName.indexOf(".") + 1,actionName.indexOf("?")== -1 ? actionName.length():actionName.indexOf("?") -1);// }// if(JSP.equals(suffix)){ // JspDispatcherServlet.getInstance().doPost(req, resp);// return;// } try {// 捕捉异常不抛到前台 String actionName = req.getServletPath(); actionName = actionName.indexOf("?") == -1 ? actionName :actionName.substring(0, actionName.indexOf("?")); /** 实际业务的class */ Class<?> clazz = null; /** 实际业务的方法 */ Method method = null; /** 前台传递的变量统一封装到context内 */ Context context = ContextFactory.createContext(req, resp); // ProxyHandler handler = new ProxyHandler(); String url = actionName.indexOf(".") == -1 ?actionName:actionName.substring(0, actionName.indexOf(".")); // 根据请求找到相应的action MapClassMethodBean classMethodBean = RequestData.getData(url); if (classMethodBean == null) { log.info("该URL 未配置"); sendRedirect(ViewNameData.getNotFoundPage(),req,resp); return; } clazz = classMethodBean.getBean(); method = classMethodBean.getM(); CglibProxyHandler cglibProxy = new CglibProxyHandler(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(cglibProxy); // Object target = clazz.cast(ac.getBean(clazz)); // handler.setTarget(target); // Object o = // Proxy.newProxyInstance(target.getClass().getClassLoader(), // target.getClass().getInterfaces(), // handler); Object o = enhancer.create(); Method[] omethods = o.getClass().getDeclaredMethods(); for (Method omethod : omethods) { if (omethod.getName().equals(method.getName())) { try { omethod.invoke(o, context); } catch (IllegalAccessException e) { log.warn(e.getMessage()); } catch (IllegalArgumentException e) { log.warn(e.getMessage()); } catch (InvocationTargetException e) { log.warn(e.getMessage()); } } } // 如果有对应的视图,跳转的相应的视图 String viewName = ViewNameData.getData(actionName); if (viewName != null) { sendRedirect(viewName,req,resp); } // 如果没有对应的视图 } catch (Exception e1) { log.error(e1.getMessage()); sendRedirect(ViewNameData.getErrorPage(),req,resp); } } private void sendRedirect(String fordardPage,HttpServletRequest req, HttpServletResponse resp) throws IOException{ String rootUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + req.getContextPath(); resp.sendRedirect(rootUrl + "/" + fordardPage); }}总结:web容器启动的时候通过listener扫描contrller所在包的注解,形成Map<String url, BeanMethod<Class controller, String method>>的数据,请求来的时候走DispatcherServlet,根据请求的url找到相应的controller和method处理请求。
如果请求后配置的有相应jsp页面跳转到相应的jsp页面。
一个简单实现,比较差。各位看官权当娱乐,工程代码后续再传,吐槽51job的审核!!!
工程代码地址:http://down.51cto.com/data/2327225