简化springmvc控制器开发配置

.net mvc3中的控制器与url映射

之前用过微软的.net mvc 3,它的控制器是继承Controller类.然后控制器里有很多方法,其中作为action的方法返回值是ActionResult.
对应的url映射是这样:类AdminController中的Index方法——->/admin/index.这个映射关系无需加额外的注解之类的东西.当然如果你要控制只能GET或者POST方法访问,也是可以加注解的.(这里叫按java中的叫注解吧,.net中怎么叫,不清楚)

spring mvc中的控制器与url映射

springmvc这里只讲比较常用的RequestMappingHandlerMapping.
spring为了做到无侵入,控制器就是普通的pojo类,类名无所谓,但是至少要打上@Controller ,如果想指定url,要再加上@RequestMapping.
Action方法也是普通的java方法,连返回值都不做要求,但是必须要打上@RequestMapping,并且大部分时候需要手动指定@RequestMapping的value的值.
对应的url映射是这样:类AdminController中的index方法——->/{控制器的@RequestMapping信息/}{Action方法的@RequestMapping信息}

絮絮谈比较

易用性方面springmvc完败.

springmvc为了做到无侵入,真是不遗余力.
但是:

  1. 我们实际上会更换框架的情况微乎其微,所以侵入不侵入无所谓的,并且大部分情况下很难做到无侵入,能把功能搞定就不错了.
  2. 无侵入这种,对编程人员的识记要求更高,因为这种无侵入,使得IDE很难提供自动提示,纠错,生成功能.并且出问题不好定位(不了解原理,源码的情况下).

灵活性,功能强大程度方面,springmvc完胜

这点无需多说:spring出品,必属精品.

本次自定义配置目的

简化Controller的开发:1.注解简化;2.功能简化.
注解简化:能不加注解就不加注解,能不显式设置value就不显式设置.
功能简化就是:部分太灵活的功能尽量少用,这种功能对技术要求高,并且不容易规范.

最终效果描述:

  1. 如果Controller有@RequestMapping则使用该@RequestMapping的信息,如果没有,默认使用@RequestMapping(“{defaultController}“),其中的{defaultController}默认是[类名首字母小写,如以Controller后缀,则删掉后缀].
  2. 如果Method上有@RequestMapping则使用该@RequestMapping的信息,
  3. 如果Method上没有@RequestMapping但是Method为public,则默认使用@RequestMapping(“{methodName}“),其中的{methodName}就是方法名.
  4. 如果上述步骤得到的@RequestMapping不包含value值,则将其value替换成{methodName}方法名.

小故事:

当前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

你可能感兴趣的:(spring,mvc)