重新开始一个新的apk项目,之前的“公共自行车”没搞完又放弃了,希望这个项目不会继续无疾而终。把自己做这个项目的过程用博客记录下来,也算是对自己的一个督促。

完整文件:url80.ctfile.com/f/25127180-734983539-bb1f65?p=551685 (访问密码: 551685)


背景 : 用户在前端页面中不小心输入的前后空格,为了防止因为前后空格原因引起业务异常,所以我们需要去除参数的前后空格!

如果我们手动去除参数前后空格,我们可以这样做

@GetMapping(value = "/manualTrim")
public void helloGet(String userName) {//手动去空格userName = userName == null ? null : userName.trim();//或者通过谷歌工具类手动去空格String trim = StringUtils.trim(userName);
}

这种方式需要每个接口参数都进行手动的去除首尾空格,显然会让代码冗余,并不友好!所以我们应该从项目整体思考,这里通过过滤器的方式去除请求参数前后空格。

我们来看下大致实现的流程

在SpringBoot中有两种方式实现自定义Filter:

第一种是使用 @WebFilter 和 @ServletComponentScan 组合注解。

第二种是通过配置类注入 FilterRegistrationBean对象。

通过FilterRegistrationBean对象可以通过Order属性改变顺序,使用@WebFilter注解的方式只能根据过滤器名的类名顺序执行,添加@Order注解是无效的。

既然是通过过滤器获取请求参数去除参数的首尾空格,那我们应该考虑几种情况的请求参数

Get请求,请求参数放到url后面
Post请求 请求参数放到url后面
Post请求 请求参数放到body里面
第一种和第二种其实可以通过一种方式实现就是request.getParameter()方法。

Post中body请求参数我们可以通过使用流的方式,调用request.getInputStream()获取流,然后从流中读取参数。

一、实现代码
1、注册过滤器
/**

  • 通过FilterRegistrationBean注册自定义过滤器TrimFilter
    */
    @Configuration
    public class FilterConfig {

    /**

    • 注册去除参数头尾空格过滤器
      /
      @Bean
      public FilterRegistrationBean trimFilterRegistration() {
      FilterRegistrationBean registration = new FilterRegistrationBean();
      registration.setDispatcherTypes(DispatcherType.REQUEST);
      //注册自定义过滤器
      registration.setFilter(new TrimFilter());
      //过滤所有路径
      registration.addUrlPatterns("/
      ");
      //过滤器名称
      registration.setName(“trimFilter”);
      //优先级越低越优先,这里说明最低优先级
      registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
      return registration;
      }
      }
      2、自定义过滤器TrimFilter
      /**
  • 自定义过滤器 通过继承OncePerRequestFilter实现每次请求该过滤器只被执行一次
    */
    public class TrimFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain)
    throws ServletException, IOException {
    //自定义TrimRequestWrapper,在这里实现参数去空
    TrimRequestWrapper requestWrapper = new TrimRequestWrapper(httpServletRequest);
    filterChain.doFilter(requestWrapper, httpServletResponse);
    }
    }
    3、自定义TrimRequestWrapper类
    TrimRequestWrapper类,其实也是最重要的一个类,继承HttpServletRequestWrapper重写getParameter,getParameterValues方法,getInputStream方法,前面的重写

可以解决非json的参数首尾去空格,但如果是json请求的参数那就必须重写getInputStream方法,从流中获取参数进行处理。

注意: request的输入流只能读取一次

/**

  • 自定义TrimRequestWrapper类
    */
    @Slf4j
    public class TrimRequestWrapper extends HttpServletRequestWrapper {

    /**

    • 保存处理后的参数
      */
      private Map<String, String[]> params = new HashMap<String, String[]>();

    public TrimRequestWrapper(HttpServletRequest request) {
    //将request交给父类,以便于调用对应方法的时候,将其输出
    super(request);
    //对于非json请求的参数进行处理
    if (super.getHeader(HttpHeaders.CONTENT_TYPE) == null ||
    (!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE) &&
    !super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE))) {
    setParams(request);
    }
    }

    private void setParams(HttpServletRequest request) {
    //将请求的的参数转换为map集合
    Map<String, String[]> requestMap = request.getParameterMap();
    log.info(“kv转化前参数:” + JSON.toJSONString(requestMap));
    this.params.putAll(requestMap);
    //去空操作
    this.modifyParameterValues();
    log.info(“kv转化后参数:” + JSON.toJSONString(params));
    }

    /**

    • 将parameter的值去除空格后重写回去
      */
      public void modifyParameterValues() {
      Set set = params.keySet();
      Iterator it = set.iterator();
      while (it.hasNext()) {
      String key = it.next();
      String[] values = params.get(key);
      values[0] = values[0].trim();
      params.put(key, values);
      }

    }

    /**

    • 重写getParameter 参数从当前类中的map获取
      */
      @Override
      public String getParameter(String name) {
      String[] values = params.get(name);
      if (values == null || values.length == 0) {
      return null;
      }
      return values[0];
      }

    /**

    • 重写getParameterValues
      */
      @Override
      public String[] getParameterValues(String name) {
      return params.get(name);
      }

    /**

    • 重写getInputStream方法 post类型的请求参数必须通过流才能获取到值
    • 这种获取的参数的方式针对于内容类型为文本类型,比如Content-Type:text/plain,application/json,text/html等
    • 在springmvc中可以使用@RequestBody 来获取 json数据类型
    • 其他文本类型不做处理,重点处理json数据格式
    • getInputStream() ,只有当方法为post请求,且参数为json格式是,会被默认调用
      */
      @Override
      public ServletInputStream getInputStream() throws IOException {
      //
      if (!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE) &&
      !super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)) {
      //如果参数不是json格式则直接返回
      return super.getInputStream();
      }
      //为空,直接返回
      String json = IOUtils.toString(super.getInputStream(), “utf-8”);
      if (StringUtils.isEmpty(json)) {
      return super.getInputStream();
      }
      log.info(“json转化前参数:” + json);
      //json字符串首尾去空格
      JSONObject jsonObject = StringJsonUtils.JsonStrTrim(json);
      log.info(“json转化后参数:” + jsonObject.toJSONString());
      ByteArrayInputStream bis = new ByteArrayInputStream(jsonObject.toJSONString().getBytes(“utf-8”));
      return new MyServletInputStream(bis);
      }

}

二、测试
因为上面说了三种情况,所以这里提供了3个接口来进行测试

/**

  • 测试接口

  • @author xub

  • @date 2022/10/24 下午5:06
    */
    @Slf4j
    @RestController
    public class ParamController {

    /**

    • 1、Get请求测试首尾去空格
      */
      @GetMapping(value = “/getTrim”)
      public String getTrim(@RequestParam String username, @RequestParam String phone) {
      return username + “&” + phone;
      }

    /**

    • 2、Post方法测试首尾去空格
      */
      @PostMapping(value = “/postTrim”)
      public String postTrim(@RequestParam String username, @RequestParam String phone) {
      return username + “&” + phone;
      }

    /**

    • 3、post方法 json入参 测试首尾去空格
      */
      @PostMapping(value = “/postJsonTrim”)
      public String helloUser(@RequestBody UserDO userDO) {
      return JSONObject.toJSONString(userDO);
      }
      }

1、Get请求测试首尾去空格
请求url

http://localhost:8080/getTrim?username=张三 &phone= 18812345678
后台输出日志

: kv转化前参数:{“username”:[“张三 “],“phone”:[” 18812345678”]}
kv转化后参数:{“phone”:[“18812345678”],“username”:[“张三”]}
接口返回

张三&18812345678
说明首尾去空格成功!

2、Post方法测试首尾去空格
请求url

http://127.0.0.1:8080/postTrim?username=张三 &phone= 18812345678
后台输出日志

: kv转化前参数:{“username”:[“张三 “],“phone”:[” 18812345678”]}
kv转化后参数:{“phone”:[“18812345678”],“username”:[“张三”]}
接口返回

张三&18812345678
说明首尾去空格成功!

3、post方法 json参数测试首尾去空格
请求url

http://127.0.0.1:8080/postJsonTrim
请求参数和返回参数

实现一个Android电子书阅读APP相关推荐

  1. [前言] 实现一个Android电子书阅读APP

    大家好,我是小方,我将在接下来的几篇文章中从零实现一个网络小说阅读器,从安卓编程最基础的部分讲起,直至成功完成我们的应用,从新建一个项目开始,不断添加新的代码,添加新的界面,循序渐进,涵盖所有我们需要 ...

  2. 【新建项目amp;使用viewPager】实现一个Android电子书阅读APP

    本章结尾处已放出应用DEMO,已经实现所有本文及后续文章所述全部功能,大家可以先下载下来玩玩看,欢迎在本文下方评论,小方很需要鼓励支持!!! 小说阅读器最终实现效果见 上一篇博文 新建一个项目 呼-我 ...

  3. 【新建项目使用viewPager】实现一个Android电子书阅读APP

    本章结尾处已放出应用DEMO,已经实现所有本文及后续文章所述全部功能,大家可以先下载下来玩玩看,欢迎在本文下方评论,小方很需要鼓励支持!!! 小说阅读器最终实现效果见 上一篇博文 新建一个项目 呼-我 ...

  4. Android电子书阅读器小程序(txt)

    Android电子书阅读器小程序(txt) 开发环境 JDK 1.8 操作系统 Windows×32位或64位 可行性分析 技术可行性: 本项目应用的均是上课所学习的内容. 软件可行性: 用平时学习的 ...

  5. Android电子书阅读器的设计与实现

    Android电子书阅读器 包括Android客服端和jsp服务端 主要有,在线图书,本地图书,用户设置,书签管理,JSP后台,可以管理用户帐号,图书信息管理 我的QQ 609085431

  6. 5款电子书阅读APP,看小说的必备神器

    喜欢看小说的朋友总是会遇到找不到想看的电子书资源,其实有些好用的电子书阅读APP里面有很多好看的小说,今天都 分享给大家! 1.追书神器 作为全网小说资源更新最快的小说阅读器,相信很多人对这款APP都 ...

  7. 安卓电子书格式_[技巧] 无敌的boss级电子书阅读app,全能高手就要一个打十个。...

    上期介绍了强大的阅读器AIReader 支持近20种阅读格式 缺点是界面操作不够简洁美观且不支持pdf格式 但它已经很强了 本期介绍一款更为强大到无敌的电子书阅读器 名为静读天下 话不多少先上图 ▽▽ ...

  8. android简单阅读app实例,PureRead 一个简单而精致的轻量级碎片化阅读App

    这是基于Flutter开发的碎片化阅读App,dd级作品,欢迎初学者学习 hxdm,过来康康啊! 主要使用的库 cached_network_image,图片缓存加载库 provider,对Widge ...

  9. android电子书阅读器

    2019独角兽企业重金招聘Python工程师标准>>> 本地电子书 一款干净美观的本地电子书阅读器,为了世界和平,决定将代码开源,稍加处理,即可实现各种梦幻功能. #源码中有三本电子 ...

最新文章

  1. 涉密电脑痕迹深度清理_Mac空间不足的情况下,该怎么清理呢?
  2. VS2010下创建WEBSERVICE,第二天 ----你会在C#的类库中添加web service引用吗?
  3. 21行代码AC——习题3-7 DNA序列(UVa-1368)_解题报告
  4. WPF 绑定StaticResource到控件的方法
  5. vue 单独页面定时器 离开页面销毁定时器
  6. wireshark使用_使用 Wireshark 抓取数据包
  7. JavaScript简介及基础知识(1)
  8. myeclipse报错:The superclass javax.servlet.http.HttpServlet was not found on the Java Build Path
  9. VSCode使用eclipse快捷键
  10. 贝叶斯网络(概率图模型)
  11. 对接湖南CA使用U_KEY登录
  12. Photoshop CS3 中文版安装教程
  13. 毕业设计基本要求计算机,计算机学院关于本科毕业设计(论文)的基本要求.doc
  14. 5G无线技术基础自学系列 | 5G组网方式
  15. Ubuntu窗口过大?按钮都点不到怎么办?
  16. 论文阅读:Neural Machine Translation By Jointly Learning To Align And Translate
  17. RPG Maker MV 图块冲突解决、素材管理
  18. 利用群晖搭建LEDE路由器,旁路由器
  19. 设备树学习(二十三、番外篇-中断子系统之softirq)
  20. android LocalSocket的使用

热门文章

  1. 图情论文笔记 | 川大实践之红色资源开发利用路径探索
  2. 微软 MSR Image Recognition Challenge 2016(IRC@ICME) 测试demo
  3. cesium有地球与无地球模式切换
  4. 【渝粤教育】国家开放大学2018年春季 0169-22T工程制图基础 参考试题
  5. 【恒指早盘分析】趋势交易——看懂很简单,做到却很难!
  6. Java学习---第二周周报
  7. 2021-7-7HTML5前端基础
  8. Chrome历史记录分析
  9. CBAP.BABOK.商业分析.业务分析.概述
  10. 计算机在物理化学的发展趋势,近代物理化学的发展趋势及特点