• 理解并手写Spring MVC框架


    一、前言

    Spring框架是大多Java程序员的必修课程,而SpringMVC是里面的重头戏,它大大的简化了Servlet的繁琐操作,让开发人员得以用更多的时间去处理业务。

    SpringMVC是一款经典的三层架构模式,M为Model(模型),V为View(视图),C为Controlle(控制器)。MVC是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

    二、SpringMVC流程

    流程简述:

    (1)用户通过浏览器或其他途径发起请求。

    (2)请求经过前端控制器DispatcherServlet,并根据请求的URI匹配到对应的处理映射器。

    (3)处理映射器返回HandlerExecutionChain实体给DispatcherServlet,内部封装了拦截器HandlerInterceptor、Object类型的具体处理器handler。

    (4)系统启动时,初始化了HandlerAdapter的List的集合,此步骤循环List集合,调用HandlerAdapter的support方法,找到handler支持的HandlerAdapter处理适配器。

    (5)由HandlerAdapter处理参数并调用处理器的方法。

    (6)返回结果是ModelAndView,即视图。其内部封装了view、model、status。

    (7)将处理得到的ModelAndView返回给DispatcherServlet。

    (8)将ModelAndView交由专业的视图解析器进行解析,得到页面位置。

    (9)返回结果给DispatcherServlet。

    (10)将数据渲染到页面。

    (11)响应请求。

    源码核心部分概览

    protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }
    
    • initMultipartResolver(context)

    初始化文件上传解析功能,将普通HttpServletRequest包装成MutipartHttpServletRequest,此类可通过getFile获取到文件集合。

    • initLocaleResolver(context)

    初始化与当地区域有关的设置,如视图解析器与国际化资源的配置。

    • initThemeResolver(context)

    初始化主题解析,如消息国际话得配置,每个主题对应 一个properties文件。

    • initHandlerMappings(context)

    初始化HandlerMappings,用来获取对应的handler与interceptor。

    • initHandlerAdapters(context)

    初始化处理适配器,用来执行具体方法。

    • initHandlerExceptionResolvers(context)

    对异常情况进行处理。

    • initRequestToViewNameTranslator(context)

    从请求中获取视图名称。

    • initViewResolvers(context)

    初始化视图解析器,将ModelAndView渲染成页面。

    • initFlashMapManager(context)

    主要用处在于传递重定向参数。

    三、手写Spring MVC

    项目目录

    源码地址:

    https://github.com/hanguilin/custom-springmvc

    环境配置:

    maven项目中引入Servlet需要的jar包

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
        <scope>provided</scope>
    </dependency>
    

    其他jar包(本人写代码用到的一些包)

            <dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-api</artifactId>
    			<version>1.7.25</version>
    		</dependency>
    		<dependency>
    			<groupId>ch.qos.logback</groupId>
    			<artifactId>logback-classic</artifactId>
    			<version>1.2.3</version>
    		</dependency>
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-simple</artifactId>
    			<version>1.7.25</version>
    		</dependency>
    		<dependency>
    			<groupId>log4j</groupId>
    			<artifactId>log4j</artifactId>
    			<version>1.2.17</version>
    		</dependency>
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-log4j12</artifactId>
    			<version>1.7.21</version>
    		</dependency>
    		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-lang3</artifactId>
    			<version>3.4</version>
    		</dependency>
    

    注解类:

    建立SpringMVC中常用注解@Controller、@RequstMapping、@Autowired、@Qualifier、@Service、@RequestParam的替代注解。区别为在自己的注解中给名字添加了Custom前缀。各个注解的区别在于注解地方,如类、方法、字段上不同。

    CustomController.java

    package com.hgl.mvc.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 控制层注解
     * @author guilin
     *
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.TYPE)
    public @interface CustomController {
    
    	String value() default "";
    }
    
    

    CustomRequestMapping.java

    package com.hgl.mvc.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 请求路径注解
     * @author guilin
     *
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Target({ElementType.TYPE, ElementType.METHOD})
    public @interface CustomRequestMapping {
    
    	String value();
    }
    
    

    CustomAutowired.java

    package com.hgl.mvc.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 自动注入
     * @author guilin
     *
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    public @interface CustomAutowired {
    
    	String value() default "";
    }
    
    

    CustomQualifer.java

    package com.hgl.mvc.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 按名称自动注入
     * @author guilin
     *
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    public @interface CustomQualifer {
    
    	String value();
    }
    
    

    image.gif

    CustomService.java

    package com.hgl.mvc.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 业务层注解
     * @author guilin
     *
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.TYPE)
    public @interface CustomService {
    
    	String value() default "";
    }
    
    

    CustomRequestParam.java

    package com.hgl.mvc.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 参数注解
     * @author guilin
     *
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.PARAMETER)
    public @interface CustomRequestParam {
    
    	String value() default "";
    }
    
    

    配置文件

    在classpath下建立spring-mvc.properties,指定扫描包路径

    spring.scanner.base.package=com.hgl
    

    核心配置类

    SpringMVC核心配置类DispatcherServlet.java,替代类为CustomDispatcherServlet.java

    package com.hgl.mvc.servlet;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.lang3.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.hgl.mvc.annotation.CustomController;
    import com.hgl.mvc.annotation.CustomQualifer;
    import com.hgl.mvc.annotation.CustomRequestMapping;
    import com.hgl.mvc.annotation.CustomService;
    import com.hgl.mvc.resolver.ArgumentResolver;
    
    public class CustomDispatcherServlet extends HttpServlet{
    
    	private static final Logger LOGGER = LoggerFactory.getLogger(CustomDispatcherServlet.class);
    
    	private static final long serialVersionUID = 1L;
    
    	private Properties contextConfig = new Properties();
    
    	// 所有扫描类
    	private List<String> classes = new ArrayList<String>();
    
    	// 存放bean的容器ioc
    	private Map<String, Object> context = new HashMap<String, Object>();
    
    	// 存放参数解析器
    	private Map<String, ArgumentResolver> argumentResolverMap = new HashMap<String, ArgumentResolver>();
    
    	// 根据请求url找到具体的处理器
    	private List<CustomHandlerMapping> handlerMapping = new ArrayList<CustomHandlerMapping>();
    
    	private List<CustomHandlerAdapter> handlerAdapter = new ArrayList<CustomHandlerAdapter>();
    
    	public CustomDispatcherServlet() {
    		LOGGER.info("CustomDispatcherServlet()...");
    	}
    
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		// 加载配置文件
    		initConfig(config.getInitParameter("spring-mvc"));
    		// 扫描类
    		initBaseScanPackage(contextConfig.getProperty("spring.scanner.base.package"));
    		// 生成bean实例,注入ioc
    		initContext();
    		// 初始化参数解析器
    		initArgumentResolver();
    		// 为controller层中service对象注入实例
    		initInstance();
    		// 建立URI与处理器的映射
    		initHandlerMapping();
    		// 处理器适配器
    		initHandlerAdapter();
    	}
    
    	private void initConfig(String initParameter) {
    		InputStream in = this.getClass().getClassLoader().getResourceAsStream(initParameter);
    		try {
    			contextConfig.load(in);
    		} catch (IOException e) {
    			LOGGER.error(e.getMessage(), e);
    		} finally {
    			if(in != null) {
    				try {
    					in.close();
    				} catch (IOException e) {
    					LOGGER.error(e.getMessage(), e);
    				}
    			}
    		}
    	}
    
    	private void initBaseScanPackage(String basePackage) {
    		URL resource = this.getClass().getClassLoader().getResource("/" + basePackage.replaceAll("\.", "/"));
    		String packagePath = resource.getFile();
    		File packageFile = new File(packagePath);
    		String[] listFiles = packageFile.list();
    		for (String filepPath : listFiles) {
    			File file = new File(packagePath + filepPath);
    			if(file.isDirectory()) {
    				initBaseScanPackage(basePackage + "." + filepPath);
    			}else {
    				classes.add(basePackage + "." + file.getName());
    			}
    		}
    	}
    
    	private void initContext() {
    		if(classes.isEmpty()) {
    			LOGGER.error("do scan failed.");
    			return;
    		}
    		for (String className : classes) {
    			String classPath = className.substring(0, className.lastIndexOf(".class"));
    			try {
    				Class<?> clazz = Class.forName(classPath);
    				String simpleName = clazz.getSimpleName();
    				if(clazz.isAnnotationPresent(CustomController.class)) {
    					CustomController controller = clazz.getAnnotation(CustomController.class);
    					String key = controller.value();
    					if(StringUtils.isBlank(key)) {
    						key = toLowerCaseFirstOne(simpleName);
    					}
    					Object instance = clazz.newInstance();
    					context.put(key, instance);
    				} else if(clazz.isAnnotationPresent(CustomService.class)) {
    					CustomService service = clazz.getAnnotation(CustomService.class);
    					String key = service.value();
    					if(StringUtils.isBlank(key)) {
    						key = toLowerCaseFirstOne(simpleName);
    					}
    					Object instance = clazz.newInstance();
    					context.put(key, instance);
    				} else {
    					continue;
    				}
    			} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
    				LOGGER.error(e.getMessage(), e);
    			}
    		}
    	}
    
    	private void initArgumentResolver() {
    		if(context.isEmpty()) {
    			return;
    		}
    		for(Map.Entry<String, Object> entry : context.entrySet()) {
    			Object bean = entry.getValue();
    			// 判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口
    			if(ArgumentResolver.class.isAssignableFrom(bean.getClass())) {
    				argumentResolverMap.put(entry.getKey(), (ArgumentResolver) bean);
    			}
    		}
    	}
    
    	private void initInstance() {
    		if(context.isEmpty()) {
    			LOGGER.error("no bean is instanced.");
    			return;
    		}
    		for(Map.Entry<String, Object> entry : context.entrySet()) {
    			Object bean = entry.getValue();
    			Class<? extends Object> clazz = bean.getClass();
    			if(clazz.isAnnotationPresent(CustomController.class)) {
    				Field[] declaredFields = clazz.getDeclaredFields();
    				for (Field field : declaredFields) {
    					if(field.isAnnotationPresent(CustomQualifer.class)) {
    						CustomQualifer qualifer = field.getAnnotation(CustomQualifer.class);
    						String beanName = qualifer.value();
    						Object value = context.get(beanName);
    						try {
    							if(!field.isAccessible()) {
    								field.setAccessible(true);
    							}
    							field.set(bean, value);
    						} catch (IllegalArgumentException | IllegalAccessException e) {
    							LOGGER.error(e.getMessage(), e);
    						}
    					}
    				}
    			}
    		}
    	}
    
    	private void initHandlerMapping() {
    		if(context.isEmpty()) {
    			LOGGER.error("no bean is instanced.");
    			return;
    		}
    		for(Map.Entry<String, Object> entry : context.entrySet()) {
    			Object bean = entry.getValue();
    			Class<? extends Object> clazz = bean.getClass();
    			if(clazz.isAnnotationPresent(CustomController.class)) {
    				String classRequestMappingVal = "";
    				if(clazz.isAnnotationPresent(CustomRequestMapping.class)) {
    					CustomRequestMapping classRequestMapping = clazz.getAnnotation(CustomRequestMapping.class);
    					classRequestMappingVal = classRequestMapping.value();
    				}
    				Method[] declaredMethods = clazz.getDeclaredMethods();
    				List<String> uris = new ArrayList<String>();
    				for (Method method : declaredMethods) {
    					String methodRequestMappingVal = "";
    					if(method.isAnnotationPresent(CustomRequestMapping.class)) {
    						CustomRequestMapping methodRequestMapping = method.getAnnotation(CustomRequestMapping.class);
    						methodRequestMappingVal = classRequestMappingVal + methodRequestMapping.value();
    					}
    					if(StringUtils.isNotBlank(methodRequestMappingVal)) {
    						if(uris.contains(methodRequestMappingVal)) {
    							throw new RuntimeException("Duplicate mapping for " + methodRequestMappingVal);
    						}
    						handlerMapping.add(new CustomHandlerMapping(bean, method, Pattern.compile(methodRequestMappingVal)));
    						uris.add(methodRequestMappingVal);
    					}
    				}
    				uris = null;
    			}
    		}
    	}
    
    	private void initHandlerAdapter() {
    		if(context.isEmpty()) {
    			LOGGER.error("no bean is instanced.");
    			return;
    		}
    		for(Map.Entry<String, Object> entry : context.entrySet()) {
    			Object bean = entry.getValue();
    			// 判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口
    			if(CustomHandlerAdapter.class.isAssignableFrom(bean.getClass())) {
    				handlerAdapter.add((CustomHandlerAdapter) bean);
    			}
    		}
    	}
    
    	private String toLowerCaseFirstOne(String s){
    		if(Character.isLowerCase(s.charAt(0)))
    			return s;
    		else
    			return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    	}
    
    	@Override
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		doPost(request, response);
    	}
    
    	@Override
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		CustomHandlerMapping handler = getHandler(request);
    		CustomHandlerAdapter handlerAdapter = getHandlerAdapter(handler);
    		CustomModelAndView modelAndView = handlerAdapter.handle(request, response, handler, argumentResolverMap);
    	}
    
    	private CustomHandlerAdapter getHandlerAdapter(CustomHandlerMapping handler) {
    		for (CustomHandlerAdapter customHandlerAdapter : handlerAdapter) {
    			if(customHandlerAdapter.support(handler)) {
    				return customHandlerAdapter;
    			}
    		}
    		throw new RuntimeException("There is no handlerAdapter for " + handler);
    	}
    
    	private CustomHandlerMapping getHandler(HttpServletRequest request) {
    		String requestURI = request.getRequestURI();
    		String path = requestURI.replaceAll(request.getContextPath(), "");
    		for (CustomHandlerMapping handler : handlerMapping) {
    			Pattern pattern = handler.getPattern();
    			Matcher matcher = pattern.matcher(path);
    			if(matcher.matches()) {
    				return handler;
    			}
    		}
    		throw new RuntimeException("There is no mapping for " + path);
    	}
    
    }
    
    

    处理映射器

    CustomHandlerMapping.java

    package com.hgl.mvc.servlet;
    
    import java.lang.reflect.Method;
    import java.util.regex.Pattern;
    
    /**
     * 自定义handlerMapping
     * 
     * @author guilin
     *
     */
    public class CustomHandlerMapping{
    
    	/**
    	 * controller对应的bean
    	 */
    	private Object controller;
    
    	/**
    	 * 具体处理方法
    	 */
    	private Method method;
    
    	/**
    	 * 用来验证是否是当前url对应的处理方法
    	 */
    	private Pattern pattern;
    
    	public CustomHandlerMapping(Object controller, Method method, Pattern pattern) {
    		super();
    		this.controller = controller;
    		this.method = method;
    		this.pattern = pattern;
    	}
    
    	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;
    	}
    }
    

    处理适配器

    CustomHandlerAdapter.java,作为接口,由实现类实现。

    package com.hgl.mvc.servlet;
    
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.hgl.mvc.resolver.ArgumentResolver;
    
    /**
     * @author guilin
     * 自定义适配器
     *
     */
    public interface CustomHandlerAdapter {
    
    	/**
    	 * 是否支持处理
    	 * 是则调用本类handle方法
    	 * 
    	 * @param handler 处理器
    	 * @return boolean
    	 */
    	public boolean support(Object handler);
    
    	/**
    	 * 具体处理方法
    	 * 
    	 * @param request
    	 * @param response
    	 * @param handler
    	 * @param argumentResolverMap
    	 * @return CustomModelAndView
    	 */
    	public CustomModelAndView handle(HttpServletRequest request, HttpServletResponse response, CustomHandlerMapping handler,
    			Map<String, ArgumentResolver> argumentResolverMap);
    
    }
    
    

    实现类CustomSimpleHandlerAdapter.java

    package com.hgl.mvc.servlet;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.hgl.mvc.annotation.CustomService;
    import com.hgl.mvc.resolver.ArgumentResolver;
    
    /**
     * 对处理适配器的实现
     * 
     * @author guilin
     *
     */
    @CustomService("customSimpleHandlerAdapter")
    public class CustomSimpleHandlerAdapter implements CustomHandlerAdapter{
    
    	private static final Logger LOGGER = LoggerFactory.getLogger(CustomDispatcherServlet.class);
    
    	@Override
    	public CustomModelAndView handle(HttpServletRequest request, HttpServletResponse response, CustomHandlerMapping handler,
    			Map<String, ArgumentResolver> argumentResolverMap) {
    		Method method = handler.getMethod();
    		Object controller = handler.getController();
    		Class<?>[] parameterTypes = method.getParameterTypes();
    		Object[] args = new Object[parameterTypes.length];
    		for (int i = 0; i < parameterTypes.length; i++) {
    			Class<?> parameterClass = parameterTypes[i];
    			for (Map.Entry<String, ArgumentResolver> entry : argumentResolverMap.entrySet()) {
    				ArgumentResolver argumentResolver = entry.getValue();
    				if(argumentResolver.support(parameterClass, i, method)) {
    					Object resolver = argumentResolver.argumentResolver(request, response, parameterClass, i, method);
    					args[i] = resolver;
    					break;
    				}
    			}
    		}
    		try {
    			method.invoke(controller, args);
    		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
    			LOGGER.error(e.getMessage(), e);
    		}
    		return new CustomModelAndView();
    	}
    
    	@Override
    	public boolean support(Object handler) {
    		// 暂定实现为true
    		return true;
    	}
    
    }
    
    

    参数解析器

    ArgumentResolver.java,作为上层接口,具体由实现类实现。

    package com.hgl.mvc.resolver;
    
    import java.lang.reflect.Method;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 参数解析器
     * @author guilin
     *
     */
    public interface ArgumentResolver {
    
    	public boolean support(Class<?> type, int paramIndex, Method method);
    
    	public Object argumentResolver(HttpServletRequest request, HttpServletResponse response,
    			Class<?> type, int paramIndex, Method method);
    }
    
    

    HttpServletRequestArgumentResolver.java,用于解析HttpServletRequest参数

    package com.hgl.mvc.resolver;
    
    import java.lang.reflect.Method;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.hgl.mvc.annotation.CustomService;
    
    /**
     * HttpServletRequest参数解析器
     * @author guilin
     *
     */
    @CustomService("httpServletRequestArgumentResolver")
    public class HttpServletRequestArgumentResolver implements ArgumentResolver {
    
    	@Override
    	public boolean support(Class<?> type, int paramIndex, Method method) {
    		return ServletRequest.class.isAssignableFrom(type);
    	}
    
    	@Override
    	public Object argumentResolver(HttpServletRequest request, HttpServletResponse response, Class<?> type,
    			int paramIndex, Method method) {
    		return request;
    	}
    
    }
    
    

    HttpServletResponseArgumentResolver.java,用于解析HttpServletResponse参数

    package com.hgl.mvc.resolver;
    
    import java.lang.reflect.Method;
    
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.hgl.mvc.annotation.CustomService;
    
    /**
     * HttpServletResponse参数解析器
     * @author guilin
     *
     */
    @CustomService("httpServletResponseArgumentResolver")
    public class HttpServletResponseArgumentResolver implements ArgumentResolver {
    
    	@Override
    	public boolean support(Class<?> type, int paramIndex, Method method) {
    		return ServletResponse.class.isAssignableFrom(type);
    	}
    
    	@Override
    	public Object argumentResolver(HttpServletRequest request, HttpServletResponse response, Class<?> type,
    			int paramIndex, Method method) {
    		return response;
    	}
    
    }
    
    

    RequestParamArgumentResolver.java,用于解析CustomRequestParam定义的参数

    package com.hgl.mvc.resolver;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.hgl.mvc.annotation.CustomRequestParam;
    import com.hgl.mvc.annotation.CustomService;
    
    /**
     * RequestParam参数解析器
     * @author guilin
     *
     */
    @CustomService("requestParamArgumentResolver")
    public class RequestParamArgumentResolver implements ArgumentResolver {
    
    	@Override
    	public boolean support(Class<?> type, int paramIndex, Method method) {
    		Annotation[][] annotations = method.getParameterAnnotations();
    		Annotation[] currentField = annotations[paramIndex];
    		for (Annotation annotation : currentField) {
    			if(CustomRequestParam.class.isAssignableFrom(annotation.getClass())) {
    				return true;
    			}
    		}
    		return false;
    	}
    
    	@Override
    	public Object argumentResolver(HttpServletRequest request, HttpServletResponse response, Class<?> type,
    			int paramIndex, Method method) {
    		Annotation[][] annotations = method.getParameterAnnotations();
    		Annotation[] currentField = annotations[paramIndex];
    		for (Annotation annotation : currentField) {
    			if(CustomRequestParam.class.isAssignableFrom(annotation.getClass())) {
    				CustomRequestParam requestParam = (CustomRequestParam) annotation;
    				String parameterName = requestParam.value();
    				String parameterVal = request.getParameter(parameterName);
    				return parameterVal;
    			}
    		}
    		return null;
    	}
    
    }
    
    
  • 相关阅读:
    OPENGL ES2.0如何不使用glActiveTexture而显示多个图片
    OpenGL帧缓存对象(FBO:Frame Buffer Object)
    EGLImage与纹理
    Android下Opengl ES实现单屏幕双眼显示
    comet4j开发指南
    tmp
    Ubuntu16.04下编译android6.0源码
    ubuntu下配置安装conky
    Qt编程之QImage类小结
    Linux学习,在线版
  • 原文地址:https://www.cnblogs.com/yl-space/p/13507651.html
Copyright © 2020-2023  润新知