美文网首页
关于一个小项目

关于一个小项目

作者: 只不过33 | 来源:发表于2020-05-22 13:32 被阅读0次

       在《由Javaweb所想到的》这篇文章里已经说了很多的理论知识。现在是时候做一个小小的项目,来对这些理论做一次检验了。

       首先说明一下,我要做的这个“小项目”,并不是一个真正的项目,它乃是一个赤裸裸的http服务集合。也就是说我不会去写前端。所有的一切我都会通过postman这个软件,或者直接通过浏览器的地址栏去访问测试这些http服务。

     当然这个项目不会太复杂,http服务不会太多。我也不想一开始就直接列出http的各种服务,因为我感觉这也太枯燥乏味了一点。这个工程首先需要的是一个大的轮廓。那么它就是一个简单的博客系统。各位博客网站放心好了。只不过是个简单的练习。肯定不是觊觎博客这块蛋糕,不过话说这块蛋糕当年真的还是蛮大的啊。当然了在这个讲究团队合作的年代,一个人想在一个行业里有所建树那已经很难了。最起码博主我已经不存一丁点幻想了,所以纯粹就是练习而已了。

       嗯,首先我先建了一个文件夹,取名叫做数据库。事实上,这件事情很简单,比我写这么多的字要简单多了。但是说实话,我不想去做。为什么?因为文字我们人类已经用了几千年了。而文件夹我们只用了几十年。所以这就叫做惯性?懂吗?惯性。。。。。。

      所以要我说实话的话,我宁愿用文字去写上十万八千个字也不愿意动手去建一个文件夹。“建一个文件夹“说实话,这句话真的有点怪怪的。

      可惜啊,本博主实在天资有限,不能靠卖字真乃一大遗憾。只能靠编程为生。虽说编程这家伙古板刻薄,真的没有文学精灵古怪那么可爱。但是有一大好处,那就是编程这家伙它不会动,就像那手里的玩具一样,想玩便玩,不想玩放一边即可。此话怎讲?就是说这家伙跟砖头差不多,搬来倒去从来不变。对于这种不变的家伙,那在人类面前不就是个板凳吗?

       这么看来,编程也有可爱的地方啊。

      所以本博主就不得不委曲求全,勉为其难地开始动工了。

      然后填一张表

项目名称:简单博客

项目http服务简单介绍:这个也不用一个个介绍,概括到位即可。

发送验证码 参数:手机号

登录   参数:手机号 验证码

查看别人的文章列表 参数:无

查看别人的文章  参数:文章id

查看自己的文章  参数:文章id

发表文章 参数:文章题目 文章正文

修改文章 参数:文章id

对文章进行打分 参数:文章id 参数

查看自己的文章列表  参数:无

删除文章 参数:文章id

因为名字叫做简单博客,所以功能做的也很简单,总共也就10个http访问。

特点分析:主要使用自增主键id进行文章识别

项目的数据库结构:这个有辅助软件,使用E-R图即可。填写参考什么什么E-R图即可。

因为是java编程 所以不妨先想一想需要哪些承载数据的pojo类吧。

文章类 字段是 id 文章名 文章正文 分数 用户id

用户类 字段是 id 手机号码

用户不设置用户名,所以每个人都是匿名的。

也许需要做哪些http服务,基本上已经决定了数据库基本包含哪些数据了。

项目的用户认证方式:

使用token认证,在第一次用户登录的时候,给用户发送token,以后每次用户访问可以不用登录,只要带着此token进行访问就行。token失效后仍然需要重新登录才行。

首先是token的生成,有时候token的生成需要传一个独特的参数。

其实这个参数本身也是能够作为一个token的。因为这个参数本来就是独一无二的。

那么为什么不直接使用它呢?

那是因为这个参数虽然独特,但是它有一个致命的缺点,就是没有保密性。因为token要具备两个特点,一个就是独特性,另一个就是保密性。所以token其实就是相当于 是用户名和密码的二合一的这么一个东西。而且验证token的时候都是在内存发生的,跟数据库那是一点儿关系都没有。而验证用户名和密码的时候往往要通过查询数据库来验证的。那么有人说了,把所有的用户名和密码都放内存中,验证的时候不是也和数据库没有关系了吗?这样子也是可以的。但是这就需要解决一个问题,即内存与数据库数据同步的问题。所以综合来看token的方式性能上还是要好一些。

       那么token是如何产生的呢?有没有具体的代码呢?这个网上是有的,而且还多的是。

       比如:

/**  

 * 生成Token的工具类:  

 */  

package red.hearing.eval.modules.token;  

import java.security.MessageDigest;  

import java.security.NoSuchAlgorithmException;  

import java.util.Random;  

import sun.misc.BASE64Encoder;  

/**  

 * 生成Token的工具类  

 * @author zhous  

 * @since 2018-2-23 13:59:27  

 *  

 */  

public class TokenProccessor {  

     private TokenProccessor(){};  

private static final TokenProccessorinstance =new TokenProccessor();  

    public static TokenProccessor getInstance() {  

        return instance;  

    }  

    /**  

     * 生成Token  

     * @return  

     */  

    public String makeToken() {  

Stringtoken = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";  

         try {  

MessageDigestmd =MessageDigest.getInstance("md5");  

            byte md5[] =  md.digest(token.getBytes());  

BASE64Encoderencoder =new BASE64Encoder();  

            return encoder.encode(md5);  

        } catch (NoSuchAlgorithmException e) {  

            // TODO Auto-generated catch block  

            e.printStackTrace();  

        }  

         return null;  

    }  

代码出处:http://www.mamicode.com/info-detail-2347408.html?__cf_chl_jschl_tk__=5187b4cbae1ce3f798484c0ee3a1cb33215a22dd-1590133965-0-ATNIrRMRioittH1p_Z638x7nrCtoffpYUDzRMZA2twEJdn592NfR_B50ArAOfIxVxoBpH28XZeU9ilqEgIyLy3yYVVHmlmIMfAcLBStOAomDTJYUJQkB_jexv6F_x6DdXTVsrgQbYDXbmmrpUWq0_BW-1A7R_gyWFOYQUxleBTld2RsMs9idiv0-8GuYcg88BlMKptgMlGBUXuc-OEdLhUyPVVMmksTihpslziPcp8njeLJulgh5SK_xQ58phGonMYaFIhPWyS_4o5fRpL_M9JBu4Z2rVmEWqz6p7c21j0ItOUgxKxTFPjApfGtcNcxjCA

比如这个程序中生成的token,是一段“杂乱无章”的字符串。那么这样的token 除非是被黑客拦截。要不然以现在的技术手段几乎是“猜”不出来的。如果说普通人设置的密码是普通的锁,那么这个字符串可以说是保险柜上的锁了。

那么当生成token之后,就需要传给客户端了。如何传给客户端,token是可以放在cookie中的。不管是不是放在cookie中,一般都是放在http的header中的。而与客户端相关的信息,一般都放在session中。所以或许将token放置到session中就可以了。而这只是一种猜想,具体还要看网上一些代码。于是我从网上找来了代码。

/**  

 *   

 */  

package red.hearing.eval.modules.token;  

import javax.servlet.http.HttpServletRequest;  

import org.apache.commons.lang3.StringUtils;  

/**  

 * Token的工具类  

 * @author zhous  

 * @since 2018-2-23 14:01:41  

 *  

 */  

public class TokenTools {  

    /**  

     * 生成token放入session  

     * @param request  

     * @param tokenServerkey  

     */  

    public static void createToken(HttpServletRequest request,String tokenServerkey){  

Stringtoken =TokenProccessor.getInstance().makeToken();  

        request.getSession().setAttribute(tokenServerkey, token);  

    }  

    /**  

     * 移除token  

     * @param request  

     * @param tokenServerkey  

     */  

    public static void removeToken(HttpServletRequest request,String tokenServerkey){  

        request.getSession().removeAttribute(tokenServerkey);  

    }  

    /**  

     * 判断请求参数中的token是否和session中一致  

     * @param request  

     * @param tokenClientkey  

     * @param tokenServerkey  

     * @return  

     */  

    public static boolean judgeTokenIsEqual(HttpServletRequest request,String tokenClientkey,String tokenServerkey){  

Stringtoken_client =request.getParameter(tokenClientkey);  

        if(StringUtils.isEmpty(token_client)){  

            return false;  

        }  

Stringtoken_server = (String) request.getSession().getAttribute(tokenServerkey);  

        if(StringUtils.isEmpty(token_server)){  

            return false;  

        }  

        if(!token_server.equals(token_client)){  

            return false;  

        }  

        return true;  

    }  

代码出处:http://www.mamicode.com/info-detail-2347408.html?__cf_chl_jschl_tk__=5187b4cbae1ce3f798484c0ee3a1cb33215a22dd-1590133965-0-ATNIrRMRioittH1p_Z638x7nrCtoffpYUDzRMZA2twEJdn592NfR_B50ArAOfIxVxoBpH28XZeU9ilqEgIyLy3yYVVHmlmIMfAcLBStOAomDTJYUJQkB_jexv6F_x6DdXTVsrgQbYDXbmmrpUWq0_BW-1A7R_gyWFOYQUxleBTld2RsMs9idiv0-8GuYcg88BlMKptgMlGBUXuc-OEdLhUyPVVMmksTihpslziPcp8njeLJulgh5SK_xQ58phGonMYaFIhPWyS_4o5fRpL_M9JBu4Z2rVmEWqz6p7c21j0ItOUgxKxTFPjApfGtcNcxjCA

在使用servlet的时候。可以直接操作session 从而返回数据就可以了。使用springmvc的时候,也是如此,

是的,是时候展示我从网上找的代码了,代码如下:

/**

* 读取所有cookie 

* 注意二、从客户端读取Cookie时,包括maxAge在内的其他属性都是不可读的,也不会被提交。浏览器提交Cookie时只会提交name与value属性。maxAge属性只被浏览器用来判断Cookie是否过期 

* @param request 

* @param response 

*/@RequestMapping("/showCookies")publicvoidshowCookies(HttpServletRequestrequest,HttpServletResponseresponse){Cookie[]cookies=request.getCookies();//这样便可以获取一个cookie数组  if(null==cookies){System.out.println("没有cookie=========");}else{for(Cookiecookie:cookies){System.out.println("name:"+cookie.getName()+",value:"+cookie.getValue());}}}/** 

* 添加cookie 

* @param response 

* @param name 

* @param value 

*/@RequestMapping("/addCookie")publicvoidaddCookie(HttpServletResponseresponse,Stringname,Stringvalue){Cookiecookie=newCookie(name.trim(),value.trim());cookie.setMaxAge(30*60);// 设置为30min  cookie.setPath("/");System.out.println("已添加===============");response.addCookie(cookie);}/** 

* 修改cookie 

* @param request 

* @param response 

* @param name 

* @param value 

* 注意一、修改、删除Cookie时,新建的Cookie除value、maxAge之外的所有属性,例如name、path、domain等,都要与原Cookie完全一样。否则,浏览器将视为两个不同的Cookie不予覆盖,导致修改、删除失败。 

*/@RequestMapping("/editCookie")publicvoideditCookie(HttpServletRequestrequest,HttpServletResponseresponse,Stringname,Stringvalue){Cookie[]cookies=request.getCookies();if(null==cookies){System.out.println("没有cookie==============");}else{for(Cookiecookie:cookies){if(cookie.getName().equals(name)){System.out.println("原值为:"+cookie.getValue());cookie.setValue(value);cookie.setPath("/");cookie.setMaxAge(30*60);// 设置为30min  System.out.println("被修改的cookie名字为:"+cookie.getName()+",新值为:"+cookie.getValue());response.addCookie(cookie);break;}}}}/** 

* 删除cookie 

* @param request 

* @param response 

* @param name 

*/@RequestMapping("/delCookie")publicvoiddelCookie(HttpServletRequestrequest,HttpServletResponseresponse,Stringname){Cookie[]cookies=request.getCookies();if(null==cookies){System.out.println("没有cookie==============");}else{for(Cookiecookie:cookies){if(cookie.getName().equals(name)){cookie.setValue(null);cookie.setMaxAge(0);// 立即销毁cookie  cookie.setPath("/");System.out.println("被删除的cookie名字为:"+cookie.getName());response.addCookie(cookie);break;}}}}

//通常开发时先用以下的代码将获取的cookie进行封装

/**

    * 根据名字获取cookie 

    * @param request 

    * @param name cookie名字 

    * @return 

    */publicCookiegetCookieByName(HttpServletRequestrequest,Stringname){Map<String,Cookie>cookieMap=ReadCookieMap(request);if(cookieMap.containsKey(name)){Cookiecookie=(Cookie)cookieMap.get(name);returncookie;}else{returnnull;}}/** 

    * 将cookie封装到Map里面 

    * @param request 

    * @return 

    */privateMap<String,Cookie>ReadCookieMap(HttpServletRequestrequest){Map<String,Cookie>cookieMap=newHashMap<String,Cookie>();Cookie[]cookies=request.getCookies();if(null!=cookies){for(Cookiecookie:cookies){cookieMap.put(cookie.getName(),cookie);}}returncookieMap;}

代码出处:https://www.jianshu.com/p/a44b5781aa46

但是以上前两段代码好像并不符合我的需求。session的存在与客户端浏览器是否关闭有关系。那么是否说明session就是只适合于浏览器上的应用呢?如果是安卓应用,那是不是要使用另外一种内存呢?

那么问题出现了,那就是生成的token应该存放在哪里?。。。。。。其实这很可能是一个错误问题。。。。。。那是因为可能服务器端根本就不存储token。

从网上看了很多token的相关资料,感觉各个做法差别很大。大概就像是装修房子一样,几万块钱也能装修,十几万也能装修,而几十万几百万也是装修。或许没有绝对的安全。或许要具体情况具体来分析。如果只是作为少数人不涉及到金钱的一个应用。如果没有那么大的厉害关系,可能简单使用一下就可以。如果涉及到大的厉害关系。那么就应当注意一下了。

      下面使用真名讲一个小故事。

      http 在提供http服务的时候。是需要识别客户端的。如果是这么一种情况,http服务器发送一根管子给http客户端。然后这个管子永远坏不了。并且别的人无法撕开这根管子。如果是这种模型,那么只需要在管子连好之后,服务器对客户端识别一次即可。因为识别之后,服务器记住这根管子就行了。

       可是现实是这样子的。管子太贵了,也太少了。管子只能租不能买。

即使你这个服务器和客户端之间安好了这么一根管子。服务器和客户端通完信之后,就得把管子给拆了,然后归还。那么有人说了,我不好容易租一回管子,那我就让服务器和客户端多说几句话可以吗?说它个三天三夜。设计者早就想好了这种情况。所以这种情况是不被允许的。因为管子宝贵啊。所以公司规定了,安好管子之后。必须客户端先说话,而且只能说一句话,而且这句话不能超过10个字。客户端说完之后,服务器端说。服务器也是只能说一句话,而且这句话不能超过20个字。服务器说完之后,就得马上归还管子。再想说话,再租管子就是了。

       虽然管子很贵,但是客户端有钱啊,客户端于是就说了:“服务器,没事,咱两个尽情地聊,不要担心租管子的事情,我已经办了年卡,这一年可以不限次数随便租管子的”。然后客户端就和服务器愉快自由自在地聊起天了。服务器一见客户端这么热情,顿时非常感动。其实客户端是有很多的,而服务器其实只有一个。服务器亲眼见了各种各样的客户端。有的客户端一辈子只来找它聊一句或者几句,便在也不见这个客户端的影子了。有的客户端则可能天天来找它聊天,一天聊好几万句也是有的。但是更多的是那种偶尔来一次,或者隔几天来一次然后聊几句的那种客户端。不管怎么样,客户端每天过来聊天的次数,那可真是无法预测的。不过整体来说还算是均衡的。就像大马路上行人的密度一样,没有办法精确估计未来某一个时间的密度。但是总体来说行人的密度一般是可以估计在一个范围之内的,当然发生极端的情况下例外。而且上面所说的行人密度,其实还符合一个函数曲线的,就是那个著名的概率曲线。 

        不论这个曲线是什么样子的,总而言之每个客户端来聊天的次数是不一样的。由于管子是通用的,而且在计算机世界中,又没有所谓的个性,所以事实上所有的客户端几乎是一模一样的。所以每次安好管子的时候。服务器端都要根据客户端说出的话进行判断,那么它是怎么判断的呢?其实它是用一个小本子来解决这个问题的。

        从公司那里借来管子的时候,管子上印有客户端的一些信息,比如上网号码啊等等。而服务器端把这些都记在了这个本子上。当客户端说话的时候,服务器端根据客户端说的话里带的一个暗号 就从自己那本子上找,服务器端找啊找,     很快它就根据那暗号在那个本子上找到了那个暗号所对应的信息,原来上网号是XXX。于是服务器端知道了自己已经已经和这个上网号在半个小时内聊了50句了。所以这分明就是一个典型的“好客户端”啊。于是服务器热情地答话了。服务器就是这样,假如它从它那个小本上,查出此客户端以前从来没有来聊过天的话。那么它就会冷冰冰地说:“对不起客户端,你还没告诉我您叫什么名字,密码是多少” 本来客户端就想知道今天的天气,没想到得到这样的一个回答。所以客户端很沮丧,也没办法只能再和服务器通一次信。先告诉服务器自己的用户名密码再说。

       这种搞个小本子的做法也是可以的。但是这个小本子上的内容太容易被擦掉了,而且小本子也是很贵的啊。

于是服务器开始想别的主意了。“最近客户端不给钱了啊,所以小本子还是少买吧。”服务器想。于是服务器突然灵机一动想到:“那么干脆,让客户端多发点暗号过来吧,我直接看暗号得了。”所以从此以后这个服务器经常受到客户端很多暗号,它一看暗号就知道这个客户端的一些情况了。比如是不是第一次来聊天的等。

       当然了暗号是发过来了,服务器也得有眼力劲去看呢,其实服务器虽然没钱买本子,但是眼力劲还是有的。

它收到了暗号,马上就开始琢磨了,这暗号这么眼熟,肯定是我亲自制作的啊。当然只看一眼也是不行的,它把暗号的包装层层打开,于是“图穷而匕首现”打开之后它说:“没错这就是 最原来的东西啊”

       那么为什么要把匕首包在图里面呢?在历史书中这个问题可能比较简单。那么在整个过程中,哪些需要被包在地图里面呢?首先,图是不少的,但是不是每张图里面都有一个匕首。其次匕首放在图里面,可能有几个原因,一个是要验证算法。一个是为了保密匕首。   那么问题来了,匕首为什么要保密?用户在登录的时候给服务器的用户名密码显然都没有保密(意为加密)啊。那么怎么服务器给用户发的这个就需要保密了呢?其实很简单,因为它这个保密之后才算是密码,不保密之前那叫名字。所以即使从对等的角度来说,客户端给服务器发送的是密码,那么服务器给客户端也应该发密码才对。即使这密码是他下次还要查看的。

        所以也可以说,多给客户端发的暗号,就是随机生成的密码。然后发给了客户端。所以这里的加密的作用可能就是生成一个密码。    不过这密码是服务器为客户端定制的密码。

项目使用的中间件:比如springboot shiro springcloud tomcat等

那么以前说过,为了降低javaweb开发的难度,很多第三方公司开发出了一些中间件。

这些中间件就像一个保姆一样,帮助程序员从吃饭到洗衣服。。。总而言之,是能管的都管了。

接下来就看程序员的了。。。

那么这些“保姆”们到底都管了哪些事情呢?

比如,springboot都管了哪些事情呢?

现在开发一个javaweb,用到的“保姆”太多了。那么springboot这个“保姆”,她呢其实就是就是一个专门介绍别的“保姆”来工作的一个“保姆”。有了这样一个“保姆”,再来请其他“保姆”来干活那就方便的多了。不用自己一个一个麻烦地去找了。而且这个“保姆”找来的“保姆”都是非常可靠的。

所以这个项目会先请这个springboot这个“保姆”

然后在让这个“保姆”去请springmvc,mybatis,shiro,redis,rabbitqp这些“保姆”。

而这些“保姆”在系统上的安装,一般来说都是比较简单的。因为就像一款合格的应用软件一样。安装一般并没有太多需要注意的事情。只要运行成功了,基本就是正确的。

项目的开发周期:

项目的开发大致计划以及预备计划:

项目的开发工具:

其实本博主一直有个疑问没有想通。那就是为什么已经有Eclipse还有人要制造出Ideal。也许是为了赚钱吧。

总而言之,作为编辑软件,从txt到word最后又到Eclipse然后又到Ideal。变化真的挺大的。但是千变万变,代码的“心”是不变的。颇有一种“我看世事多变幻,世事看我却依然”的感觉。

项目的备份策略:

项目的迭代策略:

项目的前端框架:

未完待续

相关文章

  • 承接项目开发,毕业论文it项目

    有没有要写ios项目,微信小程序项目,网页开发项目,安卓开发项目,都可以找我哈。论文中的关于it的项目也可以找我哦...

  •  小玩具:UITableView-ZCTableCellHeig

    引 小玩具的Git传送门.这是一个缓存cell高度的小玩具.目前在自己项目中使用. 关于在tableview的使用...

  • 销售高手养成系列十二:别拿产品说明书当作解决方案

    关于解决方案,我有这样一个小故事,在曾经做过的咨询案例当中,就遇到过这样的一次,项目分析会。会上,该项目的项目经理...

  • iOS小知识点03

    关于图形绘制 今天在项目中有一个小需求,需要在视图上绘制一个圆,内部有一个点,点不能超出圆外,于是找了一些关于图形...

  • 微信小程序踩坑

    本次开发微信小程序第一个版本,遇到如下问题: 关于小程序里引入iconfont 原有H5项目中iconfont.c...

  • HBase实操:HBase-Spark-Read-Demo 分享

    前言:本文是一个关于Spark读取HBase的一个小demo,简单了解一下~ 相关代码: 项目用到的 pom.xm...

  • setValue-forKey小记

    关于NSObject的setValue forKey的一个小tip 这两天重构项目的认证接口,接口的大概功能是,要...

  • 项目反思

    从好几个月前开始的一个关于医院回访系统的项目,项目倒是一个很普通的项目,复杂点的可能是这个项目有关于事业单位的一个...

  • 项目管理_05 大项目管理的几点吐槽

    最近参加了一个很大的项目,关于这个项目有几点槽,作为以后工作中的借鉴。 这个项目关于一个硬件产品研发及上市,涉及硬...

  • 5班039 北望月第1课作业#Judy's公众号价值变现训练营#

    序言/ 忝言自己算是半个前媒体人,其实是心虚的。关于自媒体,关于新媒体,自己也有涉猎,但仅作为工作项目中一个小模块...

网友评论

      本文标题:关于一个小项目

      本文链接:https://www.haomeiwen.com/subject/ealqahtx.html