Spring MVC 与 web开发

转载:http://coderbee.net/index.php/java/20140719/959

项目组用了 Spring MVC 进行开发,觉得对里面的使用方式不是很满意,就想,如果是我来搭建开发环境,我会怎么做?下面就是我的想法,只关注于 MVC 的 View 层。

一、统一的响应格式

现在基本上都是用 ajax 来调用后台接口,拿到 json格式的数据再展示,有的人直接返回数据,却没有考虑异常的情况,我觉得返回的报文里必须包含表示可能的异常信息的数据和业务响应数据。我定义了下面这个类来表示报文格式:

/**
 * 统一的 HTTP 响应格式。<br/>
 * code 为 "ok" 表示业务调用成功,否则是失败的错误码,如果有多个则以逗号分隔。<br/>
 * data 是业务数据,如果失败了则是 null。
 *
 * @author http://coderbee.net
 *
 */
public class RespBody {
    public static final String OK_CODE = "ok";
    private final String code;
    private final Object data;

    private static final RespBody OK = new RespBody(OK_CODE, null);

    private RespBody(String code, Object data) {
        this.code = code;
        this.data = data;
    }

    public static RespBody ok() {
        return OK;
    }

    public static RespBody ok(Object data) {
        return new RespBody("ok", data);
    }

    public static RespBody error(String code) {
        return new RespBody(code, null);
    }

    public static RespBody error(String code, Object msg) {
        return new RespBody(code, msg);
    }

    public String getCode() {
        return code;
    }

    public Object getData() {
        return data;
    }
}

这个类提供了一些静态方法来快速构建响应报文,这也是很重要的一个设计:用静态工厂方法而不是构造函数。

这里的 code 不应该是直接的错误提示信息,应该只是简单的错误编码,这样不同的客户端都可以调用这个 API,然后再根据错误编码、客户端语言和自己的客户端特性选择合适的错误提示信息和提示方式。

二、统一的异常处理

很多人都不考虑异常的情况,导致异常栈直接抛到响应里,这是不友好也不安全的。统一的异常处理是必须的。

我定义了一个 BaseController

@Controller
public class BaseController {
    protected final static Logger logger = LoggerFactory
            .getLogger("controller");

    @ResponseBody
    @ExceptionHandler(Exception.class)
    public RespBody exceptionHandler(Exception ex) {
        return RespBody.error("exception", ex.getMessage());
    }
}

它的作用很简单,就是定义了一个统一的异常处理逻辑。Spring MVC对异常处理的逻辑很好,如果某个Controller类没有提供带 @ExceptionHandler 注解的方法,则会查找父类是否有这种方法,所以继承自这个 BaseController 的 Controller 都自动获得异常处理能力。

三、统一的参数校验

参数校验是必须的,而且必须放在服务器端来做,客户端的校验都是可以绕过的

Spring MVC 当然也支持参数校验,在 Spring MVC 的配置文件里加入 <mvc:annotation-driven /> 即可以开启注解校验。

但 Spring MVC 的参数校验有些局限:

  • 不支持对基本类型和 String 类型的参数进行校验,也就是只支持对 POJO 校验,这个非常不友好,如果一个接口只有很少的几个参数都必须定义一个 POJO 是很恼人的,要么就得手动校验,写一些 if 分支;
  • 每个POJO后面都得有一个 BindingResult 的参数,作为对 POJO 的校验结果。

而且在每个方法里都必须对 BindingResult 进行检测,来判断参数是否合法。

在 AOP 里进行参数校验

借助 Spring 对 AOP 的支持,我们可以在 AOP 里对请求的 Controller 的方法进行拦截,做参数校验,如果校验不合格,则直接返回(因为我们已经有了统一的响应格式)。

在 AOP 里,我们可以用 Hibernate-Validator 进行手动校验,而不是通过 Spring-MVC 进行校验,这样我们就不需要在每个 POJO 后面放一个 BindingResult 参数,且 Hibernate-Validator 支持对基本类型和 String 类型的参数进行校验。

下面的代码是在 Hibernate-Validator-4.2.0-Final、validation-api-1.0.0-GA 下测试的:

首先定义一个 BindingResultHandler 类,它的方法 validate 校验请求的 Controller 的方法的参数是否合格,如果合格则继续调用业务逻辑,否则返回错误提示。

public class BindingResultHandler {

    public Object validate(ProceedingJoinPoint pjp) throws Throwable {
        Object target = pjp.getTarget();

        MethodSignature joinPointObject = (MethodSignature) pjp.getSignature();
        Method method = joinPointObject.getMethod();

        MethodValidator validator = Validation
                .byProvider(HibernateValidator.class).configure()
                .buildValidatorFactory().getValidator()
                .unwrap(MethodValidator.class);

        Set<MethodConstraintViolation<Object>> violations = validator
                .validateAllParameters(target, method, pjp.getArgs(),
                        new Class[] {});

        if (!violations.isEmpty()) {
            StringBuilder sb = new StringBuilder(128);
            for (ConstraintViolation<Object> violation : violations) {
                sb.append(‘,‘).append(violation.getMessage());
            }
            return RespBody.error(sb.substring(1), "param validation failed .");
        }

        return pjp.proceed();
    }
}

AOP 配置:

<bean id="bindingResultHandler" class="net.coderbee.demo.controller.validation.BindingResultHandler" />
<aop:config>
    <aop:aspect id="aspectBindingResult" ref="bindingResultHandler">
        <aop:pointcut id="bindingResultHandlerPointcut"
            expression="execution(public * net.coderbee.demo.controller..*Controller.*(..))" />

        <aop:around method="validate" pointcut-ref="bindingResultHandlerPointcut" />
    </aop:aspect>
</aop:config>

这样在 Controller 里就只需做注解不能完成的校验了。

@Controller
public class UserController extends BaseController {
    @ResponseBody
    @RequestMapping(value = "/test/valids")
    public RespBody valids(@Valid User user, @Valid Address address) {

        return RespBody.ok(user);
    }
}

这样的代码会简洁很多。

时间: 2024-11-03 21:06:58

Spring MVC 与 web开发的相关文章

Spring boot 基于Spring MVC的Web应用和REST服务开发

Spring Boot利用JavaConfig配置模式以及"约定优于配置"理念,极大简化了基于Spring MVC的Web应用和REST服务开发. Servlet: 1 package org.windwant.spring.servlet; 2 3 import javax.servlet.Servlet; 4 import javax.servlet.ServletConfig; 5 import javax.servlet.ServletException; 6 import j

基于Spring MVC的Web应用开发(三) - Resources

基于Spring MVC的Web应用开发(3) - Resources 上一篇介绍了在基于Spring MVC的Web项目中加入日志,本文介绍Spring MVC如何处理资源文件. 注意到本项目的web.xml配置的DispatcherServlet对应的url-pattern为"/",即所有的URL请求都会经过 Spring MVC的处理.实际的Web项目有大量的资源文件,如javascript文件,css文件,png,jpg等图片文件,甚至是Flash等等,我们没有 必要对这些静态

spring mvc构建WEB应用程序入门例子

在使用spring mvc 构建web应用程序之前,需要了解spring mvc 的请求过程是怎样的,然后记录下如何搭建一个超简单的spring mvc例子. 1) spring mvc的请求经历 请求由DispatcherServlet分配给控制器(根据处理器映射),在控制器完成处理后,请求会被发送到一个视图(根据viewController解析逻辑视图) 来呈现输出结果. 整理成下图所示: 2)搭建一个简单的spring mvc例子 ①创建一个maven工程,其中pom中要有spring相关

使用Spring MVC搭建WEB应用框架-完成案例

陈科肇-转载请注明出处,http://blog.csdn.net/u013474104/article/details/43707459 ============ 1.简介 首先Spring MVC是基于三个层面来开发的,那三个层面呢? M(model) - 模型层,控制器完成逻辑处理后,通常会产生一些信息,而这些信息需要返回给用户并在浏览器上显示的,我们把这些信息称为模型: V(view) - 视图层,我们使用JSP作为视图层,通过视图能使这些模型数据渲染输出,并通过这个输出响应的对你传递给客

Spring mvc注解式开发入门

java类 package com.cloud.po; import Java.util.Date; public class Items { private Integer id; private String name; private Float price; private String pic; private Date createtime; private String detail; public Integer getId() { returnid; } public void

Spring + Spring MVC + Hibernate项目开发集成(注解)

在自己从事的项目中都是使用xml配置的方式来进行的,随着项目的越来越大,会发现配置文件会相当的庞大,这个不利于项目的进行和后期的维护.于是考虑使用注解的方式来进行项目的开发,前些日子就抽空学习了一下.在网上也查询了很多使用注解来搭建开发框架的文章,但是有一个问题就是,使用更新的软件版本会出错.这里我将使用最新的Spring,Hibernate来进行框架的搭建,经过测试,顺利运行.分享旨在与大家一起分享学习,共同进步,有不足之处,望不吝赐教,谢谢! 本项目使用maven构建,采用Spring +

用Spring MVC创建Web应用范例,轻松入门

本文通过一个浅显易懂的范例介绍Spring MVC的框架和以及运用方法.本文的参考书籍是<Tomcat与Java Web开发技术详解>第三版,作者:孙卫琴.本文所用的软件版本为:Window10,JDK10,Tomcat9.本文所涉及的源代码的下载网址为:http://www.javathinker.net/javaweb/mvc-app.rar 为了把Spring MVC运用到Web应用中,首先需要下载与操作系统对应的Spring软件包,下载地址为https://repo.spring.io

Spring Boot 整合 Web 开发

这一节我们主要学习如何整合 Web 相关技术: Servlet Filter Listener 访问静态资源 文件上传 文件下载 Web三大基本组件分别是:Servlet,Listener,Filter.正常来说一旦我们用了框架,这三个基本就用不上了,Servlet 被 Controller 代替,Filter 被拦截器代替.但是可能在一些特殊的场景下不得不使用这三个基本组件时,Spring Boot 中要如何去引用呢?下面我们来一起学习一下. Spring Boot 集成了 Servlet 容

Spring Boot 05 —— web开发案例

Spring Boot 的一些坑 https://www.jianshu.com/p/3494c84b4be3 国际化: 1)设置首页: 方法1:在controller添加一个请求 @RequestMapping({"/","index.html"}) public String index(){ return "index.html"; } 方法2:设置配置文件  :WebMvcConfigurer  的  addViewControllers