springboot中扩展ModelAndView实现asp.net core mvc的ActionResult效果

 最近在写spring boot项目,写起来感觉有点繁琐,为了简化spring boot中的Controller开发,对ModelAndView进行简单的扩展,实现net mvc中ActionResult的写法

asp.net core mvc中控制器中提供了IActionResult接口来返回Aciton结果,可以用来返回视图view或者json,当然也可以实现接口返回自定义结果,当时写EasyCMS的时候实现过一个HtmlResult用来返回模板渲染生成的HTML内容,在asp.net core mvc中开发非常简便,那么我们可以看下在asp.net core mvc中的写法

//返回视图
[HttpGet]
public IActionResult Index(){
     return View();
}

//返回json
[HttpGet]
public IActionResult GetJson(){
     return Json();
}

//返回字符串
[HttpGet]
public IActionResult GetJson(){
     return Content();
}

 

再来看下在spring boot中原始的写法是啥样子的

    //返回index页面
   @GetMapping("/index")
    public String index() {
        return "home/index";
    }

   //或者
    @GetMapping("/tesView")
    public ModelAndView tesView(){
        
        return new ModelAndView("/home/testView");
    }

    //返回json
    @GetMapping("/getJson")
    @ResponseBody
    public Hashtable<String,Object> getJson(){
        Hashtable<String,Object> data=new Hashtable<>();
        data.put("status",true);
        data.put("message","message from json");
           return map;
    }

可以看到spring boot默认的写法并不是很简化,比如使用String返回视图view的时候必须指定视图路径,返回json必须添加@ResponseBody注解,

而使用ModelAndView 当视图路径和路由一致时是可以简化不写视图路径的 ,所以我们可以对ModelAndView来进一步扩展来简化控制器的开发,统一返回view或者json

1,首先定义一个ActionResult

public class ActionResult extends ModelAndView {
    public ActionResult()
    {
        super();
    }
    public ActionResult(View view)
    {
        super(view);
    }
}

2,在BaseController中来封装 ActionResult ,来提供统一的返回结果

package com.easycms.framework.web;

import cn.hutool.core.util.StrUtil;
import com.easycms.constant.JacksonConstants;
import com.easycms.framework.domain.DataTableDto;
import com.easycms.framework.domain.ResultAdaptDto;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import java.util.Hashtable;

public class BaseController {

    /**
     * 返回页面
     */
    //public String view(String url){
     //   return url;
    //}
    /**
     * 页面跳转
     */
    public String redirect(String url)
    {

        return StrUtil.format("redirect:{}", url);
    }
    /**
     *
     * @author yushuo
     * @description //返回视图view
     * @date 14:15 2021/2/4
     * @param
     * @return com.easycms.framework.web.ActionResult
     **/
    protected ActionResult view() {

        return view(null);
    }
    /**
     *
     * @author yushuo
     * @description //返回视图view
     * @date 14:15 2021/2/4
     * @param [viewpath]
     * @return com.easycms.framework.web.ActionResult
     **/
    protected ActionResult view(String viewPath) {
        return view(viewPath,null);
    }
    /**
     *
     * @author yushuo
     * @description //返回视图view
     * @date 14:15 2021/2/4
     * @param [model]
     * @return com.easycms.framework.web.ActionResult
     **/
    protected ActionResult view(Object model) {
        return view(null, model);
    }

    /**
    *
     * @author yushuo
     * @description //返回视图view
     * @date 14:15 2021/2/4
     * @param [viewpath, model]
     * @return com.easycms.framework.web.ActionResult
    **/
    protected ActionResult view(String viewpath, Object model) {
        ActionResult r = new ActionResult();
        r.setViewName(viewpath);
        r.addObject("model", model);
        return r;
    }


    /**
    *
     * @author yushuo
     * @description //返回json
     * @date 14:15 2021/2/4
     * @param  [Hashtable<String,Object> data]
     * @return org.springframework.web.servlet.ModelAndView
    **/
    protected ActionResult json(Hashtable<String,Object> data) {
        ActionResult modelAndView = new ActionResult(JacksonConstants.mappingJackson2JsonView);
        modelAndView.addObject("message", null);
        modelAndView.addObject("code",0);
        modelAndView.addObject("status",true);
        modelAndView.addObject("data", data);
        return modelAndView;
    }

    /**
     *
     * @author yushuo
     * @description //返回json
     * @date 14:15 2021/2/4
     * @param  [ResultAdaptDto data]
     * @return org.springframework.web.servlet.ModelAndView
     **/
    protected ActionResult json(ResultAdaptDto data) {
        ActionResult modelAndView = new ActionResult(JacksonConstants.mappingJackson2JsonView);
       // modelAndView.addObject(data);
        modelAndView.addObject("message", null);
        modelAndView.addObject("code",0);
        modelAndView.addObject("status",true);
        modelAndView.addObject("data", data.getData());
        return modelAndView;
    }

    /**
     *
     * @author yushuo
     * @description //返回json
     * @date 14:15 2021/2/4
     * @param  [DataTableDto data]
     * @return org.springframework.web.servlet.ModelAndView
     **/
    protected ActionResult json(DataTableDto data) {
        ActionResult modelAndView = new ActionResult(JacksonConstants.mappingJackson2JsonView);
        modelAndView.addObject(data);
        return modelAndView;
    }

    /**
    *
     * @author yushuo
     * @description //请求失败
     * @date 14:20 2021/2/4
     * @param [message]
     * @return com.easycms.framework.web.ActionResult
    **/
    protected ActionResult error(String message){
        ActionResult modelAndView = new ActionResult(JacksonConstants.mappingJackson2JsonView);
        modelAndView.addObject("message", message);
        modelAndView.addObject("code",0);
        modelAndView.addObject("status",false);
        return modelAndView;
    }

    /**
     *
     * @author yushuo
     * @description //请求失败
     * @date 14:20 2021/2/4
     * @param
     * @return com.easycms.framework.web.ActionResult
     **/
    protected ActionResult error(){
        ActionResult modelAndView = new ActionResult(JacksonConstants.mappingJackson2JsonView);
        modelAndView.addObject("message", "请求失败");
        modelAndView.addObject("code",0);
        modelAndView.addObject("status",false);
        return modelAndView;
    }

    /**
     *
     * @author yushuo
     * @description //请求失败
     * @date 14:20 2021/2/4
     * @param [message]
     * @return com.easycms.framework.web.ActionResult
     **/
    protected ActionResult ok(String message){
        ActionResult modelAndView = new ActionResult(JacksonConstants.mappingJackson2JsonView);
        modelAndView.addObject("message", message);
        modelAndView.addObject("code",0);
        modelAndView.addObject("status",true);
        return modelAndView;
    }

    /**
     *
     * @author yushuo
     * @description //请求成功
     * @date 14:20 2021/2/4
     * @param
     * @return com.easycms.framework.web.ActionResult
     **/
    protected ActionResult ok(){
        ActionResult modelAndView = new ActionResult(JacksonConstants.mappingJackson2JsonView);
        modelAndView.addObject("message", "操作成功");
        modelAndView.addObject("code",0);
        modelAndView.addObject("status",true);
        return modelAndView;
    }
}

3,BaseController中用到的JacksonConstants

package com.easycms.constant;

import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import java.text.SimpleDateFormat;
import java.util.TimeZone;

/**
 * @author yushuo
 * @className
 * @descripton TODO
 * @date 2021/2/5 13:47
 **/
public class JacksonConstants {

    /**
     * @author yushuo
     * @description //jackson ObjectMapper
     * @date 13:52 2021/2/5
     * @param
     * @return
    **/
    public static ObjectMapper objectMapper;
    /**
     * @author yushuo
     * @description //jackson MappingJackson2HttpMessageConverter
     * @date 13:52 2021/2/5
     * @param
     * @return
     **/
    public static  MappingJackson2HttpMessageConverter jackson2HttpMessageConverter;
    /**
     * @author yushuo
     * @description //jackson MappingJackson2JsonView
     * @date 13:52 2021/2/5
     * @param
     * @return
     **/
    public static MappingJackson2JsonView mappingJackson2JsonView;
    static {
        objectMapper=objectMapper();
        jackson2HttpMessageConverter=jackson2HttpMessageConverter();
        mappingJackson2JsonView=mappingJackson2JsonView();
    }

    /**
    *
     * @author yushuo
     * @description //jackson配置jackson2HttpMessageConverter
     * @date 13:49 2021/2/5
     * @param []
     * @return org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
    **/
    private static MappingJackson2HttpMessageConverter jackson2HttpMessageConverter(){
        return new MappingJackson2HttpMessageConverter(objectMapper());
    }

    /**
    *
     * @author yushuo
     * @description //jackson配置 objectMapper
     * @date 13:51 2021/2/5
     * @param []
     * @return com.fasterxml.jackson.databind.ObjectMapper
    **/
    private static ObjectMapper objectMapper(){
        final Jackson2ObjectMapperBuilder builder=new Jackson2ObjectMapperBuilder();
        final ObjectMapper objectMapper=builder.build();
        SimpleModule simpleModule=new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE,ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER,true);

        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        return objectMapper;
    }
    /**
     *
     * @author yushuo
     * @description //jackson配置
     * @date 13:49 2021/2/5
     * @param []
     * @return org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
     **/
    private static MappingJackson2JsonView mappingJackson2JsonView(){
        return new MappingJackson2JsonView(objectMapper());
    }
}

4,实际使用

返回视图

    @GetMapping("/login")
    public ActionResult login(){

        return view("/home/login");
    }

   //或者
    @GetMapping("/login")
    public ActionResult login(){

        return view();
    }
   //或者
    @GetMapping("/login")
    public ActionResult login(){
         ModelMap model=new ModelMap();
         model.put("author","yushuo");
        return view(model);
    }

返回json

@GetMapping("/getJson")   
 public ActionResult getJson(String id){
       Hashtable<String,Object> data=new Hashtable<>();
        data.put("id",id);
        return json(result);
    }

 

这样是不是就比原始的控制器开发简化多了呢

可以使用统一ActionResult来返回视图view或者json,整体代码风格看起来也更统一