尚筹网-2.Maven问题及登陆功能

1. jdbc url地址参数

jdbc.url=jdbc:mysql://localhost:3306/atcrowdfunding190105?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8
  • rewriteBatchedStatements设置为true表示允许多条SQL语句使用“;”分开一起发送给数据库执行。
  • useUnicode和characterEncoding设置数据库连接使用的字符集是UTF-8

2. Maven Jar包下载失败相关【重要】

2.1 明显的下载失败

2.1.1 具体表现

在Maven仓库中如果看到jar包或其他相关文件是以“lastUpdated”作为扩展名结尾,说明jar包或其他相关文件下载失败。

2.1.2 原因分析

  • Maven在下载jar包的过程中,文件会以lastUpdated作为临时扩展名。文件下载完成后,Maven会将“lastUpdated”扩展名去掉。
  • 如果下载一半连不上网,导致下载失败,那么Maven就放任文件保持临时扩展名“lastUpdated”不管。
  • 当我们下一次强制要求Maven重新下载jar包时候,Maven看到这个文件以“lastUpdated”结尾,那么Maven就会无视“下载”命令。
  • 所以对于以“lastUpdated”为扩展名的文件需要手动删除,然后再让Maven重新下载。

2.1.3 应对方法

  • 基本做法:删除以“lastUpdated”结尾的文件,重新下载。
  • 问题:Maven仓库使用一段时间后,以“lastUpdated”结尾的文件会非常多,手动删除不现实。
  • 正确做法:借助clearLastUpdated.bat脚本文件批量处理。

2.1.4 clearLastUpdated.bat文件设置

  • 将clearLastUpdated.bat文件放入Maven仓库根目录
  • 使用文本编辑器打开
  • 修改下面两项
    • SET CLEAR_PATH=D:
    • SET CLEAR_DIR=D:\RepMaven0105

CLEAR_PATH设置为Maven仓库所在盘符

CLEAR_DIR设置为Maven仓库的根目录,一定要使用非中文没有空格的目录

2.1.5 需要注意的问题

  • 如果依赖信息写错,世界上并不存在这个依赖对应的jar包,无论重试多少次都无法下载成功。
  • 所以如果多次尝试下载,在网络和其他jar包下载都正常的情况下,特定某一个jar包始终下载失败,则很有可能是依赖信息写错了。

2.2 下载完成但内部文件损坏

2.2.1 具体表现

  • 表面上看起来,jar包并不是以“lastUpdated”结尾,表示已经下载完成。但是,程序编译或运行的时候报错。比如:找不到xxx类错误,而且通常这个类不是我们编写的;又或者找不到xxx方法,而且通常这个方法不是我们编写的。
  • 其他表现往往还体现为一些莫名其妙的错误,特别是往往和我们编写的代码没有直接关系。

2.2.2 确诊

  • 到Maven仓库中找到疑似下载失败的jar包
  • 使用文件校验工具文件校验
    • 打开工具
    • 将要验证的jar包拖拽进工具界面
    • 比较SHA1值
      • 一致:确定jar包下载成功,内部正确没问题
      • 不一致:确定jar包内部损坏

2.3 HASH加密原理

明文→加密→密文

HASH加密方式特点:

  • 包含一系列具体的加密算法,例如:MD5、SHA1、CRC32等等,彼此之间的区别是加密强度不同,具体体现为密文长度长短不一
  • 不可逆:不能通过密文反推出明文
  • 在算法确定的前提下,输入不变,输出不变
  • 在算法确定的前提下,输入发生非常细微的变化,输出一定会变,校验文件就是基于这个特性。服务器端加密结果如果和本地加密结果不一致,那么一定可以断定下载过程中数据发生了错误。
  • 在算法确定的前提下,不管输入的数据有多大还是多小,输出结果长度固定。

2.4 根据依赖信息定位jar包在仓库里位置

<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>

jar包所在目录:Maven仓库根目录/org/apache/commons/commons-lang3/3.1

2.5 强制重新下载jar包

2.5.1 删除jar包

根据上面描述找到jar包所在位置,删除jar包所在目录中的全部文件。

2.5.1 在IDE中执行Maven刷新

3. 显示首页

3.1 执行流程

3.3 创建PortalHandler

  • 所在工程:atcrowdfunding-admin-2-component

  • 全类名:com.rgh.crowd.funding.handler.PortalHandler

  • 代码

    @Controller
    public class PortalHandler {
    
        @RequestMapping("/index")
        public String showIndex(){
    
            //从数据加载页面需要显示的数据
    
            return "index-page";
        }
    }
    

3.3 创建index-page.jsp

  • 将原型index.html页面的内容复制进去。

  • 所在工程:atcrowdfunding-admin-1-webui

  • 文件位置:

3.4 调整index-page.jsp

<html lang="GB18030">改成<html lang="UTF-8">
    <meta charset="GB18030">改成<meta charset="UTF-8">
    添加<title>❤汇聚点滴的力量,成就非凡的伟业❤</title>

3.5 处理样式和JavaScript相关

3.5.1 第一步:样式和JavaScript文件

所在工程:atcrowdfunding-admin-1-webui

从原型中直接复制到项目中

3.5.2 第二步:刷新页面

此时应该能正常访问

4. 解决页面路径问题

4.1 方案一

将contextPath存入application域

  • 在一个自定义监听器中将context.getContextPath()返回值存入application域,属性名是appPath。
  • 在页面上使用${appPath}获取。
  • 路径写法成为:${appPath}/xxx/xxx/xxx

4.2 方案二

4.2.1 写法

<base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/"/>

4.2.2 注意点

  • base标签需要放在head标签内

  • base标签必须放在所有带路径的标签前面

  • serverName和serverPort之间必须有“:”

  • contextPath前:不能有“/”

    • 因为contextPath本身就是“/”开头的,再写会多一个,导致Cookie的路径不一致,进而导致Session不能正常工作
  • contextPath后:必须有“/”

    • 带路径的标签,如果路径以“/”开头,则不参考base标签。又因为具体标签中的路径和base标签中的路径拼起来以后必须是有效、完整的路径,所以“/”要放在base标签的路径最后

5. 登陆功能

5.1 修改登陆超链接

  • 所在工程:atcrowdfunding-admin-1-webui
  • 所在文件:/atcrowdfunding-admin-1-webui/src/main/webapp/WEB-INF/index-page.jsp
<ul class="nav navbar-nav navbar-right">
    <li><a href="login.html">登录</a></li>
    <li><a href="reg.html">注册</a></li>
    <li><a>|</a></li>
    <li><a href="admin/to/login/page.html">管理员登录</a></li>
</ul>

5.2 使用view-controller实现页面跳转

spring-web-mvc.xml文件中加入。注意:path属性要求必须带扩展名,后缀是html。

<!--
    @RequestMapping("/admin/to/login/page")
    public String toLoginPage() {
    return "admin-login";
    }
    -->
<mvc:view-controller path="/admin/to/login/page.html" view-name="admin-login"/>

5.3 登陆页面代码

admin-login.jsp

form表单

<form action="admin/do/login.html" class="form-signin" role="form">
    <h2 class="form-signin-heading"><i class="glyphicon glyphicon-log-in"></i> 管理员登录</h2>
    <p>${requestScope.MESSAGE}</p>
    <div class="form-group has-success has-feedback">
        <input
               type="text"
               name="loginAcct"
               class="form-control"
               id="inputSuccess4"
               placeholder="请输入登录账号" autofocus>
        <span class="glyphicon glyphicon-user form-control-feedback"></span>
    </div>
    <div class="form-group has-success has-feedback">
        <input
               type="text"
               name="userPswd"
               class="form-control"
               id="inputSuccess4"
               placeholder="请输入登录密码"
               style="margin-top:10px;">
        <span class="glyphicon glyphicon-lock form-control-feedback"></span>
    </div>

    <button class="btn btn-lg btn-success btn-block">登录</button>
</form>

5.4 登陆流程分析

5.5 MD5加密的工具方法

  • 所在工程:atcrowdfunding-admin-3-common
  • 全类名:com.atguigu.crowd.funding.util.CrowdFundingUtils
public class CrowdFundingUtils {

    /**
     * 判断Map是否有效
     * @param map 待验证的Map
     * @param <K>
     * @param <V>
     * @return true代表有效,false代表无效
     */
    public static <K,V> boolean mapEffective(Map<K,V> map){
        return map != null && map.size()>0;
    }

    /**
     * 判断集合是否有效
     * @param collection 待验证的集合
     * @param <E>
     * @return true代表有效,false代表无效
     */
    public static <E> boolean collectionEffective(Collection<E> collection){
        return collection != null && collection.size()>0;
    }

    /**
     * 判断字符串是否有效
     * @param source 待验证字符串
     * @return true表示有效,false表示无效
     */
    public static boolean stringEffective(String source){
        return source != null && source.length()>0;
    }

    /**
     * MD5加密工具方法
     * @param source 明文
     * @return 密文
     */
    public static String md5(String source){

        //判断传入的明文字符串是否有效
        if(!stringEffective(source)){
            throw new RuntimeException("明文不是有效字符串,请核对后再操作");
        }

        //声明StringBuilder待用
        StringBuilder builder = new StringBuilder();
        //准备字符数组
        char[] characters = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        String algorithm = "MD5";
        try {
            //执行加密的核心对象
            MessageDigest digest = MessageDigest.getInstance(algorithm);
            //将要加密的明文转换成字节数组的形式
            byte[] inputBytes = source.getBytes();
            //执行加密
            byte[] outputBytes = digest.digest(inputBytes);
            //遍历outputBytes
            for (int i = 0;i<outputBytes.length;i++){
                //获取当前字节数值
                byte b = outputBytes[i];
                //获取低4位的值
                int lowValue = b & 15;
                //获取高四位的值
                int hightValue = (b >> 4) & 15;
                //以高四位,低四位的值为下标从字符数组中获取对应字符
                char highCharacter = characters[hightValue];
                char lowCharacter = characters[lowValue];
                //拼接
                builder.append(highCharacter).append(lowCharacter);
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return builder.toString();
    }
}

5.6 handler方法

  • 所在工程:atcrowdfunding-admin-2-component
  • 全类名:com.atguigu.crowd.funding.handler.AdminHandler
@RequestMapping("/admin/do/login")
public String doLogin(@RequestParam("loginAcct") String loginAcct,
                      @RequestParam("userPswd")  String userPswd,
                      Model model,
                      HttpSession session){
    //调用adminService的login方法执行登陆业务逻辑,返回查询到的Admin对象
    Admin admin = adminService.login(loginAcct,userPswd);
    //判断admin是否为null
    if(admin == null){
        model.addAttribute("MESSAGE","登陆账号或密码不正确!请核对后再登陆");
        return "admin-login";
    }
    session.setAttribute("LOGIN-ADMIN",admin);
    return "admin-main";
}

注意:HttpSession要求导入servlet-api才能够正常使用

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <scope>provided</scope>
</dependency>

provided依赖不能传递,只能在有需要的工程单独加入

5.7 service方法

public Admin login(String loginAcct, String userPswd) {
    //根据loginAcct查询数据库
    AdminExample adminExample = new AdminExample();
    adminExample.createCriteria().andLoginAcctEqualTo(loginAcct);
    List<Admin> list = adminMapper.selectByExample(adminExample);
    if(!CrowdFundingUtils.collectionEffective(list)){//!false=true集合无效
        return null;
    }
    //获取唯一集合元素
    Admin admin = list.get(0);
    if(admin == null){
        return null;
    }
    //比较密码
    String userPswdDataBase = admin.getUserPswd();//数据中查的
    String userPswdBroswer = CrowdFundingUtils.md5(userPswd);//页面传的加密
    if(Objects.equals(userPswdBroswer,userPswdDataBase)){
        //密码相当登陆成功
        return admin;
    }
    return null;

需要在spring-persist-tx.xml配置文件中加入事务属性配置

<tx:method name="login" read-only="true"/>

5.8 后台主页面

  • 所在工程:atcrowdfunding-admin-1-webui

  • 文件位置:
  • 内容:

    <title>❤汇聚点滴的力量,成就非凡的伟业❤</title>
    </head>
    <body>
        <h1>后台主页面</h1>
        ${sessionScope['LOGIN-ADMIN'] }
    </body>
    </html>
    

6. 登陆的辅助功能

6.1 常量声明

  • 所在工程:atcrowdfunding-admin-3-common

  • 全类名:com.rgh.crowd.funding.util.CrowdFundingConstant

  • 内容:

    public class CrowdFundingConstant {
        public static final String ATTR_NAME_MESSAGE = "MESSAGE";
        public static final String ATTR_NAME_LOGIN_ADMIN = "LOGIN-ADMIN";
        public static final String MESSAGE_LOGIN_FAILED = "登录账号或密码不正确!请核对后再登录!";
        public static final String MESSAGE_CODE_INVALID = "明文不是有效字符串,请核对后再操作!";
        public static final String MESSAGE_ACCESS_DENIED = "请登录,再操作!";
    }
    

6.2 配置异常映射机制

  • 作用:将捕获到的异常类型和具体页面对应起来。在捕获到对应类型的异常后,跳转到对应页面。

  • 配置:XML方式(只能返回页面,很难兼容Ajax请求)

  • 配置:Annotation方式(兼容两种请求)

  • 所在工程:atcrowdfunding-admin-2-component

  • 全类名:com.rgh.crowd.funding.exception.CrowFundingExceptionResolever

  • 内容:

    @ControllerAdvice
    public class CrowFundingExceptionResolever {
        @ExceptionHandler(value=Exception.class)
        public ModelAndView catchException(Exception exception){
            ModelAndView mav = new ModelAndView();
            mav.addObject("exception",exception);
            mav.setViewName("system-error");
            return mav;
        }
    }
    

6.3 错误信息页面

system-error.jsp

<script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
    $(function(){
        $("#bakcBtn").click(function(){
            window.history.back();
        });
    });
</script>
<h1>${requestScope.exception.message }</h1>
<button id="bakcBtn" class="btn btn-lg btn-success btn-block">后退</button>

6.4 退出登陆操作

  • 所在工程:atcrowdfunding-admin-2-component
  • 所在类:com.rgh.crowd.funding.handler.AdminHandler
  • 内容:
@RequestMapping("/admin/logout")
public String logout(HttpSession session){ 
    session.invalidate();    
    return "redirect:/index.html";
}

6.5 登陆检出拦截器

说明:仅仅是临时使用,练习拦截器。将来使用SpringSecurity后将取消。

6.5.1 拦截器类

  • 所在工程:atcrowdfunding-admin-2-component

  • 全类名:com.rgh.crowd.funding.interceptor.LoginInterceptor

  • 内容:

    public class LoginInterceptor extends HandlerInterceptorAdapter{
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            HttpSession session = request.getSession();
            Admin admin = (Admin) session.getAttribute(CrowdFundingConstant.ATTR_NAME_LOGIN_ADMIN);
            if(admin == null){
          request.setAttribute(CrowdFundingConstant.ATTR_NAME_MESSAGE,CrowdFundingConstant.MESSAGE_ACCESS_DENIED);
                request.getRequestDispatcher("/WEB-INF/admin-login.jsp").forward(request,response);
                return false;
            }
            return true;
        }
    }
    

6.5.2 注册拦截器

  • 所在工程:atcrowdfunding-admin-1-webui

  • 配置文件:spring-web-mvc.xml

    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--设置当前要拦截的路径-->
            <mvc:mapping path="/**"/>
            <!--设置不需要拦截的路径-->
            <mvc:exclude-mapping path="/index.html"/>
            <mvc:exclude-mapping path="/admin/to/login/page.html"/>
            <mvc:exclude-mapping path="/admin/do/login.html"/>
            <mvc:exclude-mapping path="/admin/logout.html"/>
            <!--拦截器的bean-->
            <bean class="com.rgh.crowd.funding.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容