2.2 开发注册功能

本文详细介绍了如何分步骤实现一个Web应用的注册功能,包括用户访问注册页面、填写表单并提交、激活账号的整个流程。涉及到的技术点包括Thymeleaf模板引擎、MD5加密、邮件激活机制以及SpringMVC的Controller和Service层处理。同时,文章还展示了如何处理表单验证和错误信息展示,以及激活码的验证和账号状态更新。
摘要由CSDN通过智能技术生成


开发注册功能

一次注册请求拆分成三次请求:

第一次请求 用户访问注册页面,服务器接受请求返回注册页面;

第二次请求 用户填写表单,提交给服务器,服务器接受此次请求,调用对应的服务来处理用户提交的数据,如果数据有误(用户名存在,邮箱存在)就返回注册页面让用户重新填写,如果数据无误,则向用户发送一封激活邮件;

第三次请求 用户若数据有误,重复第二次请求 如果无误,点击激活邮件,再次访问服务器,服务器对其进行验证,(看用户是否存在,激活码是否正确)正确则激活,并且返回到登录页面 ,激活错误或者重复提交则返回到注册页面;

第一次请求 用户访问注册页面

1、编写loginController来处理请求,返回注册页面

  • 修改注册页面,使之能被Thymeleaf引擎解析,修改声明,相对路径
@Controller
public class LoginController {

    @RequestMapping(value = "/register",method = RequestMethod.GET)
    public String getRegister() {
        return "/site/register";
    }
}

2、修改注册页面和主页,使用Thymeleaf语法

  • 修改路径 把相对路径用@{}包起来

  • 修改主页的首页和注册的路径 提取头部复用 增加th:fragment 取一个别名 在register页面中引用提取的头部

  • <header class="bg-dark sticky-top" th:fragment="header">
    
    <header class="bg-dark sticky-top" th:replace="index::header">
    

引入jar包,生成随机字符串等处理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hnrWemge-1645443671426)(C:\Users\XL\AppData\Roaming\Typora\typora-user-images\image-20220221095932254.png)]

修改项目域名,暂时为本地路径

#community
community.path.domain=http://localhost:8080

建立一个工具类,方便生成随机字符串和处理加密的工作

  • MD5加密因为会生成一个固定的加密后的字符串,不安全,所以采用在用户密码后拼接一共字符串的方法
public class CommunityUtil {
    //生成随机字符串
    public static String generateUUID()
    {
        //把生成的字符串的-替换成空格
        return UUID.randomUUID().toString().replaceAll("-","");
    }

    //MD5加密加一段随机字符串提高安全性
    public static String MD5(String key)
    {
        //如果key为空则返回空
        if(StringUtils.isBlank(key))
        {
            return null;
        }
        //加密成十六进制字符串返回
        return DigestUtils.md5DigestAsHex(key.getBytes());

    }
}

第二次请求 用户填写表单

编写UserService对注册业务进行处理

  • 编写注册方法 返回类型为Map 用来保存处理的结果

  • 对账号为空,密码错误,邮箱已经被注册等问题进行判断提示

  • 执行注册,设置用户的详细信息 userid设置的是自增长,不需要手动添加

  • 最后调用UserMapper把用户信息插入到数据库中

    @Service
    public class UserService {
        @Autowired(required = false)
        private UserMapper userMapper;
    
        //注入域名和工程路径
        @Value("${community.path.domain}")
        private String domain;
        @Value("${server.servlet.context-path}")
        private String contextPath;
    
        @Autowired
        private TemplateEngine templateEngine;
    
        @Autowired
        private  MailClient mailClient;
    
        public User queryUserById(int userId)
        {
            return userMapper.queryById(userId);
        }
    
        //注册业务
        public Map<String,Object>  register(User user)
        {
            Map<String,Object> map=new HashMap<>();
            if(user==null)
            {
                throw new IllegalArgumentException("用户信息不能为空");
            }
            //验证用户名是否已经存在
            if(userMapper.queryByName(user.getUsername())!=null)
            {
                map.put("usernameMsg","用户名已经存在");
                return map;
            }
            //验证邮箱是否已经存在
            if(userMapper.queryByEmail(user.getEmail())!=null)
            {
                map.put("emailMsg","邮箱已经存在");
                return map;
            }
            //注册用户
            //保存用户随机字符串 截取5个
            user.setSalt(StringUtils.substring(CommunityUtil.generateUUID(),5));
            //保存密码
            String key=user.getPassword()+user.getSalt();
            user.setPassword(CommunityUtil.MD5(key));
            user.setType(0);
            user.setStatus(0);
            //激活码使用随机生成的字符串
            user.setActivationCode(CommunityUtil.generateUUID());
            //使用牛客网的头像库随机生成
            user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png",new Random().nextInt(1000)));
            user.setCreateTime(new Date());
            userMapper.InsertUser(user);
    
    
            //激活邮件
            Context context=new Context();
            context.setVariable("email",user.getEmail());
            // http://localhost:8080/community/activation/101/code
            String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode();
            context.setVariable("url",url);
            String content = templateEngine.process("/mail/activation", context);
            mailClient.sendMail(user.getEmail(), "激活账号", content);
            return map;
        }
    
    }
    

编写Controller处理用户提交数据的请求

@RequestMapping(value = "/register",method = RequestMethod.POST)
public String register(Model model, User user)
{
    Map<String, Object> map = userService.register(user);
    //为空说明注册成功,向用户返回一个结果跳转页面
    if(map==null|| map.isEmpty())
    {
        model.addAttribute("msg",
                "恭喜您注册成功我们已经向您发送了一封激活邮件,清尽快激活!");
        model.addAttribute("url","/index");
        return "/site/operate-result";
    }else {
        model.addAttribute("usernameMsg", map.get("usernameMsg"));
        model.addAttribute("passwordMsg", map.get("passwordMsg"));
        model.addAttribute("emailMsg", map.get("emailMsg"));
        return "/site/register";
    }

}

修改表单数据

  • 修改表单提交路径
  • 给每一个框取一个name,声明数据的名字,name要和controller中的User属性名对应,SpringMvc基于同名原则把值传为User。username
  • 注册没有成功,处理错误消息
  • 如果是错误返回主页,这时主页就需要显示刚才已经填好的信息;如果是直接访问,就显示空
  • 账号有问题返回账号错误信息,密码,邮箱同理
  • 错误信息是否显示依靠样式is-invalid 因此需要动态拼接
<!-- 内容 -->
<div class="main">
   <div class="container pl-5 pr-5 pt-3 pb-3 mt-3 mb-3">
      <h3 class="text-center text-info border-bottom pb-3">注&nbsp;&nbsp;册</h3>
      <form class="mt-5" method="post" th:action="@{/register}">
         <div class="form-group row">
            <label for="username" class="col-sm-2 col-form-label text-right">账号:</label>
            <div class="col-sm-10">
               <input type="text"
                     th:class="|form-control ${usernameMsg!=null?'is-invalid':''}|"
                     th:value="${user!=null?user.username:''}"
                     id="username" name="username" placeholder="请输入您的账号!" required>
               <div class="invalid-feedback" th:text="${usernameMsg}">
                  该账号已存在!
               </div>
            </div>
         </div>

第三次请求 激活注册账号

定义常量接口

usersERVICES实现接口

public interface CommunityConstant {

    /**
     * 激活成功
     */
    int ACTIVATION_SUCCESS = 0;

    /**
     * 重复激活
     */
    int ACTIVATION_REPEAT = 1;

    /**
     * 激活失败
     */
    int ACTIVATION_FAILURE = 2;
}
  • 先从数据库中获取该user的信息
  • 如果其状态status==1表示已经激活,返回重复激活
  • 否则激活码正确 更新用户状态为已经激活
  • 否则激活失败
//激活业务
public int activation(int userId,String code)
{
    User user = userMapper.queryById(userId);
    if(user.getStatus()==1)
    {
        return ACTIVATION_REPEAT;
    }else if(user.getActivationCode().equals(code))
    {
        userMapper.UpdateStatus(userId,1);
        return ACTIVATION_SUCCESS;
    }else {
        return ACTIVATION_FAILURE;
    }
}
  • 编写激活controller方法
  • @PathVariable 从路径中获取变量值
  • 调用service的激活方法根据返回值往modle里放入不同的信息 和跳转值
// http://localhost:8080/community/activation/101/code
@RequestMapping(path = "/activation/{userId}/{code}", method = RequestMethod.GET)
public String activation(Model model, @PathVariable("userId") int userId, @PathVariable("code") String code) {
    int result = userService.activation(userId, code);
    if (result == ACTIVATION_SUCCESS) {
        model.addAttribute("msg", "激活成功,您的账号已经可以正常使用了!");
        model.addAttribute("url", "/login");
    } else if (result == ACTIVATION_REPEAT) {
        model.addAttribute("msg", "无效操作,该账号已经激活过了!");
        model.addAttribute("url", "/index");
    } else {
        model.addAttribute("msg", "激活失败,您提供的激活码不正确!");
        model.addAttribute("url", "/index");
    }
    return "/site/operate-result";
}

编写方法处理login请求

@RequestMapping(value = "/login",method = RequestMethod.GET)
public String getLogin() {
    return "/site/login";
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值