一:springmvc原理 springMvc执行流程: 1:项目启动初始化servlet容器:dispatcherServlet 2:dispatcherServlet在初始化init方法中争对配置文件中的包进行扫描并放置ioc容器中 3:初始化handlerMapping,获取url路径以及方法名称使用url作为key,method作为value保存在一个map集合中 4:当用户请求过来,会执行doService方法,通过doService方法获取请求路径,再通过此请求路径查找handlerMapping中是否存在对应的key-value,如果存在,则通过反射执行value方法 5:方法执行完成,将结果返回给dispatcherServlet 6:dispatcherServlet调用视图解析器,解析执行结果,底层通过重定向或者转发实现
二:实现
1:引入jar包 servlet-api 即可
2:web.xml配置
项目启动运行后,初始化当前配置的servlet容器
<servlet> <servlet-name>myDispatherServlet</servlet-name> <servlet-class>com.zbin.servlet.MyDispatherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> //拦截所有请求 <servlet-mapping> <servlet-name>myDispatherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
3:自定义注解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface MyController { }
@Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyRequestMapping { String value() default ""; }
4:自定义servlet,继承HttpServlet,重新init(),doGet(),doPost()方法
package com.zbin.servlet; import com.zbin.annotation.MyController; import com.zbin.annotation.MyRequestMapping; import com.zbin.util.ClassUtil; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 自定义是servlet * * @author zhangbin 2019年03月26日 * @version 1.0 * @since 1.0 2019年03月26日 */ public class MyDispatherServlet extends HttpServlet { //放置bean和class对象 ConcurrentHashMap<String, Object> springMvcBeans = new ConcurrentHashMap<>(); //放置url和class对象 ConcurrentHashMap<String, Object> urlBeans = new ConcurrentHashMap<>(); //放置url和方法名称 ConcurrentHashMap<String, String> urlMethod = new ConcurrentHashMap<>(); //重写init方法 @Override public void init() throws ServletException { //获取包下所有的类 List<Class<?>> classes = ClassUtil.getClasses("com.zbin.controller"); try { //初始化容器,获取所有的bean对象,保存到map集合中 getSpringMvcBeans(classes); } catch (Exception e) { e.printStackTrace(); } handlerMapping(); } /** * @return void * @Author zhangbin * @Description 初始化容器 * @Date 10:48 2019/3/26 * @Param [classes] **/ private void getSpringMvcBeans(List<Class<?>> classes) throws Exception { //遍历类 for (Class<?> aClass : classes) { //如果类不为空 if (aClass != null) { //判断类上是否存在自定义controller注解 MyController declaredAnnotation = aClass.getDeclaredAnnotation(MyController.class); if (declaredAnnotation != null) { //获取类名小写,保存的springMvcBeans中 String simpleName = aClass.getSimpleName(); String beanId = ClassUtil.toLowerCaseFirstOne(simpleName); //将bean和class实例保存在map集合中 springMvcBeans.put(beanId, ClassUtil.newInstance(aClass)); } } } } //初始化handlerMapping,将url地址与方法绑定 private void handlerMapping() { //遍历容器 for (Map.Entry<String, Object> springMvcBean : springMvcBeans.entrySet()) { //获取容器中的实例对象 Object value = springMvcBean.getValue(); Class<?> valueClass = value.getClass(); //判断类上是否存在自定义requestMapping注解 MyRequestMapping annotation = valueClass.getDeclaredAnnotation(MyRequestMapping.class); String basePath = ""; //类这一层的url地址 if (annotation != null) { basePath = annotation.value(); } //获取类中的方法 Method[] methods = valueClass.getMethods(); for (Method method : methods) { //判断方法上是否存在注解requestMapping MyRequestMapping declaredAnnotation = method.getDeclaredAnnotation(MyRequestMapping.class); if (declaredAnnotation != null) { String url = declaredAnnotation.value(); //得到handlerMapping的url String urlPath = basePath + url; //以url作为key,类的实例作为value保存到urlBeans中 urlBeans.put(urlPath, value); //以url作为key,对应方法名作为value保存到urlBeans中 urlMethod.put(urlPath, method.getName()); } } } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取请求的uri String requestURI = req.getRequestURI(); //根据请求的uri查找是否存在bean对象 Object o = urlBeans.get(requestURI); if (o == null) { //不存在的话可以抛出异常 resp.getWriter.println("出错了,路径错啦"); return; } //根据uri获取要执行的方法 String methodName = urlMethod.get(requestURI); if (methodName == null) { //不存在的话可以抛出异常 resp.getWriter.println("出错了,路径错啦"); return; } //方法的执行结果 Object result = result(o, methodName); //视图解析器(简单点,直接跳转到,是不是和springMvc配置文件很像??哈哈) String perfix = "/"; String after = ".jsp"; //转发到执行结果的页面 req.getRequestDispatcher(perfix + result + after).forward(req, resp); } //通过反射执行方法,返回Object private Object result(Object o, String methodName) { if (methodName != null) { Class<?> oClass = o.getClass(); try { Method method = oClass.getMethod(methodName); Object invoke = method.invoke(o); return invoke; } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } return null; } }