之前用过微软的.net mvc 3,它的控制器是继承Controller类.然后控制器里有很多方法,其中作为action的方法返回值是ActionResult.
对应的url映射是这样:类AdminController中的Index方法——->/admin/index.这个映射关系无需加额外的注解之类的东西.当然如果你要控制只能GET或者POST方法访问,也是可以加注解的.(这里叫按java中的叫注解吧,.net中怎么叫,不清楚)
springmvc这里只讲比较常用的RequestMappingHandlerMapping
.
spring为了做到无侵入,控制器就是普通的pojo类,类名无所谓,但是至少要打上@Controller ,如果想指定url,要再加上@RequestMapping.
Action方法也是普通的java方法,连返回值都不做要求,但是必须要打上@RequestMapping,并且大部分时候需要手动指定@RequestMapping的value的值.
对应的url映射是这样:类AdminController中的index方法——->/{控制器的@RequestMapping信息/}{Action方法的@RequestMapping信息}
springmvc为了做到无侵入,真是不遗余力.
但是:
这点无需多说:spring出品,必属精品.
简化Controller的开发:1.注解简化;2.功能简化.
注解简化:能不加注解就不加注解,能不显式设置value就不显式设置.
功能简化就是:部分太灵活的功能尽量少用,这种功能对技术要求高,并且不容易规范.
当前springmvc默认的行为是:如果Method上的@RequestMapping没有设置value值,则value值默认为空.这样的话这个方法就会成为该控制器的后备映射方法.
比如控制器为/admin/*,这意味着所有的/admin前缀都会进来,但如果找不到对应的映射,则都会被匹配到后备映射方法.
其实在springmvc的早期版本(貌似3.0之前),如果Method上的@RequestMapping没有设置value值,则会使用方法名作为替代.但是后来改掉了.改掉肯定是有原因的,当然是为了框架更灵活,强大.但是我其实蛮喜欢这种默认效果的,并且很多太灵活和强大的功能我也用不到.所以我就做了自定义的修改,并写了这篇文章.
最终效果:
/admin/index对应代码
@Controller
public class AdminController{
public String index(){
return "index";
}
}
/index对应代码
@Controller
@RequestMapping
public class AdminController{
public String index(){
return "index";
}
}
/admin/hello对应代码
@Controller
public class AdminController{
@RequestMapping("hello")
public String index(){
return "index";
}
}
使用自定义的HandlerMapping替换默认的RequestMappingHandlerMapping,替换方式在下一章节.自定义HandlerMapping的代码如下
import java.lang.annotation.Annotation;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* User: landy
* Date: 15/1/28
* Time: 下午5:58
*/
public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = null;
RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
if (methodAnnotation != null) {
if (methodAnnotation.value().length == 0) {
methodAnnotation = createReplaceAnnotation(method.getName(), methodAnnotation);
}
} else {
if (Modifier.isPublic(method.getModifiers())) {
methodAnnotation = createReplaceAnnotation(method.getName());
}
}
if (methodAnnotation != null) {
info = createRequestMappingInfo(methodAnnotation, null);
RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
if (typeAnnotation != null) {
info = createRequestMappingInfo(typeAnnotation, null).combine(info);
} else {
String simpleName = handlerType.getSimpleName();
if (simpleName.endsWith("Controller")) {
simpleName = simpleName.replace("Controller", "");
}
simpleName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);
info = createRequestMappingInfo(createReplaceAnnotation("/" + simpleName), null).combine(info);
}
}
return info;
}
private RequestMapping createReplaceAnnotation(final String name, final RequestMapping old) {
return new RequestMapping() {
@Override
public Class<? extends Annotation> annotationType() {
return old.getClass();
}
@Override
public String[] value() {
return new String[]{name};
}
@Override
public RequestMethod[] method() {
return old.method();
}
@Override
public String[] params() {
return old.params();
}
@Override
public String[] headers() {
return old.headers();
}
@Override
public String[] consumes() {
return old.consumes();
}
@Override
public String[] produces() {
return old.produces();
}
};
}
private RequestMapping createReplaceAnnotation(final String name) {
return new RequestMapping() {
@Override
public Class<? extends Annotation> annotationType() {
return RequestMapping.class;
}
@Override
public String[] value() {
return new String[]{name};
}
@Override
public RequestMethod[] method() {
return new RequestMethod[0];
}
@Override
public String[] params() {
return new String[0];
}
@Override
public String[] headers() {
return new String[0];
}
@Override
public String[] consumes() {
return new String[0];
}
@Override
public String[] produces() {
return new String[0];
}
};
}
}
基于xml配置的替换方式参考这个http://git.oschina.net/landyking/BlogCodeShow/tree/master/springmvc/custom_handlerMapping/xml-way