Spring Boot整合邮件服务,从零开始

现在很多网站,实现登录或者注册的时候都会用到验证码之类的方式确保安全,Spring Boot,接触Spring Boot没多久,今天完成了Spring Boot 整合邮件服务实现利用邮箱完成注册的功能


这里给一个测试访问地址:180.76.99.142:8080,
所有注释以及全部代码都在下面,方便随时查阅

下面开始从零搭建

1、创建数据库

数据库名:springemail
在这里插入图片描述

2、idea创建一个maven工程pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <name>EmailPro</name>
    <groupId>site.tian</groupId>
    <artifactId>EmailPro</artifactId>
    <version>1.0</version>
    <!--Spring Boot父依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
    </parent>

    <dependencies>
        <!--邮件服务-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <!--web模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!--引入连接池druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>
        <!--添加log4j不然德鲁伊配置项目无法启动-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!--引入自动生成get set方法,还可以使用日志-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--添加jdbc启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--添加数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
        <!--引入通用mapper的启动器,包括了mybatis,注意:如果之前使用的是mybatis启动器,要在@MapperScan重新导包-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>
        <!--加入thymeleaf启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--测试的启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
    <!--打成jar包-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

在这里插入图片描述

3.工程目录结构

功能虽小但五脏俱全 静态文件下载地址:http://180.76.99.142/jt.zip

4、login页面(其实没必要这么多,纯属好看,登陆注册都在这里面)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
   <head>
      <title>Astronauts sign up & login Form a Flat Responsive Widget Template :: xmoban.cn </title>
      <!-- Meta tags -->
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <meta name="keywords" content=" Astronauts sign up & login Form Responsive Widget, Audio and Video players, Login Form Web Template, Flat Pricing Tables, Flat Drop-Downs, Sign-Up Web Templates, Flat Web Templates, Login Sign-up Responsive Web Template, Smartphone Compatible Web Template, Free Web Designs for Nokia, Samsung, LG, Sony Ericsson, Motorola Web Design"
         />
      <script>
         addEventListener("load", function() { setTimeout(hideURLbar, 0); }, false); function hideURLbar(){ window.scrollTo(0,1); }
      </script>
      <!-- Meta tags -->
      <!--pop-ups-->
      <link th:href="@{~/css/popuo-box.css}" rel="stylesheet" type="text/css" media="all" />
      <!-- //pop-ups-->
      <!--stylesheets-->
      <link th:href="@{~/css/style.css}" rel='stylesheet' type='text/css' media="all">
      <!--//style sheet end here-->
      <link href="//fonts.googleapis.com/css?family=Barlow:300,400,500" rel="stylesheet">
   </head>
   <body>
      <h1 class="header-w3ls">
         登录 或者~ 注册
      </h1>
      <div class="art-bothside">
         <div class="mid-cls">
            <div class="art-right-w3ls">
               <h2>Astronauts sign up and login</h2>
               <p>consectetur adipiscing elit, sed do eiusmod tempor incididunt Lorem ipsum dolor sit amet</p>
               <form id="myForm" th:action="reg" method="post">
                  <div class="main">
                     <div class="form-left-to-w3l">
                        <input type="text" name="username" placeholder="用户名" required="">
                     </div>
                     <div class="form-right-w3ls">
                        <input type="email" name="email" placeholder="注册邮箱~ ~ " required="">
                     </div>
                  </div>
                  <div class="main">
                     <div class="form-left-to-w3l">
                        <input type="password" name="password" placeholder="Password" id="password" required="">
                        <div class="clear"></div>
                     </div>
                     <div class="form-right-w3ls ">
                        <input type="password" placeholder="Confirm Password" id="confirm_password" required="">
                     </div>
                  </div>
                  <div class="btnn">
                     <button th:id="submit" type="submit">注册</button>
                     <span class="btn-block" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}" style="color: red"></span>
                  </div>
               </form>
               <div class="banner-agileits-btm">
                  <div class="w3layouts_more-buttn">
                     <h3>Already have an account..? <a href="#small-dialog1 " class="play-icon popup-with-zoom-anim">login</a></h3>
                  </div>
                  <div id="small-dialog1" class="mfp-hide w3ls_small_dialog wthree_pop">
                     <div class="agileits_modal_body">
                        <!--login form-->
                        <div class="letter-w3ls">
                           <form id="TowForm"  action="login" method="post">
                              <div class="form-left-to-w3l">
                                 <input type="text" name="username" placeholder="Name" required="">
                              </div>
                              <div class="form-right-w3ls">
                                 <input type="email" name="email" placeholder="Email" required="">
                              </div>
                              <div class="form-right-w3ls ">
                                 <input type="password" name="password" placeholder="Password" required="">
                              </div>
                              <div class="btnn">
                                 <button th:id="login" type="submit">登录</button><br>
                              </div>
                           </form>
                           <div class="clear"></div>
                        </div>
                        <!--//login form-->
                     </div>
                  </div>
               </div>
            </div>
            <div class="art-left-w3ls">
               <img th:src="@{~/images/right1.jpg}" class="img-fluid" alt="">
            </div>
         </div>
      </div>
      <div class="copy">
         <p>&copy;2020 Astronauts sign up & login Form. All Rights Reserved | Design by
      </div>
      <!--js working-->
      <script th:src='@{~/js/jquery-2.2.3.min.js}'></script>
      <!--//js working-->
      <script>
         var password = document.getElementById("password")
           , confirm_password = document.getElementById("confirm_password");
         
         function validatePassword(){
           if(password.value != confirm_password.value) {
             confirm_password.setCustomValidity("Passwords Don't Match");
           } else {
             confirm_password.setCustomValidity('');
           }
         }
         password.onchange = validatePassword;
         confirm_password.onkeyup = validatePassword;
      </script>
      <!--//scripts-->
      <script th:src="@{~/js/jquery.magnific-popup.js}"></script>
      <!-- //pop-up-box -->
      <script>
         $(document).ready(function () {
         	$('.popup-with-zoom-anim').magnificPopup({
         		type: 'inline',
         		fixedContentPos: false,
         		fixedBgPos: true,
         		overflowY: 'auto',
         		closeBtnInside: true,
         		preloader: false,
         		midClick: true,
         		removalDelay: 300,
         		mainClass: 'my-mfp-zoom-in'
         	});
         
         });
      </script>
<script>
   $("#submit").click(function () {
      $("#myForm").submit();
   });
   $("#login").click(function () {
      $("#TowForm").submit();
   })
</script>
   </body>
</html>

4.1 、登陆成功后主页面main其实就是从session中取出用户名

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
欢迎您:[[${session.user.username}]]
</body>
</html>

5、yml.xml 文件

#设置默认端口
server:
  port: 8080

#设置启动时加载控制器
spring:
  mail:
    host: smtp.126.com #发送邮件服务器
    username: [email protected] #发送邮件的邮箱地址,这里设置成你们自己的就行
    password: ~~xxxxxxxx~~  #客户端授权码,不是邮箱密码,网易的是自己设置的,百度搜索网易授权码操作获取
    properties.mail.smtp.port: 465 #465或者994
    from: [email protected] # 发送邮件的地址,和上面username一致
    #下面配置有兴趣可以自行查阅
    properties.mail.smtp.starttls.enable: true
    properties.mail.smtp.starttls.required: true
    properties.mail.smtp.ssl.enable: true
    default-encoding: utf-8
  mvc:
    servlet:
      load-on-startup: 1
  datasource: #配置数据源
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/springemail?characterEncoding=utf8
    username: "root"
    password: "tiantian" #这里有一个坑,这种方式的配置数据库即使数据库密码正确,若数据库密码是由纯数字组成的,依然会报错
    type: com.alibaba.druid.pool.DruidDataSource #指定数据源
  thymeleaf: #关闭缓存,防止更改页面不能即使刷新
    cache: false
    mode: HTML5
    encoding: utf-8
#mybatis配置
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: site.tian.pojo
  configuration: #驼峰命名法配置
    map-underscore-to-camel-case: true
#静态资源的访问要放在资源文件夹中才不会被过滤掉,如:static,Public

6、连接数据库还需要配置数据源

package site.tian.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
@Configuration
public class DruidConfig {
    /*配置数据库*/
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druid() {
        return new DruidDataSource();
    }

}

7、为了防止非授权登录,这里简单用拦截器配置一下

package site.tian.interceptor;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String user = (String)request.getSession().getAttribute("user");
        if(user == null){
            request.setAttribute("msg","您没有权限,请先登录");
            request.getRequestDispatcher("/login").forward(request,response);
            return false;
        }else {
            return true;
        }
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

8、把拦截器配置到容器中

package site.tian.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import site.tian.interceptor.LoginInterceptor;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    /*添加拦截器,添加到最上面最好*/
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**")
                .excludePathPatterns("/","/checkCode","/reg","/login","/js/**","/css/**","/images/**");
    }
    @Override
    /*设置默认跳转的请求视图*/
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("login");
        registry.addViewController("/login").setViewName("login");
    }
}

9、创建实体类

package site.tian.pojo;

import lombok.Data;
@Data
public class User {
    private Long id;
    private String username;
    private String password;
    private String email;
    /**
     * 状态:0代表未激活,1代表激活
     */
    private Integer status;
    /**
     * 利用UUID生成一段数字,发动到用户邮箱,当用户点击链接时
     * 在做一个校验如果用户传来的code跟我们发生的code一致,更改状态为“1”来激活用户
     */
    private String code;
}

10、OK上面都是准备工作,下面步入正题

10.1

controller

package site.tian.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import site.tian.email.UUIDUtils;
import site.tian.pojo.User;
import site.tian.service.UserService;

import javax.servlet.http.HttpServletRequest;

@Controller
public class LoginController {
    @Autowired
    private UserService userService;

    /*注册*/
    @RequestMapping("/reg")
    public String res(User user, Model model) {
        user.setStatus(0);
        String code = UUIDUtils.getUUID() + UUIDUtils.getUUID();
        user.setCode(code);
        userService.register(user);
        model.addAttribute("msg", "注册成功前往邮箱激活!");
        return "login";
    }

    /**
     * 校验邮箱中的code激活账户
     * 首先根据激活码code查询用户,之后再把状态修改为"1"
     */
    @RequestMapping(value = "/checkCode")
    public String checkCode(String code) {
        User user = userService.checkCode(code);
        System.out.println(user);
        //如果用户不等于null,把用户状态修改status=1
        if (user != null) {
            user.setStatus(1);
            //把code验证码清空,已经不需要了
            user.setCode("");
            System.out.println(user);
            userService.updateUserStatus(user);
        }
        return "login";
    }

    @RequestMapping("/login")
    public String login(User user, HttpServletRequest request) {
        if (user.getPassword() != null && user.getEmail() != null && user.getUsername() != null) {
           User token= userService.login(user);
            request.getSession().setAttribute("user",token);
            return "main";
        }else {
            return "login";
        }
    }

}

10.2 、配置email主要配置有以下几个类

接口

package site.tian.email;

public interface MailService {

    void sendHtmlMail(String to, String subject, String content);
}

实现类

package site.tian.email;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

@Service
public class MailServiceImpl implements MailService {
    /*开启日志*/
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private JavaMailSender mailSender;
    /**
     * 配置文件中我的qq邮箱
     */
    @Value("${spring.mail.from}")
    private String from;

    /**
     * 发送HTML邮件
     * @param to 收件者
     * @param subject 邮件主题
     * @param content 文本内容
     */
    @Override
    public void sendHtmlMail(String to,String subject,String content) {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = null;
        try {
            helper = new MimeMessageHelper(message, true);
            helper.setFrom(from);
            helper.setTo(subject);
            helper.setTo(to);
            helper.setText(content, true);
            mailSender.send(message);
            //日志信息
            logger.info("邮件已经发送。");
        } catch (MessagingException e) {
            logger.error("发送邮件时发生异常!", e);
        }
    }
}

验证码实现工具类

package site.tian.email;

import java.util.UUID;

public class UUIDUtils {
    public static String getUUID(){
        return UUID.randomUUID().toString().replace("-","");
    }
}

10.3 、业务接口和实现类

接口

package site.tian.service;

        import site.tian.pojo.User;

public interface UserService {
    public void register(User user);

    User checkCode(String code);

    void updateUserStatus(User user);

    User login(User user);
}

实现类

package site.tian.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import site.tian.email.MailService;
import site.tian.mapper.UserMapper;
import site.tian.pojo.User;
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MailService mailService;
    @Override
    public void register(User user) {
        userMapper.insert(user);
        //获取激活码
        String code = user.getCode();
        System.out.println("code:"+code);
        //主题
        String subject = "来自天天网站的激活邮件";
        //激活码是我们点击邮件链接之后根据激活码查询用户,如果存在说明一致,将用户状态修改为“1”激活,有用户来访问服务器
        //上面的激活码发送到用户注册邮箱
        String context = "<a href='http://127.0.0.1:8080/checkCode?code="+code+"'>激活请点击:"+code+"进行激活您的账号</a>";
        //发送激活邮件
        mailService.sendHtmlMail(user.getEmail(),subject,context);
    }

    @Override
    public User checkCode(String code) {
        return userMapper.checkCode(code);
    }

    @Override
    public void updateUserStatus(User user) {
        userMapper.updateUserStatus(user);
    }

    @Override
    public User login(User user) {
        return userMapper.login(user);
    }
}

10.4、mapper文件及对应xml

接口

package site.tian.mapper;


import site.tian.pojo.User;

public interface UserMapper  {

    void insert(User user);

    User checkCode(String code);

    void updateUserStatus(User user);

    User login(User user);
}

xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="site.tian.mapper.UserMapper">
    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user (username,password,status,code,email) VALUES(#{username},#{password},#{status},#{code},#{email}) ;
    </insert>
    <update id="updateUserStatus">
        UPDATE user SET status = #{status},code=#{code} WHERE id = #{id} ;
    </update>
    <select id="checkCode" resultType="site.tian.pojo.User">
        select * from user where code=#{code}
    </select>
    <select id="login" resultType="site.tian.pojo.User">
        select * from user where status=1 and username=#{username} and email=#{email} and password=#{password}
    </select>
</mapper>

11、上述是所有代码,完结

发布了5 篇原创文章 · 获赞 5 · 访问量 184

猜你喜欢

转载自blog.csdn.net/weixin_44078653/article/details/103999615