精华内容
下载资源
问答
  • 概述 spring/spring boot 返回的json数据,通常包含了对象所有的字段,有时候浪费流量。...后端在返回数据前进行统一拦截,只返回需要的字段。具有有多种实现方式(这里只提供spring boot)。 首先约定返回的Ba...

    概述

    spring/spring boot 返回的json数据,通常包含了对象所有的字段,有时候浪费流量。例如一个接口有10个字段,而前端只需要2个字段,都返回会浪费流量。
    解决方案:前端在header中传递需要包含或需要排除的字段;后端在返回数据前进行统一拦截,只返回需要的字段。
    具有有多种实现方式(这里只提供spring boot)。

    首先约定返回的BaseResult对象格式如下,里面result属性就是实际各种数据对象。

    {
        "ret":0,
        "msg":null,
        "result":{
            "id":1,
            "name":"后摄像头53"
        },
        "time":1540972430498
    }

    实现方式一:通过AOP controller来实现

    aop实现步骤说明:

    • 判断返回的是不是BaseResult对象
    • 判断request header或params是否有x-include-fields、x-exclude-fields属性(有则取出来放入set中)
    • 满足以上条件则对BaseResult.result 对象进行处理,用Map替换result对象,Map只返回需要的字段。如果是Array或Collection则每个Item替换成一个Map。
    
    import com.cehome.cloudbox.common.object.BaseResult;
    import com.cehome.cloudbox.common.object.ItemsResult;
    import com.cehome.cloudbox.common.object.PageResult;
    import com.cehome.cloudbox.common.page.Page;
    import com.cehomex.spring.feign.FeignRequestHolder;
    import org.apache.commons.beanutils.PropertyUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.beans.PropertyDescriptor;
    import java.util.*;
    
    @Aspect
    public class ControllerAOP {
        private static String INCLUDE_FIELDS = "x-include-fields";
        private static String EXCLUDE_FIELDS = "x-exclude-fields";
        private static String P_INCLUDE_FIELDS = "x-include-fields";
        private static String P_EXCLUDE_FIELDS = "x-exclude-fields";
    
        private static final Logger logger = LoggerFactory.getLogger(ControllerAOP.class);
    
        @Pointcut("within(@org.springframework.stereotype.Controller *)")
        public void controller() {
        }
    
        @Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")
        public void restController() {
        }
    
        @Around("(controller() || restController()) && execution(public * *(..))")
        public Object proceed(ProceedingJoinPoint joinPoint) throws Throwable {
    
            try {
    
                Object object=joinPoint.proceed();
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
                        .getRequestAttributes();
                if (requestAttributes != null) {
                    HttpServletRequest request = requestAttributes.getRequest();
                    handleReturnValue(object,request);
                }
                return object;
            } finally {
    
                FeignRequestHolder.removeAll();
            }
    
    
        }
    
        /**
         * 返回前端需要的字段
         * @param o
         * @param request
         * @throws Exception
         */
        public void handleReturnValue(Object o,HttpServletRequest request) throws Exception {
            if(!isSuccess(o)) return;
    
            //HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
            //HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
            String fields1 = StringUtils.trimToEmpty(request.getHeader(INCLUDE_FIELDS));
            if(fields1.length()==0) fields1 = StringUtils.trimToEmpty(request.getParameter(P_INCLUDE_FIELDS));
            String fields2 = StringUtils.trimToEmpty(request.getHeader(EXCLUDE_FIELDS));
            if(fields2.length()==0) fields2 = StringUtils.trimToEmpty(request.getParameter(P_EXCLUDE_FIELDS));
            if (fields1.length() > 0 || fields2.length() > 0) {
                Set<String> includes = fields1.length() == 0 ? new HashSet<>() : new HashSet<>(Arrays.asList(fields1.split(",")));
                Set<String> excludes = fields2.length() == 0 ? new HashSet<>() : new HashSet<>(Arrays.asList(fields2.split(",")));
    
                if (o instanceof BaseResult) {
                    BaseResult result = (BaseResult) o;
                    Object object = result.getResult();
                    result.setResult(convertResult(object, includes, excludes));
    
                } else if (o instanceof ItemsResult) {
                    ItemsResult result = (ItemsResult) o;
                    Object object = result.getItems();
                    result.setItems(convertResult(object, includes, excludes));
    
                } else if (o instanceof PageResult) {
                    PageResult result = (PageResult) o;
                    Object object = result.getPage();
                    if (object instanceof Page) {
                        Page page=(Page) object;
                        List datas = page.getDatas();
                        page.setDatas((List)convertResult(datas, includes, excludes));
    
                    }
    
                }
    
            }
    
    
        }
    
        private boolean isSuccess(Object object){
            if(object==null) return false;
            if (object instanceof BaseResult) return ( (BaseResult) object).isSuccess();
            if (object instanceof ItemsResult) return ( (ItemsResult) object).isSuccess();
            if (object instanceof PageResult) return ( (PageResult) object).isSuccess();
            return false;
        }
        /*private void handleObject(Object object, Set<String> includes, Set<String> excludes) throws Exception {
    
            PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(object);
            for (PropertyDescriptor pd : pds) {
                String name = pd.getName();
                if (name.equals("class")) {
                    continue;
                }
                if (excludes.contains(name) || !includes.contains(name)) {
                    PropertyUtils.setProperty(object, name, null);
                }
            }
        }*/
    
        /**
         * convert objects to maps
         * @param object
         * @param includes
         * @param excludes
         * @return
         * @throws Exception
         */
        private Object convertResult(Object object, Set<String> includes, Set<String> excludes) throws Exception{
            if (object instanceof Object[]) {
                Object[] objects = (Object[]) object;
                return convertArray(objects,includes,excludes);
            } else if (object instanceof Collection) {
                Collection collection = (Collection) object;
                return convertCollection(collection,includes,excludes);
            }else{
                return convertObject(object,includes,excludes);
            }
        }
    
        private Collection<Map> convertCollection(Collection collection, Set<String> includes, Set<String> excludes) throws Exception{
            Collection<Map> result=new ArrayList<>();
            for (Object item : collection) {
                result.add(convertObject(item,includes,excludes));
            }
            return result;
        }
        private Map[] convertArray(Object[] objects, Set<String> includes, Set<String> excludes)  throws Exception{
            Map[] result=new HashMap[objects.length];
            for(int i=0;i<objects.length;i++){
                result[i]=convertObject(objects[i],includes,excludes);
            }
    
            return result;
        }
    
        /**
         * convert object to map
         * @param object  input
         * @param includes  include props
         * @param excludes  exclude props
         * @return
         * @throws Exception
         */
        private Map convertObject(Object object, Set<String> includes, Set<String> excludes) throws Exception {
    
            Map<Object,Object> result=new HashMap<>();
            if(!(object instanceof Map)) {
                PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(object);
                for (PropertyDescriptor pd : pds) {
                    String name = pd.getName();
                    if (name.equals("class")) {
                        continue;
                    }
                    if(!excludes.isEmpty() && excludes.contains(name)){
                        continue;
                    }
                    if(!includes.isEmpty() && !includes.contains(name)){
                        continue;
                    }
                    result.put(name,PropertyUtils.getProperty(object, name));
                }
            }else {
                Map<Object,Object>  map=(Map<Object,Object>) object;
    
                for(Map.Entry<Object,Object>  entry :map.entrySet()){
                    String name= entry.getKey()==null?"":entry.getKey().toString();
                    if(!excludes.isEmpty() && excludes.contains(name)){
                        continue;
                    }
                    if(!includes.isEmpty() && !includes.contains(name)){
                        continue;
                    }
                    result.put(entry.getKey(),entry.getValue());
    
                }
            }
    
            return result;
    
    
        }
    
    
    
    }
    

    用Map替换的方式改变了原来的对象,还有一种效率更好的不改变对象的方式,
    就是把不需要返回的字段设为null,然后配置一个JSON处理bean,统一过滤null的字段。这种方式null的字段就不再返回前端,需要前端做些兼容。

        @Bean
        @Primary
        @ConditionalOnMissingBean(ObjectMapper.class)
        public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
            ObjectMapper objectMapper = builder.createXmlMapper(false).build();
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            return objectMapper;
        }

    实现方式二:自定义HttpMessageConverter来实现

    spring boot缺省包含了好几个消息转换器,根据返回媒体类型进行匹配,第一个匹配上就忽略掉其它的了。
    MappingJackson2HttpMessageConverter 是其处理JSON的消息转换器。

    • 所以,需要先删除缺省的MappingJackson2HttpMessageConverter
    • 继承MappingJackson2HttpMessageConverter,实现自定义的消息转换。
    
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.fasterxml.jackson.annotation.JsonInclude;
    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.impl.SimpleBeanPropertyFilter;
    import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
    import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
    
    import java.io.IOException;
    import java.lang.reflect.Type;
    import java.nio.charset.Charset;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpOutputMessage;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.HttpMessageNotWritableException;
    import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJacksonValue;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
    
    
        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    
            //-- 移除缺省的JSON处理器
            for (int i = converters.size() - 1; i >= 0; i--) {
                HttpMessageConverter<?> messageConverter = converters.get(i);
                if (messageConverter instanceof org.springframework.http.converter.json.MappingJackson2HttpMessageConverter)
                    converters.remove(i);
            }
    
            // --  添加自己得JSON处理器
    
            MappingJackson2HttpMessageConverter c = new MappingJackson2HttpMessageConverter() {
                @Override
                protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
                    
                    //-- 例子一: 转成fastjson对象,然后替换name字段
                    JSONObject json = (JSONObject) JSON.toJSON(object);
                    json.getJSONObject("result").put("name", "coolma");
                    super.writeInternal(json, type, outputMessage);
                   
                    //-- 例子二: 用过滤器只保留name字段,其它字段不要。
                    //注意,例子二需要给BaseResult对象的result属性加上com.fasterxml.jackson.annotation.JsonFilter注解:
                    // @JsonFilter("result") 
                    // private  T result;
                    MappingJacksonValue value = new MappingJacksonValue(object);
                    value.setFilters(new SimpleFilterProvider().addFilter("result",
                            SimpleBeanPropertyFilter.filterOutAllExcept("name")));
                    super.writeInternal(value, type, outputMessage);
                }
    
            };
            c.setDefaultCharset(Charset.forName("UTF-8"));
            List<MediaType> mediaTypes = new ArrayList<>();
            mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
            c.setSupportedMediaTypes(mediaTypes);
            converters.add(c);
    
        }
    }
    
    展开全文
  • 同一个功能,后端返回的数据结构经常变动,导致前端写逻辑也得相应修改,而接口适配就是为了解决此问题,不管后端接口怎么变动,前端只需要调整适配数据部分,而不会对页面已有逻辑造成影响。 请求接口适配 ...

    为什么要做接口适配

    同一个功能,后端返回的数据结构经常变动,导致前端写的逻辑也得相应的修改,而接口适配就是为了解决此问题,不管后端接口怎么变动,前端只需要调整适配的数据部分,而不会对页面已有逻辑造成影响。

    请求接口的适配

    拿登录功能来说,有账号密码字段。

    请求登录(以前)

    export const Login = data => {
        return ajax.post('/sso/login', {
            username: data.username,
            password: data.password
        })
    }

    export const Login = data => {
        return ajax.post('/sso/login', data)
    }

    请求登录(现在)

    export const Login = data => {
        return ajax.post('/sso/login', {
            username: data.name,
            password: data.password
        })
    }

    以前的写法和现在的写法,它们的差别在于以前获取的页面数据字段都是按照后端要求的数据结构写的,而现在的做法只是在请求登录时,对传递的数据进行调整。

    这样做的好处在于页面中的逻辑,数据结构可以根据自己来定义,而不会限制于后端的数据结构,另外也就不必等后端接口实现好了再写相关逻辑,因为所有的数据结构都是自己来定义的。

    响应数据的适配

    还是拿登录功能来说

    现在

    export const Login = data => {
        return ajax.post('/sso/login', {
            userName: data.name,
            password: data.password
        }).then(res => {
            let data = res.data
            
            return {
                token: data.token,
                name: data.userName,
                sex: data.userSex,
                mobile: data.userMobile
            }
        })
    }

    页面中

    <template>
      <div>姓名:{{user.name}}</div>
      <div>性别:{{user.sex}}</div>
    </template>
    
    <script>
        import { Login } from '$api'
        
        export default {
            data() {
                return {
                    name: '',
                    sex: ''
                }
            },
            created() {
                Login({
                    name: '张三',
                    password: '123456'
                }).then(res => {
                    this.name = res.name
                    this.sex = res.sex
                })
            }
        }
    </script>

    以前

    export const Login = data => {
        return ajax.post('/sso/login', {
            userName: data.userName,
            password: data.password
        })
    }

    页面中

    <template>
      <div>姓名:{{user.userName}}</div>
      <div>性别:{{user.userSex}}</div>
    </template>
    
    <script>
        import { Login } from '$api'
        
        export default {
            data() {
                return {
                    userName: '',
                    userSex: ''
                }
            },
            created() {
                Login({
                    userName: '张三',
                    password: '123456'
                }).then(res => {
                    this.userName = res.userName
                    this.userSex = res.userSex
                })
            }
        }
    </script>

    可以看到以前我们总是按后端返回的数据结构,原样的写在页面里面,然而一旦后端数据结构发生了变更,我们就要找到所有使用此接口的页面,并调整相应参数。

    现在的做法虽然看似代码变多了,但你会发现,页面中的数据结构是按照我们自己写的,所以后端的数据结构怎么改变,都不怎么需要改动页面中的参数和逻辑。

    结语

    尽管接口适配可以避免重新调整页面既有逻辑,但不管如何还是需要后端提前提供接口文档的,因为最终的数据是由后端来提供的,如果期望的接口并没有返回指定数据,而这些数据需要另一个接口来获取,从而导致页面中的逻辑与现有数据不一致。

    也就是说,尽管我们可以对接口进行适配,但还是有必要提前了解一下后端返回的数据和所需的数据。

    转载于:https://www.cnblogs.com/pssp/p/10123189.html

    展开全文
  • 前后端分离开发中最重要一部就是前后端联调,很多时候后端进度是跟不上前端,所以需要前端模拟一些数据进行调试,这样前端进度就可以加快了。后端的小哥哥别打我;    使用mockjs可以很方便模拟出想要...

         前后端分离开发中最重要的一部就是前后端联调,很多时候后端进度是跟不上前端的,所以需要前端模拟一些数据进行调试,这样前端的进度就可以加快了。后端的小哥哥别打我;

        

      使用mockjs可以很方便的模拟出想要的数据,只要后端字段给好,就可以模拟出数据,等到后端的数据接口真真好的时候可以直接将接口换掉;

      使用方法;

       一;安装json-server   (ps:本人理解这是模拟一个后端服务器,到时候会开一个虚拟服务器出来)

          npm install json-server –g

          二;在项目中安装mockjs

        npm install mockjs –save

       三;在项目中建立目录mock  ,并且增加mockjs文件,将如下代码写入文件中

      

    var Mock = require('mockjs');
    var Random = Mock.Random;
    
    module.exports = function(){
          var data2 = {
                title:[]
          };
          for(var i = 0;i<20;i++){
                var content = Random.cparagraph(0,10);
                data2.title.push({
                      id:i,
                      title:Random.cword(20,30),
                      name:Random.cname(),
                      email:Random.email(),
                      color:Random.color(),
                      s:Random.region(),
                      q:Random.city( true )
                })
          }
          return data2;
    }
    

        四;使用命令执行文件,运行服务

        json-server mock/db.js;

          

    ps:本人看文章学到的,项目中还没有具体使用

    参考链接

    https://zm12.sm-tc.cn/?src=l4uLj8XQ0IiIiNGckZ2TkJiM0ZyQktCHhp3Pzc3J0J6Ni5ack5qM0MjNzMvKz8jRl4uSkw%3D%3D&uid=e4391b419c0308e33c48eb4823b5515c&hid=e52b73bf962427b19f439c8ad15cc617&pos=1&cid=9&time=1526148679529&from=timeline&restype=1&pagetype=0020004000000408&bu=ss_doc&query=%E7%94%A8node+%E6%90%AD%E5%BB%BAmock&mode=&v=1&force=true&wap=false&uc_param_str=dnntnwvepffrgibijbprsvdsdichei

    转载于:https://www.cnblogs.com/qqfontofweb/p/9078195.html

    展开全文
  • Java后端统一封装返回结果在JavaWeb编程中,总是需要返回结果嘛,对于前后端分离项目来说,对结果封装尤其重要,如果不进行封装话总是需要各种各样的返回类型,如果说统一了返回值类型话那就只需要指定...

    Java后端统一封装返回结果

    在Java的Web编程中,总是需要返回结果的嘛,对于前后端分离的项目来说,对结果的封装尤其重要,如果不进行封装的话总是需要各种各样的返回类型,如果说统一了返回值类型的话那就只需要指定一种返回值就好了

    我是这样做的,封装一个Result VO类 表示这是要给前端展示的对象,ViewObject。

    里面的字段主要有

    code 响应码 自定的

    msg 返回消息

    data 真实的返回的数据

    timestamp 时间戳

    然后这样完了后,还有一点需要考虑,就是这对对象需要频繁的被创建,但是有很多时候里面的数据都是空的,或者说是类似的,这个时候就需要事先创建一些对象,然后使用静态方法返回,这样就不用频繁的使用new关键字进行创建了。省去很多时间,然后呢,还有一些情况是就里面的数据不一样,响应码以及消息都是一样的所以需要再抽取一个方法然后通过参数传入变化的数据。

    然后如果什么都不一样的话也是会使用new关键字进行创建,这样也很麻烦,因为每次赋值都需要写一下对象名然后使用setter进行赋值嘛。这个时候我们极其自然的想到一种设计模式那就是建造者模式,不需要使用new关键字,而且是链式编程,很是方便,而且幸运的是,在Lombok中提供了一个注解@Builder来生成该类的建造者很是方便。

    至此返回结果就封装完毕了

    具体如下

    /**

    * @author lc

    * @date 2020-12-22 17:40

    */

    @Builder

    @ToString

    public class ResultVO {

    /**

    * 响应码

    */

    public int code;

    /**

    * 返回的数据

    */

    public Object data;

    /**

    * 时间戳

    */

    public Date timestamp;

    /**

    * 消息

    */

    public String msg;

    public static ResultVO error() {

    return ResultVO.builder().code(20001).data(false).timestamp(new Date()).build();

    }

    public static ResultVO error(Object data) {

    return ResultVO.builder().code(20001).data(data).timestamp(new Date()).build();

    }

    public static ResultVO success() {

    return ResultVO.builder().code(20000).data(true).timestamp(new Date()).build();

    }

    public static ResultVO success(Object data) {

    return ResultVO.builder().code(20000).data(data).timestamp(new Date()).build();

    }

    }xxxxxxxxxx     public static ResultVO success(Object data) {        return ResultVO.builder().code(20000).data(data).timestamp(new Date()).build();   }}/** * @author lc * @date 2020-12-22 17:40 */@Builder@ToStringpublic class ResultVO {    /**     * 响应码     */    public int code;    /**     * 返回的数据     */    public Object data;    /**     * 时间戳     */    public Date timestamp;    /**     * 消息     */    public String msg;    public static ResultVO error() {        return ResultVO.builder().code(20001).data(false).timestamp(new Date()).build();   }    public static ResultVO error(Object data) {        return ResultVO.builder().code(20001).data(data).timestamp(new Date()).build();   }    public static ResultVO success() {        return ResultVO.builder().code(20000).data(true).timestamp(new Date()).build();   }    public static ResultVO success(Object data) {        return ResultVO.builder().code(20000).data(data).timestamp(new Date()).build();   }}

    但是还有一个点,那就是状态码,也就是响应码 如果改变的话,需要对每个进行方便,而且在《阿里巴巴编程规约》中不建议使用魔法值。所以我们需要在一个类中将这些状态码,封装成常量,这样如果需要改变的话只需要对这个类进行修改就好了

    package com.cliong.mall.entity;

    /**

    * @author lc

    * @date 2020-12-24 15:28

    */

    public class ResultStatus {

    public final static int SUCCESS = 20000;

    public final static int FAIL = 20001;

    }

    至此,完成

    展开全文
  • 我们经常会遇到显示 "某个之间之前" 的需求(比如各种社交软件,在回复消息时,显示xxx之前回复),我们可以在...其实很简单,我们只需要将从数据库中取到的date类型的字段进行处理。 工具类如下: import jav...
  • springboot 返回给前端不必要的字段如何处理 现在大多数项目都是前后端...要sql上做工,查前端所需要的;(细节省略) 第二步 1.可以在类头上加注解局部处理(第一种) @JsonInclude(JsonInclude.Include.NON_NUL
  • 背景 地点:xxxx公司会议室... 后端小菜:多余的字段你们不要管就好啦,又不影响你们~,实在不行我拷贝个新对象给你! 思考 ????接口传输大量无用数据占用带宽资源、影响性能、甚至泄漏敏感信息!拷贝新对象...
  • TommyLemon2018-08-16 15:16:45 +08:00@wangxiaoaer后端:零用时开发接口、零沟通零被打扰。前端 /客户端:内容可任意...APIJSON 实现了前端 /客户端要什么就返回什么,而不是后端给什么才能用什么,从根本上解决了...
  • 在已有接口文档的情况下,我们可以直接按照接口文档来开发,将相应的字段写好,在接口完成 之后,只需要改变url地址即可。 mock/index.js 内容 const fs = require('fs'); const path = require('path'); const Mock...
  • 我们应该有这样一个常识,当后台向前台返回数据时,除了普通类型字段之外(如文本),所有有关联关系,我们都应该返回一个对象...而现在我只需要a中name,如下所示,我们不应该返回name,而是应该将整个对象返回,...
  • 上手操作 ...然后在dao下创建UserMapper接口,我们只需要在接口定义我们需要用到抽象方法。比如根据id查找user,那么写返回类型User 方法名selectUser (参数int id)。 package com.neu.l
  • 之前公司需要修改sonarQube平台上的代码规范问题,其中,有一种修改错误是枚举类里的字段没有符合驼峰风格,可问题是这些枚举的字段名是需要序列化成json格式返回给前端的,name问题就来了。如何后端修改其枚举...
  • 后端接口联调时候经常会出现判断后台返回的某个字段值是否有值,但是无值情况有好几种,如果每次都一一判断不仅浪费时间,也会衍生出很多不必要代码,特此写一个专门用于判断方法,在用时候只需要
  • GraphQL

    2020-08-10 15:20:02
    1.我们需要什么数据需要什么格式,后端就按照什么格式给我们返回什么样的数据结构,我们要哪些字段后端给我们返回我们需要的这些字段, 其他的都不返回,前端就和后端解耦了---》在前端直接写查询, 后端只管...
  • 问题描述:获取到后端返回的...卡了好久,反复测试了n遍results数据,最后发现输入建议列表的数据来源于data:[] 中的 value 字段,将 response 中需要展示的字段组成 {value:‘输入建议’} 这种格式,问题解决。 ...
  • 今天碰到一个很奇怪问题:后端返回的数据中ID字段数据对应不上,数据库和前端得到数据不一致,debug了下,原因是js解析json数据时,Long类型是用Number接收,Number最多是16位,所以导致后面几位数据丢失,查了...
  • 点击上方“ Java资料站”,选择“标星公众号”优质文章,第一时间送达我恰芙蓉王...后端不是只需要把列表返回就行了嘛。。。没错,我也是这样想,但是在一场和前端撕逼大战中败下阵来之后,这个东西就落在我身上...
  • 后端不是只需要把列表返回就行了嘛。。。没错,我也是这样想,但是在一场和前端撕逼大战中败下阵来之后,这个东西就落在我身上了。当时由于工期原因,时间比较紧,也就不考虑效率和易用性了,只是满足当时需求...
  • 最近在做一个项目系统时,需要Java后端给前端页面返回时间(要用本地时间--北京时间),后端时间字段映射,转换,不管怎么处理都是按照北京时间来,这个是正确。但是只要一到前端显示时候,就会比北京时间少8...
  • 后台给了一个状态值, 我们前端在显示时, 需要显示状态名。 后端在开发时, 自己在数据库中造了一些测试数据,没有关联正确,导致返回的数据有缺失。 正常业务不同阶段,有一些数据字段与业务状态有关,...
  • zTree

    2017-11-16 20:47:09
    zTree插件即可用静态加载树形列表,也可用动态加载,动态加载时,后端只需要返回一个json字符串即可,前提是这个json用到的实体类的字段必须遵循zTree的API。如这里的实体类叫Menu,则它的字段如下,这是固定的: ...
  • 同事A与同事B打电话,当通话结束时候两个页面会同时向后端发送请求添加记录,这个时候后端就会有两条记录,但是业务需要只保留一个通话记录就可以了。 第一次采取措施是先查询再插入,但是运行后发现有两条...
  • json-server实践与自定义配置化

    千次阅读 2018-05-28 09:58:26
    背景 之前做项目都没有用到mock服务,都是等后端给接口字段或者前端留空位;但新公司项目需要搭建mock服务,本想把旧项目json-server搬...按照我对mock服务理解,需检测 restful 风格 url 返回对应数据...
  • 这段时间做了一个研究网站,其中UI图上有个按照烟地区以及首字母...然后会把数据整理成这样:之后只需要将这四个数组里面数据首字母拿出来比较,然后按照首字母给它们分类即可!获取字符串首字母字典文件:ht...

空空如也

空空如也

1 2 3 4
收藏数 67
精华内容 26
关键字:

后端只返回需要的字段