web路由的java简单实现思路

895 阅读2分钟

这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

1.web路径分析

https://juejin.cn/pins/recommended

协议://地址/端口/路由地址
                我们只关注这里就可以了
前面的容器处理了

2.路由思路

2.1定义注解
2.2系统初始化的时候扫描注解,解解析路由缓存起来
2.3接收请求的时候由自定义过滤器进行拦截
2.4解析请求的路径,并匹配缓存的路由,处理业务
2.5注意对于业务处理的action进行单例实例化
2.6目前这里这里处理方法还只是servlet的request,response只是个例子了解下流程

3.基本实现

3.1注解简单的定义

@Retention(RetentionPolicy.RUNTIME)
public @interface PathAnnotation {
    String path();//这里是路径
    String type();//这里是类型
}

3.2扫描注解,缓存路径

这里就是遍历读取class文件,找到注解为PathAnnotation的类
解析路径然后缓存起来

//路由对应的实体类
public class Route {
	/** 路径*/
	private String path;
	
	/** 执行方法*/
	private String method;

	/** 方法类型*/
	private String type;
	
	/** action控制类*/
	private Object action;
 } 
 
 /**
 * 扫描的class类,解析路径缓存起来routeList
 * @param path
 * @return
 * @throws IllegalAccessException
 * @throws InstantiationException
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public void addAllRoutes(Set<Class> actionClass) throws InstantiationException, IllegalAccessException {
if (null != actionClass) {
 for (Class cls : actionClass) {
	PathAnnotation pa = (PathAnnotation) cls.getAnnotation(PathAnnotation.class);
	String routPath = "";
	if (null != pa) {
	 routPath = pa.path();
	}
	Method[] methods = cls.getMethods();
	for (Method m : methods) {
	 pa = m.getAnnotation(PathAnnotation.class);
	 if (null == pa) {
	    continue;
	}
	routPath += "/" + pa.path();
	Route rt = new Route(routPath, m.getName(), pa.type(), BeanUtil.getBeanUtil().getObj(cls));
        logger.info("加载路由:" + rt.toString());
        routeList.add(rt);
      }
    }
   }
}

3.3路径匹配

/**
 * 这里是个匹配的路径内容
 * 这里的匹配路径所有的都根据/来的
 * @param rs
 * @param path
 * @return
 */
public static  Route findRoute(Routes rs,String path) {
	if(null==rs||rs.getRouteList().size()<1) {
		return null;
	}else {
		List<Route> allRoute=rs.getRouteList();
		//首先要把路径给格式化为标准的路径
               if(null==path) {
	          return null;
               }else {
                /**
                 * 1.这里首先要去掉开始的项目地址,然后把字符\转换为/
                 * 2.如何是/结尾的要去掉
                 * 3.开始的项目地址如何去掉
                 * 4.项目路径匹配返回正常的路由
                 */  
                String currentPath=path.trim().replace('\\', '/');
                if(currentPath.endsWith("/")) {
                   currentPath=currentPath.substring(0,currentPath.length()-1);
                }
                if(currentPath.startsWith("/")) {
                   currentPath=currentPath.substring(1,currentPath.length());	
                }

                for(Route rt:allRoute) {
                        if(rt.getPath().equals(currentPath)) {
                                return rt;
                        }
                }
               }
	      return null;
	}
}

4.效果测试

4.1指定过滤器配置

<filter>
	<filter-name>pingpang</filter-name>
	<filter-class>com.pingpang.core.Core</filter-class>
	<init-param>
	   <param-name>autoPackage</param-name>
           <!--这里是扫描的包路径-->
	   <param-value>com.pingpang.test</param-value>
     </init-param>
</filter>
<filter-mapping>
	<filter-name>pingpang</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

4.2测试action

//路由注解的测试
@PathAnnotation(path = "hello", type = "")
public class PingPangTest {

	@PathAnnotation(path = "test", type = "")
	public void helloWord(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
       	System.out.println("-----------");
       	request.getRequestDispatcher("/login.jsp").forward(request, response);
	 }
}

4.3效果图

image.png

image.png