V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
int64ago
V2EX  ›  程序员

「求助」Spring 同一个接口根据 Content-Type 返回不同的数据

  •  
  •   int64ago ·
    int64ago · 2016-10-25 17:11:05 +08:00 · 2947 次点击
    这是一个创建于 2949 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求是具体是这样的,目前的后端是 Spring 渲染好 Freemarker 页面后直接返回 HTML 页面

    代码可能如下:

     @RequestMapping("/index")
     public String hello(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model) {
         model.addAttribute("name", name);
         return "index";
     }
    

    我的理解就是, Model 先填充数据,然后再用 Model 填充 index.ftl ,然后再返回 index.html

    但是,我有时候的需求是,如果我请求的 Content-Type 指定是 json 的话,那么直接把 Model 里的数据当作 JSON 返回即可,不要去渲染 ftl 了

    我看到网上大多数的解决方法是这样的:

    @Controller
    public class PersonController 
    {
    
     private static List<Person> personList;
    
     static
     {
      personList = 
        Arrays.asList(new Person[] 
          { new Person(1, "Pas", "Apicella"),
               new Person(2, "Lucia", "Apicella"),
               new Person(3, "Lucas", "Apicella"),
               new Person(4, "Siena", "Apicella")
             });   
     }
    
        @RequestMapping(value="/people", 
                  method = RequestMethod.GET, 
                  produces={"application/xml", "application/json"})
        @ResponseStatus(HttpStatus.OK)
        public @ResponseBody People listWithJSON() 
        {
         return new People(personList);
    
        }
        
        // View-based method
        @RequestMapping(value = "/people", method = RequestMethod.GET)
        public String listWithView(Model model, HttpServletResponse response, HttpServletRequest request) 
        {
             
         // Call RESTful method to avoid repeating code
         model.addAttribute("peopleList", listWithJSON().getPeople());
    
         // Return the view to use for rendering the response
         return "people";
        }
    } 
    

    还有这样

    其实,都是一类解决方法

    这样做的问题很明显:

    • 破坏业务代码逻辑
    • 写太多重复代码
    • 在已经有很多页面的系统上追加额外方法太浪费时间

    从编程角度看,我觉得是否有种方法,在稍微底层逻辑上加个类似 Monkey Patch 或者 AOP 类似方法,可能就几行代码,也可能仅仅是配置,就可以实现这个需求呢?

    如果这个从技术上来看不可行,是否有代价非常小的做法呢?

    PS :我本人不是 Java 程序员,表述有不合规的地方请指出

    6 条回复    2016-10-26 09:38:00 +08:00
    int64ago
        1
    int64ago  
    OP
       2016-10-25 17:12:49 +08:00
    @murmur
    @FrankFang128

    看到两位经常讨论 Java ,跪求解答
    zhuangzhuang1988
        2
    zhuangzhuang1988  
       2016-10-25 17:25:05 +08:00
    调试下 就好了.. 记得,好像,在 resolver 上....
    KingOfUSA
        3
    KingOfUSA  
       2016-10-25 17:29:56 +08:00
    不是程序员的话,把这样的事情交给程序员就好啦。要相信你的程序员
    PEP4JASON
        4
    PEP4JASON  
       2016-10-25 18:51:53 +08:00
    如果是 JSON 的话直接打印出来就行了 不需要传值到页面上 再做相关处理 ,不知道我是不是理解对了
    safilar
        5
    safilar  
       2016-10-25 19:16:15 +08:00
    关注中
    johnj
        6
    johnj  
       2016-10-26 09:38:00 +08:00
    Spring MVC 内置 Content Negotiation 机制
    如果你的请求里面带有后缀的话 举个例子 index.json 就会认为请求的数据是 json 。后缀优先级高
    Accept header 优先级较低。
    所以前端我建议请求不带后缀 统一用 header 然后不带 header 的给设一个默认的 比如 freemarker
    思路是这样。搜一下 spring mvc content negotiation 吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5445 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 03:24 · PVG 11:24 · LAX 19:24 · JFK 22:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.