写点什么

简单实现 springmvc 中的请求处理

用户头像
赵镇
关注
发布于: 2 小时前

自定义 MVC 框架中的一些元素

一些注解


@Documented@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface Controller {    String value () default "";}
@Documented@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface RequestMapping { String value () default "";}
@Documented@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface Service { String value () default "";}
@Documented@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface Autowired { String value () default "";}
复制代码


处理对象封装


public class Handler {
private Object controller;//Controller对应的类 private Method method;//执行业务的方法 private Pattern pattern;//uri private Map<String,Integer> paramIndexMapping;//参数和位置的映射
public Handler(Object controller, Method method, Pattern pattern) { this.controller = controller; this.method = method; this.pattern = pattern; this.paramIndexMapping = new HashMap<>(); }
public Object getController() { return controller; }
public void setController(Object controller) { this.controller = controller; }
public Method getMethod() { return method; }
public void setMethod(Method method) { this.method = method; }
public Pattern getPattern() { return pattern; }
public void setPattern(Pattern pattern) { this.pattern = pattern; }
public Map<String, Integer> getParamIndexMapping() { return paramIndexMapping; }
public void setParamIndexMapping(Map<String, Integer> paramIndexMapping) { this.paramIndexMapping = paramIndexMapping; }}
复制代码


自定义 DisptchServelet 处理代码


public class DispatchServelet extends HttpServlet {    private Properties properties = new Properties();    private List<String> classNames = new ArrayList<>();    private Map<String,Object> ioc =new HashMap<>();    private List<Handler> handlerMapping = new ArrayList<>();    @Override    public void init(ServletConfig config) throws ServletException {        //加载配置文件        String contextConfigLocation = config.getInitParameter("contextConfigLocation");        doLoadConfig(contextConfigLocation);        //扫描相关的类,扫描注解        doScan(properties.getProperty("scanPackage"));        //初始化bean,基于注解        doInstance();        //实现依赖注入        doAutoWired();        //实现处理器映射器,将url和method进行关联        initHandlerMapping();        System.out.println("mvc 初始化完成");            }    //执行的是方法和url方法映射    private void initHandlerMapping() {        if (ioc.isEmpty()){            return;        }        for (Map.Entry<String,Object> entry :ioc.entrySet()){            Class<?> aClass = entry.getValue().getClass();            if (!aClass.isAnnotationPresent(Controller.class)){                continue;            }            String baseUrl = "";            if (aClass.isAnnotationPresent(RequestMapping.class)){                RequestMapping requestMapping = aClass.getAnnotation(RequestMapping.class);                baseUrl=requestMapping.value();            }            Method[] methods= aClass.getMethods();            for (int i=0;i<methods.length;i++){                Method method = methods[i];                if (!method.isAnnotationPresent(RequestMapping.class)){                    continue;                }                RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);                String methodUrl = requestMapping.value();                String url = baseUrl+methodUrl;                Handler handler = new Handler(entry.getValue(),method, Pattern.compile(url));                Parameter[] parameters = method.getParameters();                for (int j=0;j<parameters.length;j++){                    Parameter parameter = parameters[j];                    if (parameter.getType().equals(HttpServletRequest.class)||parameter.getType().equals(HttpServletResponse.class)){                        handler.getParamIndexMapping().put(parameter.getType().getSimpleName(),j);                    }else {                        handler.getParamIndexMapping().put(parameter.getName(),j);                    }                }                //完成方法和url的映射关系                handlerMapping.add(handler);            }        }    }    //执行注入部分,同样是做的ioc的部分功能    private void doAutoWired() {        if (ioc.isEmpty()){            return;        }        for (Map.Entry<String,Object> entry :ioc.entrySet()){            Field[] declareFields = entry.getValue().getClass().getDeclaredFields();            for (int i=0;i<declareFields.length;i++){                Field declareField = declareFields[i];                if (!declareField.isAnnotationPresent(Autowired.class)){                    continue;                }                Autowired autowired = declareField.getAnnotation(Autowired.class);                String beanName = autowired.value();                if ("".equals(beanName.trim())){                    beanName=declareField.getType().getName();                }                declareField.setAccessible(true);                try {                    //直接将这个字段的值设置为ioc中已经示例化的类,                    // 即是完成了ioc中的实例化交给容器来管理的情况                    declareField.set(entry.getValue(),ioc.get(beanName));                } catch (IllegalAccessException e) {                    e.printStackTrace();                }            }
} }
//执行的是符合要求的类的初始化,实际上是实现的一部分ioc的功能 private void doInstance() { if (classNames.size()==0){ return; } try { for (int i=0;i<classNames.size();i++){ String className = classNames.get(i); Class<?> clazz = Class.forName(className); if (clazz.isAnnotationPresent(Controller.class)){ String simpleName = clazz.getSimpleName(); String lowerFirst = lowerFirst(simpleName); Object o = clazz.newInstance(); //因为controller无别名,所以简单设置成首字母小写就行 ioc.put(lowerFirst,o); }else if (clazz.isAnnotationPresent(Service.class)){ Service service = clazz.getAnnotation(Service.class); String beanName =service.value(); if (!"".equals(beanName.trim())){ ioc.put(beanName,clazz.newInstance()); }else { beanName = lowerFirst(clazz.getSimpleName()); ioc.put(beanName,clazz.newInstance()); }
Class<?>[] interfaces = clazz.getInterfaces(); for (int j=0;j<interfaces.length;j++){ Class<?> ainterface = interfaces[j]; System.out.println(ainterface.getName()); //将实现类和接口进行绑定 ioc.put(ainterface.getName(),clazz.newInstance()); } }else { continue; } } }catch (Exception e){ e.printStackTrace(); }
}

private String lowerFirst(String className){ char[] chars = className.toCharArray(); if ('A'<chars[0]&&chars[0]<'Z'){ chars[0]+=32; } return new String(chars); } private void doScan(String basePackage) { //获取到指定包下的所有类的类名 String scanPackagePath= Thread.currentThread().getContextClassLoader().getResource("").getPath()+basePackage.replaceAll("\\.","/"); File pack = new File(scanPackagePath); File [] files = pack.listFiles(); for (File file:files){ if (file.isDirectory()){ doScan(basePackage+"."+file.getName()); }else if (file.getName().endsWith(".class")){ String className = basePackage+"."+file.getName().replaceAll(".class",""); classNames.add(className); } } } //实现加载web.xml中配置的文件的路径 private void doLoadConfig(String contextConfigLocation) { InputStream inputStream =this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation); try { properties.load(inputStream); } catch (IOException e) { e.printStackTrace(); } }

@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Handler handler = getHander(req); if (handler==null){ resp.getWriter().write("404 not found"); return; } Class<?> [] parameterTypes = handler.getMethod().getParameterTypes(); Object[] paraValues = new Object[parameterTypes.length];
Map<String,String[]> parameterMap = req.getParameterMap(); for (Map.Entry<String,String[]> param:parameterMap.entrySet()){ String value = StringUtils.join(param.getValue(),","); if (!handler.getParamIndexMapping().containsKey(param.getKey())){ continue; } //对应实际参数的位置 Integer index = handler.getParamIndexMapping().get(param.getKey()); paraValues[index]=value;
} //对应上req,和resp参数的位置 int reqIndex = handler.getParamIndexMapping().get(HttpServletRequest.class.getSimpleName()); paraValues[reqIndex]=req; int respIndex = handler.getParamIndexMapping().get(HttpServletResponse.class.getSimpleName()); paraValues[respIndex]=resp;
try { //实际执行的是controller中的方法 handler.getMethod().invoke(handler.getController(),paraValues); System.out.println("执行controller方法成功"); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }
}
private Handler getHander(HttpServletRequest req) { if (handlerMapping.isEmpty()){ return null; } String url =req.getRequestURI(); for (Handler handler:handlerMapping){ Matcher matcher = handler.getPattern().matcher(url); if (!matcher.matches()){ continue; } return handler; } return null; }
}
复制代码


测试代码


public interface DemoService {
String getName(String name);}


@Service("demoService")public class DemoServiceImpl implements DemoService { @Override public String getName(String name) { return name; }}
@Controller@RequestMapping("/demo")public class DemoController { @Autowired private DemoService demoService; @RequestMapping("/query") public String query(HttpServletRequest req, HttpServletResponse resp,String name){ return demoService.getName(name); }}
复制代码


web.xml 配置


<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>mvc</servlet-name> <servlet-class>com.zhao.mvcframework.servelet.DispatchServelet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>mvc.properties</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping></web-app>
复制代码


mvc.properties 的配置


scanPackage=com.zhao.mvcdemo
复制代码


pom 文件的配置


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.zhao</groupId> <artifactId>mvc</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging>
<name>mvc Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.10</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/</path> </configuration>
</plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> <compilerArgs>-parameters</compilerArgs> </configuration> </plugin> </plugins> </build></project>
复制代码


测试时访问具体的 http://localhost:8080/demo/query?name=zhaozhen 无问题



代码地址为https://github.com/zhendiao/deme-code/tree/main/mvc

发布于: 2 小时前阅读数: 2
用户头像

赵镇

关注

还未添加个人签名 2017.12.20 加入

还未添加个人简介

评论

发布
暂无评论
简单实现springmvc中的请求处理