1. 程式人生 > >######漏發郵件問題【###終歸是程式碼問題(測試出來的-不是直接可見的邏輯問題!!!try catch finally問題)。先耐心測試自身找原因,廣泛應用的都是成熟技術!

######漏發郵件問題【###終歸是程式碼問題(測試出來的-不是直接可見的邏輯問題!!!try catch finally問題)。先耐心測試自身找原因,廣泛應用的都是成熟技術!

===ssm整合JavaMail:漏發郵件問題【###終歸是程式碼問題(測試出來的-不是直接可見的邏輯問題!!!try catch finally問題)。】

=== ###知識點:【finally保證異常仍然需要執行的程式碼一定會執行!】

===最後程式碼:(只需要看insertUser方法)

 /**
     * 新增使用者
     * 手機號、郵箱、備註可空
     * 是否刪除、建立時間、修改時間為空,mapper層插入預設值
     * 姓名、角色id、登入名、密碼不為空
     * 登入名唯一, 登入名存在返回0
     * 插入成功返回自增主鍵
     * 其他錯誤返回-1
     */
    @Override
    public int insertUser(UserDO user, String rePassword,
                          Integer agencyId,
                          Integer advertiserId,
                          HttpServletRequest request) {
        int userMessageIsAvailable = this.checkUserMessage(user, rePassword);
        if (userMessageIsAvailable != 1) {
            return userMessageIsAvailable;
        }

        String salt = Long.toString(System.currentTimeMillis());
        ByteSource byteSource = ByteSource.Util.bytes(salt);
        user.setSalt(salt);
        Object md5Password = new SimpleHash("MD5", user.getPassword(), byteSource, 5);
        String password = user.getPassword();//設定加密密碼前,取出明文密碼。發郵件
        user.setPassword(String.valueOf(md5Password));
        int result = userMapper.insertSelective(user);//基本資訊。

        if(  result>0 ) {

                new Thread(){
                    @Override
                    public void run() {

//========================》freeMarker建立郵件內容:開始
                        Configuration configuration = freeMarkerConfigurer.getConfiguration();
                        //載入模板物件
                        Template template = null;
                        String fileName = null;//拿出來,finally內部可見。
                                //建立一個數據集
                        Map data = new HashMap<>();
                        MockMultipartFile multipartFile = null;
                        try {
                            template = configuration.getTemplate("mail.ftl");
                            //data需要的資料分析:圖片絕對路徑。
                            //String realPath = request.getServletContext().getRealPath("");
                            String realPath = request.getServletContext().getRealPath("/");
                            if (!realPath.endsWith(java.io.File.separator)) {
                                //linux下拿到的realPath不帶"\";Windows下帶
                                realPath = realPath + java.io.File.separator;
                            }
                            System.out.println("===》realPath:"+realPath);//E:\ClickCube\classes\artifacts\ClickCube_front_Web_exploded\

                            //防止圖片位置變化,每次發郵件,上傳一次mailLogo.png
                            InputStream inputStream = new FileInputStream(realPath+"resource/mailLogo/mailLogo.png");//
                            //不行換個MultipartFile的實現類試試======》
                            multipartFile = new MockMultipartFile("mailLogo.png", inputStream);
                            fileName = multipartFile.getName();

//                            add
//                            configuration.clearEncodingMap();
//                            configuration.clearSharedVariables();
//                            configuration.clearTemplateCache();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }finally { //》》》前面  出現任何異常,只要使用者插入成功,都要發郵件。
                            //### 【有時漏發郵件 就是沒有寫到finally裡導致的】》沒有執行發郵件方法。。。

                            String fileId = null;
                            String content = null;
                            String toMail = null;
                            try{
                                //===》沒連線VPN 會報錯 部分=== 開始
                                fileId = FastDFSUtil.uploadFile(multipartFile.getBytes(), fileName);//===》沒連線VPN 開始報錯。。。
                                //獲取伺服器寫在配置檔案中的頭地址
                                String filePathUrl = ReadPropertiesUtil.readFilePath();
                                //設定在伺服器上的絕對地址
                                String logoUrl = filePathUrl + "/" + fileId;
                                System.out.println("=====》logoUrl:" + logoUrl);
                                data.put("logoUrl", logoUrl);//ok

                                data.put("loginName", user.getLoginName());
                                data.put("password", password);//加密前取出的明文密碼。

                                content = FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
                                //========================》freeMarker建立郵件內容:結束
                                toMail = user.getEmail();
                                //===》沒連線VPN 會報錯 部分=== 結束
                            }catch (Exception e){
                                e.printStackTrace();
                            }finally {  //====》沒連線VPN 報錯。保證發郵件也要執行。。。
                                if(result>0){
                                    //MailUtils.sendMail("註冊郵件", content, toMail);//有些郵箱不能解析HTML。是不是content是String的原因?
                                    sendTemplateMail( content,toMail );//設定為html郵件。【使用Spring整合的Mail方式,不用原生JavaMail】
                                }
                            }

                        }


                    }//run執行緒體
                }.start();



        }//a==1 插入記錄成功。


        return user.getId();
    }

    //傳送模板郵件
    public void sendTemplateMail(String htmlText,String toMail) {
        MimeMessage msg=mailSender.createMimeMessage();
       try{
           MimeMessageHelper helper=new MimeMessageHelper(msg,false,"utf8");//由於是html郵件,不是mulitpart型別
           helper.setFrom("
[email protected]
"); helper.setTo(toMail); helper.setSubject("註冊成功-郵件"); helper.setText(htmlText, true);//是html郵件:true }catch (Exception e){ e.printStackTrace(); }finally { mailSender.send(msg);//有異常仍然發郵件。 System.out.println("成功傳送模板郵件"); } }

 

====之前導致問題的程式碼:

①測試發現:漏發的郵件,沒有執行發郵件程式碼。。。

②問題原因:

【### 只有一個try catch。try中程式碼過多,

####  前面程式碼出現異常,不能保證:“出現異常,後面仍然需要執行的程式碼(發郵件)”  仍然繼續執行!!!】

  /**
     * 新增使用者
     * 手機號、郵箱、備註可空
     * 是否刪除、建立時間、修改時間為空,mapper層插入預設值
     * 姓名、角色id、登入名、密碼不為空
     * 登入名唯一, 登入名存在返回0
     * 插入成功返回自增主鍵
     * 其他錯誤返回-1
     */
    @Override
    public int insertUser(UserDO user, String rePassword,
                          Integer agencyId,
                          Integer advertiserId,
                          HttpServletRequest request) {
        int userMessageIsAvailable = this.checkUserMessage(user, rePassword);
        if (userMessageIsAvailable != 1) {
            return userMessageIsAvailable;
        }

        String salt = Long.toString(System.currentTimeMillis());
        ByteSource byteSource = ByteSource.Util.bytes(salt);
        user.setSalt(salt);
        Object md5Password = new SimpleHash("MD5", user.getPassword(), byteSource, 5);
        String password = user.getPassword();//設定加密密碼前,取出明文密碼。發郵件
        user.setPassword(String.valueOf(md5Password));
        int a = userMapper.insertSelective(user);//基本資訊。

        if(  new Integer(a) !=null ) {

                new Thread(){
                    @Override
                    public void run() {

//========================》freeMarker建立郵件內容:開始
                        Configuration configuration = freeMarkerConfigurer.getConfiguration();
                        //載入模板物件
                        Template template = null;
                        //建立一個數據集
                        Map data = new HashMap<>();
                        try {
                            template = configuration.getTemplate("mail.ftl");
                            //data需要的資料分析:圖片絕對路徑。
                            //String realPath = request.getServletContext().getRealPath("");

                            String realPath = request.getServletContext().getRealPath("/");
                            if (!realPath.endsWith(java.io.File.separator)) {
                                //linux下拿到的realPath不帶"\";Windows下帶
                                realPath = realPath + java.io.File.separator;
                            }
                            System.out.println("===》realPath:"+realPath);//E:\ClickCube\classes\artifacts\ClickCube_front_Web_exploded\


                            //String logoUrl="http://"+localAddr+":"+localPort+contextPath+"/resource/mailLogo/mailLogo.png";//必須加http
                            //        logoUrl的IP不對。換個裝置就訪問不到Logot圖片了。IP總是伺服器本機的127.0.0.1
                            //解決思路:
                            // ①圖片寫到瀏覽器。
                            // ②拿到正確的伺服器IP【同一臺伺服器。網路變化:伺服器IP變化(所以只能傳送logo附件。本地顯示附件太麻煩)】
                            // ③logo圖片放到 fastDFS(穩定的檔案伺服器)上,再訪問遠端的圖片。

                            //防止圖片位置變化,每次發郵件,上傳一次mailLogo.png
                            InputStream inputStream = new FileInputStream(realPath+"resource/mailLogo/mailLogo.png");//
                            //不行換個MultipartFile的實現類試試======》
                            MockMultipartFile multipartFile = new MockMultipartFile("mailLogo.png", inputStream);
                            //
                            String fileName = multipartFile.getName();
                            //businessLicenseFileId等4個XXXFileId是要存到資料庫中的絕對ID,或者相對路徑,也是在伺服器中的相對地址
                            String fileId = FastDFSUtil.uploadFile(multipartFile.getBytes(), fileName);

                            //獲取伺服器寫在配置檔案中的頭地址
                            String filePathUrl = ReadPropertiesUtil.readFilePath();
                            //設定在伺服器上的絕對地址
                            String logoUrl = filePathUrl + "/" + fileId;
                            System.out.println("=====》logoUrl:" + logoUrl);
                            data.put("logoUrl", logoUrl);//ok

                            data.put("loginName", user.getLoginName());
                            data.put("password", password);//加密前取出的明文密碼。

                           /* //指定檔案輸出的路徑及檔名
                            File htmlFile = new File("D:\\freemarker_registerMail\\mail.html");
                            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile),"UTF-8"));
                            //輸出檔案
                            template.process(data, out);//ok
                            //關閉流
                            out.close();*/

                            String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
                            //========================》freeMarker建立郵件內容:結束
                            String toMail = user.getEmail();
                            //MailUtils.sendMail("註冊郵件", content, toMail);//有些郵箱不能解析HTML。是不是content是String的原因?
                            sendTemplateMail( content,toMail );//設定為html郵件。【使用Spring整合的Mail方式,不用原生JavaMail】
                        } catch (Exception e) {
                            e.printStackTrace();
                        }



                    }//run執行緒體
                }.start();



        }//a==1 插入記錄成功。


        return user.getId();
    }