写在前面:

  先来陈述一下为什么会有这样一个需求和这篇博文。

  这是公司的一个项目,我们负责前端,后台服务由其他公司负责。该系统有一个系统偏好设置模块,用户可以设置系统的背景图片等系统样式,因为这是一个比较简单的功能,所以当时没有让后台公司来实现,由自己公司的一个领导编写了一个Servlet。但是由于服务器故障被格式化之后,这个Servlet就丢失了。本来打算跟领导汇报的,但是又怕挨批评,而且这个功能也并不复杂,所以决定自己实现一下吧。但是作为一个对Java一点都不懂的我来说,还是废了不少功夫的,所以有必要将这个过程记录一下。

具体需求:

  每一个用户都可以针对该Web系统设置自己的背景图片,可以从系统预设的图片中选择,也可以自己上传新的图片。而我们需要做的就是将用户的配置信息、上传的图片保存下来,当用户下次登录时,通过配置信息加载对应的背景图片即可。

实现方案:

  方案一:

  如果将所有的用户配置信息都存放到一个文件中,那么不管在获取还是保存时,都需要解析这个文件的内容,太麻烦,而且不利于扩展。假设以后这个系统偏好设置模块,不仅可以设置背景图片,还可以设置系统的常用功能模块,那对应保存每个用户的配置信息的数据格式就变了,那么解析这个文件内容的方法也就得跟着变了。举个例子吧,假设之前文件中保存用户配置信息的数据是这样的,{"用户Id1":"url1", "用户Id2":"url2", "用户Id3":"url3", ...}。那么在扩展了功能之后,数据格式就会变成了这个样子,{"用户Id1":{"bgImage":"url1", "常用功能":"功能1, 功能2, ..."}, "用户Id2":{"bgImage":"url2", "常用功能":"功能2, 功能3, ..."}, ...},或者说变成了其他格式,不管变成了哪种格式,总之一句话,之前的那种格式已经满足不了需求了,所以解析这个文件内容的方法势必要进行改造。这就是不利于扩展的一个方面。

  方案二:

  其实我们可以根据用户Id将每一个用户的配置信息单独放到一个目录下,而每一个功能的配置信息,单独放到一个文件中。什么意思呢?其实就是这样:

  每一个用户的背景图片的配置信息都在对应用户Id文件夹下的bgImageConfig.txt文件中。这样只要给出用户Id和文件名,我们就将对应的文件内容读取直接返回给前端,无需解析文件内容。因为文件内容本身就是前端保存进来的,保存时我们也不会去关注具体保存了什么信息,只需要将内容写入文件即可。这样做还有一个好处,假设甲方增加了一个设置系统常用功能的需求,那么我们的目录就会变成这样:

  而我们的代码逻辑却不需要改变。与上面同样的道理,只要给出用户Id和文件名,我们就将文件内容直接返回给前端。我们甚至都不会去关注用户Id和文件名具体是什么,我们只需要将用户Id和文件名拼接起来,获取时,如果存在则直接读取返回;如果不存在,则返回为空或者作出提示。保存时,如果存在则直接覆盖;如果不存在,则创建然后写入内容。文件名完全可以由前端自己确定,前端保存配置信息时传递的文件名是什么,我们就保存该文件名对应的文件。获取时,只要给出对应的文件名,我们就将对应的文件内容返回即可。

  对于用户自己上传的图片,是统一放到一个目录中,还是分别放到用户Id对应的文件夹下,其实也是有讲究的。假设统一放到一个目录中,那假如两个用户上传的图片是不一样的,但是恰好文件名是一样的,那之前的图片岂不是会被覆盖了?所以还是分别放到用户Id对应的文件夹下比较好。

技术点:

  1、Servlet

    虽然是Java小白,但是基本的Servlet还是了解的,但是也仅仅停留在创建一个Servlet,测试一下GET、POST请求而已。

  2、Java上传文件

    这里是通过commons-fileupload-1.3.1.jar和commons-io-2.5.jar来实现的,代码是从网上找的,具体原理还是不太明白,这里就不贴代码了,等到最后记录一下项目的地址。

    还有一点需要注意的是,上传文件时的参数获取和普通的GET、POST请求的参数获取,还是不一样的。我们需要获取文件流,判断文件流是不是非文件域fileItem.isFormField(),如果是非文件域,则通过fileItem.getFieldName()获取参数名,通过new String[]{Streams.asString(fileItem.getInputStream())}获取参数值。

    另外需要注意的一点是,我们需要获取文件的上传路径,这里我们是通过request.getSession().getServletContext().getRealPath("")得到工程目录所对应的路径的,然后执行创建文件夹、写文件等操作。我们还需要返回前端一个可访问的Web路径,当然不能是功能目录所对应的绝对路径,这样前端是访问不到的。这里我们是通过request.getRequestURL()获取前端的请求路径,然后和前面保存的上传路径拼接起来的,这部分功能参考了这里

    关于获取文件的上传路径和返回前端一个可访问的Web路径,总感觉自己的做法太麻烦,抽空需要请教一下有没有简便的做法。

  3、Java的文件操作

    通过实现这么一个功能,对File类有了一个基本的认识。该类的对象可以代表一个具体的文件或文件夹。通过该类,可以实现创建文件夹mkdir()、mkdirs(),创建文件createNewFile(),判断文件或文件夹是否存在exists()等。这里参考的是火之光Java写入文件的几种方法

总结:

  虽然这个功能是做通了,但是还是有好多不明白的地方,还是应该再接着研究的,否则下次还是不知道怎么用。

  项目地址:https://github.com/Youwanwu/CloudServer.git

Servlet之保存用户偏好设置简单功能的实现的更多相关文章

  1. Android 保存用户偏好设置

    很多情况下都允许用户根据自己的习惯和爱好去设置软件,而我们需要保存这些设置,可以用一个专业保存用户偏好的类:SharedPreferences. 这个类是实现方法其实也就是创建和修改 XML 文件, ...

  2. 16_采用SharedPreferences保存用户偏好设置参数

    按钮事件 <Button android:id="@+id/button" android:layout_width="wrap_content" and ...

  3. 黎活明8天快速掌握android视频教程--16_采用SharedPreferences保存用户偏好设置参数

    SharedPreferences保存的数据是xml格式,也是存在数据保存的下面四种权限: 我们来看看 我们来看看具体的业务操作类: /** * 文件名:SharedPrecences.java * ...

  4. 【Qt官方例程学习笔记】Application Example(构成界面/QAction/退出时询问保存/用户偏好载入和保存/文本文件的载入和保存/QCommandLineParser解析运行参数)

    The Application example shows how to implement a standard GUI application with menus, toolbars, and ...

  5. Android之使用SharedPreferences保存用户偏好参数

    在Android应用中,我们常需要记录用户设置的一些偏好参数,,此时我们就需要用SharedPreferences和Editor将这些信息保存下来,在下次登录时读取. SharedPreference ...

  6. SharedPreferences保存用户偏好参数

    package com.example.administrator.myapplication; import android.content.Context; import android.cont ...

  7. iOS开发--应用设置及用户默认设置【2、读取应用中的设置】

            在上一节中,我们通过探讨应用的系统设置的基本功能,了解运用bundle捆绑包以及plist文件的基本开发.用户能够使用设置应用来声明他们的偏好设置,那么我们怎样去调用用户所设置的参数呢 ...

  8. iOS开发--应用设置及用户默认设置——转载

    [链接]iOS开发--应用设置及用户默认设置[1.bundlehttp://www.jianshu.com/p/6f2913f6b218 在iphone里面,应用都会在“设置”里面有个专属的应用设置, ...

  9. iOS: 偏好设置的详解和使用

    偏好设置的详解: 用途:主要用来存储用户系统的设备信息,但有的时候也可以在程序的任何地方用来存储数据,作为全局数据来访问,例如视图切换需要进行登录时. 偏好设置的写入: •很多iOS应用都支持偏好设置 ...

随机推荐

  1. 激活phpstorm10.0.1

    注册时选择“License server”输入“http://idea.lanyus.com/”点击“OK”快速激活JetBrains系列产品

  2. mmap学习

    mmap学习 内存页: Linux是以页为单位来管理物理内存的,一页大小一般等于4096字节.页容量越大,系统中可能存在的内存碎片就越多. mmap将一个磁盘上的文件或者对象映射进内存.文件被映射到多 ...

  3. MAC上的包管理利器

    Homebrew- MAC上的包管理利器 2013-07-01 16:25 by 黄博文, 76 阅读, 0 评论, 收藏, 编辑 包管理器是神马东西?让我们看看wikipedia上的介绍. In s ...

  4. [Android学习笔记4]四大应用组件之一:Service 上

    一.什么是Service 一个Service就是一个能够在后台执行长时操作的应用程序组件,并且不提供用户界面.一个应用程序组件能够启动一个Service,即使用户切换到另一个应用程序,这个Servic ...

  5. Java-调用抽象类中指定参数的构造方法

    abstract class person {  private String name;  private int age;  public person(String name,int age) ...

  6. Java中数组Arrays.binarySearch,快速查找数组内元素位置

    在数组中查找一个元素,Arrays提供了一个方便查询的方法.Arrays.binarySearch(): 测试列子: public class MainTestArray { public stati ...

  7. jquery表格提交验证

    在表格中的验证 1.body中的内容 <form action="http://www.qq.com" id="form1"><table w ...

  8. Android学习笔记(三)Android开发环境的搭建

    一.配置JAVA环境 二.配置Android开发环境 可以安装adt-bundle-windows,该压缩包一般自带Eclipse.或者安装Android Studio,要注意SDK的版本是否符合要求 ...

  9. JS 用角度换东南西北

    最近因为业务,正好需要用设备回传的角度值转成用户读得懂的文字形式 function toDirStr(num){ var num=parseInt(num) var N='北'; var E='东'; ...

  10. 关于map()与filter()

    def f1(a): if a == 3: pass else: return a*a li = [1,2,3,4] for i in filret(f1,li) print(i) def f1(a) ...