• Java Web 项目学习(二) 开发注册功能


     访问注册界面:

      三层(Controller、Service、DAO) 只需要 Controller 就可以完成。

    • 在Controller下
      • 构建,LoginController。
      • 找到对应HTML界面,引入模板thymeleaf。做响应修改
        • 相对路径修改为模板样式 @{}
              <link rel="stylesheet" th:href="@{/css/global.css}" />
              <link rel="stylesheet" th:href="@{/css/login.css}" />
              <script th:src="@{/js/global.js}"></script>
              <script th:src="@{/js/register.js}"></script>
          View Code
        • 找到对应首页的HTML界面index.html,做对应修改,让其可以跳转到注册界面,同样是@{}替换

                          <!-- 功能 -->
                          <div class="collapse navbar-collapse" id="navbarSupportedContent">
                              <ul class="navbar-nav mr-auto">
                                  <li class="nav-item ml-3 btn-group-vertical">
                                      <a class="nav-link" th:href="@{/index}">首页</a>
                                  </li>
                                  <li class="nav-item ml-3 btn-group-vertical">
                                      <a class="nav-link position-relative" href="site/letter.html">消息<span class="badge badge-danger">12</span></a>
                                  </li>
                                  <li class="nav-item ml-3 btn-group-vertical">
                                      <a class="nav-link" th:href="@{/register}">注册</a>
                                  </li>
          View Code

          因为头部(导航栏)在每个页面复用,每个都修改,十分繁琐。因此复用一下。在index中起别名。将register中的header替换掉。
          index.html  <header class="bg-dark sticky-top" th:fragment="header"> th:fragment="" 起别名
          register.html <header class="bg-dark sticky-top" th:replace="index::header"> th:replace="index::header"     (两个冒号)

     提交注册数据:

      • 准备工作

        • 导入包   Commons Lang  用来判断为空、不合法的情况。(https://mvnrepository.com/)

        • 发邮件需要带激活连接,激活连接在我们网站内。所以在application.properties中定义链接。
        • 写一个工具类,提供方法以供我们使用。
          /**
           * 提供静态的方法,不用容器托管,直接调。
           *
           */
          public class CommunityUtil {
              //生成随机字符串
              public static String generateUUID(){
                  return UUID.randomUUID().toString().replaceAll("-"."");
              }
          
              //MD5 加密
              //用户密码 + salt  再做加密
              public static String md5(String key){
                  if(StringUtils.isEmptyOrWhitespaceOnly(key)){
                      return null ;
                  }
                  return DigestUtils.md5DigestAsHex(key.getBytes());
              }
          }
          View Code
      • UserService
        发邮件,针对用户,因此使用。注入相关信息。固定值的注入用 @Value(“”)
        @Service
        public class UserService implements CommunityConstant {
            @Autowired
            private UserMapper userMapper;
            @Autowired
            private MailClient mailClient;  //发邮件
            @Autowired
            private TemplateEngine templateEngine;   //模板引擎
        
        
            //发邮件,连接, 配置域名和项目名
            @Value("${server.servlet.context-path}")
            private String contextPath;
            @Value("${community.path.domain}")
            private String domain;
        
        
        
        
            //根据用户id查询用户名
            public User findUserById(int id){
                return userMapper.selectById(id);
            }
        
        
            public Map<String,Object> register(User user){
                Map<String,Object> map= new HashMap<>();
        
                //空值处理
                if (user == null){
                    throw new IllegalArgumentException("参数不能为空");
                }
                //以下是业务层面的错误,告诉他不对
                if(StringUtils.isEmptyOrWhitespaceOnly(user.getUsername())){
                    map.put("usernameMsg","账号不能为空");
                    return map;
                }
                if(StringUtils.isEmptyOrWhitespaceOnly(user.getPassword())){
                    map.put("passwordMsg","密码不能为空");
                    return map;
                }
                if(StringUtils.isEmptyOrWhitespaceOnly(user.getEmail())){
                    map.put("emailMsg","邮箱不能为空");
                    return map;
                }
                //验证账号
                User uExist =userMapper.selectByName(user.getUsername());
                if (uExist != null) {
                    map.put("usernameMsg","该账号已经存在");
                    return map;
                }
        
                //验证邮箱
                uExist = userMapper.selectByEmail(user.getEmail());
                if (uExist != null) {
                    map.put("emailMsg","该邮箱已经被注册");
                    return map;
                }
        
                //注册用户
                user.setSalt(CommunityUtil.generateUUID().substring(0,5));
                user.setPassword(CommunityUtil.md5(user.getPassword()+ user.getSalt()));
                user.setStatus(0);
                user.setType(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/comminity/activation/userid/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;
            }
        
        
        
            //成功激活。重复激活没有意义,激活码是伪造的,
            public int activation(int userId , String code){
                //查到用户,判断状态是否已激活,匹配激活码
                User user = userMapper.selectById(userId);
                if(user.getStatus() ==1){
                    return ACTIVATION_REPEATION;
                }
                else if(user.getActivationCode().equals(code)){
                    userMapper.updateStatus(userId,1);
                    return ACTIVATION_SUCCESS;
                }else {
                    return  ACTIVATION_FAILURE;
                }
        
            }
        }
        View Code

      • LoginController
        • 注入UserService,按照逻辑写对应代码。
              @RequestMapping(path = "/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("target","/index");
                      return "/site/operate-result";
                  }else{
                      model.addAttribute("usernameMsg",map.get("usernameMsg"));
                      model.addAttribute("emailMsg",map.get("emailMsg"));
                      model.addAttribute("passwordMsg",map.get("passwordMsg"));
                      return "/site/register";
                  }
              }
        • 修改对应HTML(index)
          • 常规操作,xmlns=“”...”   替换相对路径。 修改替换头部使用index的header。
          • 对表单进行操作 <form class="mt-5" method="post" th:action="@{/register}"> 同时注意需要有提交按钮 <button type="submit">
          • 在input添加name属性,name=“XX” 。其中XX应与Controller中User中的属性对应。密码邮箱情况同理。确认密码不用,是前台的工作 。
            <input type="text" class="form-control" id="username" name="username" placeholder="请输入您的账号!" required>
          • (成功跳转 首页,通过 site/operate-result)
            <!-- 内容 -->
                    <div class="main">
                        <div class="container mt-5">
                            <div class="jumbotron">
                                <p class="lead" th:text="${msg}">您的账号已经激活成功,可以正常使用了!</p>
                                <hr class="my-4">
                                <p>
                                    系统会在 <span id="seconds" class="text-danger">8</span> 秒后自动跳转,
                                    您也可以点此 <a id="target" th:href="@{${target}}" class="text-primary">链接</a>, 手动跳转!
                                </p>
                            </div>
                        </div>
                    </div>
            View Code
          • (失败返回注册界面,提示信息 ,site/index)  这段确认密码对应部分也需要修改

            <input type="text" class="form-control"
                   th:value="${user!= null? user.username:''}"
                   id="username" name="username" placeholder="请输入您的账号!" required>

            这段确认密码不需要修改

            <div class="invalid-feedback" th:text="${usernameMsg}">该账号已存在!</div>

            div的框是否显示通过input中的is-invalid 控制,因此我们需要动态的判断,因此修改最终的对应input为

            <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>
        • 遇到的各种错误
          • There was an unexpected error (type=Internal Server Error, status=500). Error resolving template [/register], template might not exist or might not be accessible by any of the configured Template Resolvers
            在controller中的返回值    return "/register";  而应该是 return "/site/register";  导致找不到返回界面了。
            想不明白为什么在  @RequestMapping(path = "/register",method = RequestMethod.POST)  就不需要加路径。可能是spring自动对应了。

          • 提示已发送邮件,但是登陆邮箱没收到
            ——换个邮箱试试!我一开始用的是QQ邮箱。可能发的太多了。后面收不到,垃圾箱里也没有。后来重新申请的网易邮箱就好了。

             

    激活注册账号:

    • 激活执行后有三种状态。1 激活成功,2 重复激活(无意义),3 激活码伪造。 定义工具类下的CommunityConstant 用来表示状态。接口就可以。常量一般采用大写。ctrl+shif+u大写转换。
      public interface CommunityConstant {
          /**
           * 激活成功
           */
          int ACTIVATION_SUCCESS =0;
      
          /**
           * 重复激活
           */
          int ACTIVATION_REPEATION =1;
      
          /**
           * 激活失败
           */
          int ACTIVATION_FAILURE =2;
      }
      View Code
    • 在UserService中加一个方法。改变用户状态。
      //成功激活。重复激活没有意义,激活码是伪造的,
          public int activation(int userId , String code){
              //查到用户,判断状态是否已激活,匹配激活码
              User user = userMapper.selectById(userId);
              if(user.getStatus() ==1){
                  return ACTIVATION_REPEATION;
              }
              else if(user.getActivationCode().equals(code)){
                  userMapper.updateStatus(userId,1);
                  return ACTIVATION_SUCCESS;
              }else {
                  return  ACTIVATION_FAILURE;
              }
      
          }
      View Code
    • 在Controller当中,处理请求。请求的页面是发送的那个邮件,邮件就是一个html。
      • 声明路径按照Service所给出的。从路径中取值传入代码中使用@PathVariable("userId") int userid,
      • 无论成功还是失败,都给用户提示(跳转到提示页面,页面根据不同情况做不同反映),成功跳到登录界面,失败跳到首页。
        // http://localhost:8080/comminity/activation/userid/code
            @RequestMapping(path="activation/{uderId}/{code}",method = RequestMethod.GET)
            public String avtivation(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("target","/login");
        
                }else if (result ==ACTIVATION_REPEATION){
                    model.addAttribute("msg","无效操作,该账号已激活过!");
                    model.addAttribute("target","/index");
        
                }else{
                    model.addAttribute("msg","激活失败,您提供的激活码不正确!");
                    model.addAttribute("target","/index");
                }
                return "/site/operate-result";
            }
      • 对login界面做的声明(controller)的处理(html文件)
            @RequestMapping(path = "/login", method = RequestMethod.GET)
            public String getLoginPage(){
                return "site/login";
            }

        login.html 引入模板,并做常规修改。同时在index.html中,添加登录界面连接。

            <a class="nav-link" th:href="@{login}">登录</a>
    • 遇到的各种问题:

      • This application has no explicit mapping for /error。 There was an unexpected error (type=Not Found, status=404). No message available
        错误原因 :多写了html <a class="nav-link" th:href="@{login.html}">登录</a>  应该为 <a class="nav-link" th:href="@{login}">登录</a> 

      • 点击邮箱的连接无法跳转正确的界面。(其实是第二大部的错误)
        ——url的对应拼错了。在Service中使用的是  context.setVariable("key",url);   而在对应的HTML中采用的是  <a th:href="${url}">此链接</a>,   这样就导致按照url索引出来的值为null。无法进行跳转。更改Service中的变量  context.setVariable("url",url);   就可以完成跳转。

  • 相关阅读:
    Levmar 配置
    函数前加static与不加static的区别
    关于形如--error LNK2005: xxx 已经在 msvcrtd.lib ( MSVCR90D.dll ) 中定义--的问题分析解决
    Latex 算法Algorithm
    matlab 曲线拟合
    生成eps图形
    libSVM在matlab下的使用安装
    spring 事务管理笔记
    集合框架
    小程序 滑动弹窗阻止主页面滑动
  • 原文地址:https://www.cnblogs.com/codinghard/p/14823737.html
Copyright © 2020-2023  润新知