一个简易的基于annotation的web MVC框架的实现

1、导入jar包
-- webmvc.jar
-- asm.jar

2、配置核心servlet
	<servlet>
		<servlet-name>WebServlet</servlet-name>
		<servlet-class>
			com.cwq.webmvc.core.servlet.DispatcherServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
		<init-param>
			<param-name>handler-scan</param-name>
			<param-value>com.xyz,com.abc</param-value>	<!-- 配置包扫描列表,多个包用逗号隔开 -->
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>WebServlet</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>


3、handler的定义
handler可以是一个普通的POJO,通过定义一系列的注解使其具备某些功能。

Context Path: /web
Servlet Mapping: *.do

 示例1:

@RequestMapping("/Order/.*")	
public class OrderHandler {	
	
	@RequestMapping(param = "load")
	@ForwardUrl("/showOrder.ftl")
	public void method1(int uid)		// RequestURL: /web/Order/m1.do?uid=2&action=load
	{		
		// do something...
	}	

	@RequestMapping(param = "commond=method2")
	@ForwardUrl("/showOrder.ftl")
	public void method2(String name)	// RequestURL: /web/Order/m1.do?name=张三&commond=method2
	{		
		// do something...
	}
}


 示例2:

@RequestMapping("/User/.*")
@ForwardUrl("/showUser.ftl")
public class UserHandler {

	public void save(User user)		// RequestURL: /web/User/save.do?id=2&name=张三
	{		
		// do something...
	}
	
	public void load(int id)		// RequestURL: /web/User/load/2.do
	{		
		// do something...
	}	
}


 示例3:

@WebHandler
public class ProductHandler {	

	@RequestMapping("/Product/save")
	@ForwardUrl("/showProduct.ftl")
	public void save(Product product)	// RequestURL: /web/Product/save.do?pid=2&pname=产品1
	{		
		// do something...
	}

	@RequestMapping("/Product/load")
	@ForwardUrl("/showProduct.ftl")
	public void load(int pid)		// RequestURL: /web/Product/load.do?pid=2
	{		
		// do something...
	}	
}



注解使用详细说明:
* @RequestMapping:定义在方法级别或类级别
  *  value: 定义要绑定到该类或方法的url,该url不需要加上ContextPath和ServletMapping。
  *   param: 定义形式key=value,只有request中有指定的值才满足匹配,如果未指定key,则默认为action,如 param = "save" 等价于 param = "action=save",类似struts

中的DispatchAction。
  *   method: 定义请求类型的绑定,如 method=RequestMethod.GET,则限定为只有GET请求方式才匹配。
* @ForwardUrl:定义在方法级别或类级别
  *   value: 定义需跳转的url
* @HandlerInitialize:标识注解,定义在方法级别,标识该方法为handler的初始化方法,在handler中每次请求处理之前都会先执行该方法。
* @HandlerDispose:标识注解,定义在方法级别,在handler中每次请求处理之后都会执行该方法。
* @MethodMapping:定义在方法级别,用于改变方法的绑定名字
  *   value:默认是以方法名匹配,如 @MethodMapping("newMethod") 将使用newMethod去匹配,而非方法名
* @ModelAttribute:定义在参数级别,定义该参数的值将从ModelMap中获取
  *   value:定义要获取值的key,如果ModelMap没有指定key对应的值,将抛出异常
* @ParameterConverter:标识注解,定义在方法级别,定义该方法为
* @RequestParam:定义在参数级别,改变参数的绑定名字,
  *   value:默认是以参数名绑定,如 @RequestParam("newParam") 将使用newParam去匹配,而非参数名
* @SessionAttributes:定义在类级别,指定ModelMap中的哪些值存储在session中
  *   value:定义定式{"key1","key2"...}
* @WebHandler:标识注解,定义在类级别,标识该类为request handler
* @ReturnKey:定义在方法级别,默认情况下,handler请求处理方法的返回值以'data'为key存储在request中,该注解用于自定义key值
  *   value:指定返回值新的key值

注意事项:
* 1、尽量不要在一个handler中同时使用基于annotation和REST两种风格的映射,最佳实践是在类级别统一使用@RequestMapping进行url映射,然后在方法级别通过param属性进行进一步分流。

* 2、尽量将绑定的url差异化定义的大一些,避免url出现包含关系,目前出现包含关系的处理方式是:在匹配的前提下,URL的length最大,即为最匹配的。

* 3、对于@RequestMapping的定义,如果出现类级别和类级别、类级别和方法级别、方法级别和方法级别的冲突,均会在servlet初始化时抛出异常。
  * 冲突实例:
    * 方法级:A、@RequestMapping(param = "method2")
    * 方法级:B、@RequestMapping(param = "action=method2")

  * 不冲突实例:
    * 类级:A、@RequestMapping("/order/Aorder", method = RequestMethod.GET)
    * 类级:A、@RequestMapping("/order/Aorder")

    * 类级:A、@RequestMapping("/order/Border")
    * 方法级:A、@RequestMapping("/order/Border", method = RequestMethod.POST)
  但不推荐这样做。

你可能感兴趣的:(mvc,Web,框架,servlet,REST)