SSM整合demo黑马旅游网-------2.注册功能

上一节,我们已经将基本环境配置完成,接下来正式整合

1. 将项目前端代码页面载入

在这里插入图片描述

2. 功能分析

2.1 register.html

  • 使用 js完成表单验证,即鼠标离开输入框就判断输入是否合法
  • 使用ajax完成表单提交
  • 注册成功,跳转到成功页面

2.2 web层

  • 获取表单提交数据
  • 封装User对象
  • 调用service完成注册
  • 根据返回,提示信息
        成功 即跳转
        不成功,提示用户已存在

2.3 service层

  • 调用mapper层根据用户名查询用户
         存在,返回false
        不存在,调用mapper保存用户信息

2.4 UserMapper层

  • Boolean findByUserName(String username);
  • void saveUser(User user);

3. register.html

在这里插入图片描述
这是整个regiester.html需要验证的,只需要将每个跳转改成对应的路径即可

4. SSM整合

4.1 工厂整合

将session工厂交给Spring容器管理,只需要从容器中获取执行操作的Mapper实例即可

applicationContext.xml

 <!--加载jdbc.properties-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--配置mybatis的sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:sqlMapConfig.xml"/>
    </bean>

    <!--扫描Mapper,让Spring容器产生Mapper类-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.ssmtravel.mapper"/>
    </bean>

4.2 事务控制

将事务控制交给spring容器进行声明式事务控制

applicationContext.xml

	......
	......
	......
	
    <!--头部添加命名空间,粘贴其他的,直接修改相应的名字即可-->
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    ......
    ......
    ......
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
	......
	......
	......
	......
	......
	......
	<!--配置声明式事务控制-->
    <!--平台事务管理-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 配置事务增强-->
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!-- 切点表达式-->
    <!--* com.ssmtravel.service.Impl.*.*(..)
        public :修饰符省略
        *: 返回值类型、包名、类名、方法名可以使用星号* 代表任意
        ..:参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表
           包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类

    -->
    <!--事务织入-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.ssmtravel.service.Impl.*.*(..))"/>
    </aop:config>
    

5. 验证用户名是否存在

只有这个是需要访问后端,其他验证均只是简单验证。

5.1 register.html

		// *********************************** 验证用户名 ***********************************
			var username = document.getElementById("username");
			username.onblur = function () {
				xiaoyan_username();
			}

			function xiaoyan_username() {
				//2.定义正则
				var reg_username = /^\w{8,20}$/;

				//3.判断,给出提示信息
				var flag = reg_username.test(username.value);
				if (flag) {
					//用户名合法
					$("#username").css("border", "");
					$.ajax({
						type:'POST',
						url:"/ssm-travel/user/selectByUserName",
						data:"username="+username.value,
						dataType:"json",
						success: function(data) {
							if(data == "success"){
								$("#errorMsg").css("visibility","hidden");
								$("#username").css("border", "");

							}else{
								$("#username").css("border", "1px solid red");
								// username.value="用户名已经存在";       //让用户名输入框为空
								$("#errorMsg").css("visibility","visible");
								$("#errorMsg").html(data)
								$("#username").focus();//把焦点给用户名输入框
								flag = false

							}
						}
					});

				} else {
					//用户名非法,加一个红色边框
					$("#username").css("border", "1px solid yellow");
				}



				return flag;

			}


5.2 mapper层

  • UserMapper.java

src\main\java\com\ssmtravel\mapper\UserMapper.java

    // 判断用户是否已经存在
    @Select("select * from tab_user where username = #{username}")
    Boolean findByUserName(String username);

    // 保存用户
    @Insert("insert into tab_user values()")
    void saveUser(User user);
  • UserMapper.xml

这时候即可创建 src\main\resources\com\ssmtravel\mapper\UserMapper.xml

<mapper namespace="com.ssmtravel.mapper.UserMapper">

    <insert id="saveUser">
        insert into tab_user (username, password, name, birthday, sex, telephone, email, status, code)
        values (#{username},#{password},#{name},#{birthday},#{sex},#{telephone},#{email},#{status},#{code});
    </insert>
 
</mapper>

5.3 service层

  • 创建接口
    UserService.jave
package com.ssmtravel.service;

import com.ssmtravel.domain.User;

public interface UserService {

    // 判断用户是否已经存在
    Boolean findByUserName(String username);

    // 保存用户
    void saveUser(User user);

}


  • 创建实现 UserServiceImpl.java
package com.ssmtravel.service.Impl;

import com.ssmtravel.domain.User;
import com.ssmtravel.mapper.UserMapper;
import com.ssmtravel.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @title: UserServiceImpl
 * @Author Qian
 * @Date: 2022/4/14 16:00
 * @Version 1.0
 */
@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;


    public Boolean findByUserName(String username) {
        Boolean aBoolean = userMapper.findByUserName(username);
        return aBoolean;
    }


    public void saveUser(User user) {
        userMapper.saveUser(user);
    }
}

5.4 web层

package com.ssmtravel.controller;



import com.fasterxml.jackson.databind.ObjectMapper;
import com.ssmtravel.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;


/**
 * @title: UserContorller
 * @Author Qian
 * @Date: 2022/4/14 16:09
 * @Version 1.0
 */
@Controller
@RequestMapping("/user")
public class RegisterContorller {

    private String err_msg = null;
    @Autowired
    private UserService userService;

    // ******************************* 一.注册 ****************************************
    @RequestMapping(value = "/selectByUserName",produces={"application/json; charset=UTF-8"})
    @ResponseBody
    public String selectByUserName(String username) throws IOException {
        Boolean byUserName = userService.findByUserName(username);
        if (byUserName != null) {
            err_msg = "用户名已存在";
        } else {
            err_msg = "success";
        }
        ObjectMapper objectMapper = new ObjectMapper();
        return valueAsString = objectMapper.writeValueAsString(err_msg);
    }
}

通过jackson转换json格式字符串,回写字符串:
ObjectMapper objectMapper = new ObjectMapper();
String valueAsString = objectMapper.writeValueAsString(err_msg);

5.5 效果

在这里插入图片描述

6. 异步提交表单

采用异步提交表单

6.1 图片验证码

页面显示验证码,需要生成验证码,主要到有一个 src=“checkCode”,所以需要先创建一个工具类生成图片验证码,同时创建一个CkeckCodeController,同时存入session,当用户提交表单时,从session获取验证码和前端提交的验证码比较验证即可。

在这里插入图片描述

  • CheckCodeUtils.java 工具类

网上搜索

package com.ssmtravel.utils;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class CheckCodeUtils {

    public static final String RANDOMCODEKEY = "CHECKCODE_SERVER";//放到session中的key
    private Random random = new Random();
    private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生的字符串

    private int width = 80;//图片宽
    private int height = 26;//图片高
    private int lineSize = 40;//干扰线数量
    private int stringNum = 4;//随机产生字符数量

    /**
     * 生成随机图片
     */
    public void getRandcode(HttpServletRequest request,
                            HttpServletResponse response) {
        HttpSession session = request.getSession();
        //BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
        //产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
        Graphics g = image.getGraphics();
        g.fillRect(0, 0, width, height);
        g.setFont(new Font("Times New Roman",Font.ROMAN_BASELINE,18));
        g.setColor(getRandColor(160, 200));
        //绘制干扰线
        for(int i=0;i<=lineSize;i++){
            drowLine(g);
        }
        //绘制随机字符
        String randomString = "";
        for(int i=1;i<=stringNum;i++){
            randomString=drowString(g,randomString,i);
        }
        session.removeAttribute(RANDOMCODEKEY);
        session.setAttribute(RANDOMCODEKEY, randomString);
        g.dispose();
        try {
            //将内存中的图片通过流动形式输出到客户端
            ImageIO.write(image, "JPEG", response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*
     * 获得字体
     */
    private Font getFont(){
        return new Font("Fixedsys",Font.CENTER_BASELINE,18);
    }
    /*
     * 获得颜色
     */
    private Color getRandColor(int fc,int bc){
        if(fc > 255)
            fc = 255;
        if(bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc-fc-16);
        int g = fc + random.nextInt(bc-fc-14);
        int b = fc + random.nextInt(bc-fc-18);
        return new Color(r,g,b);
    }

    /*
     * 绘制字符串
     */
    private String drowString(Graphics g,String randomString,int i){
        g.setFont(getFont());
        g.setColor(new Color(random.nextInt(101),random.nextInt(111),random.nextInt(121)));
        String rand = String.valueOf(getRandomString(random.nextInt(randString.length())));
        randomString +=rand;
        g.translate(random.nextInt(3), random.nextInt(3));
        g.drawString(rand, 13*i, 16);
        return randomString;
    }
    /*
     * 绘制干扰线
     */
    private void drowLine(Graphics g){
        int x = random.nextInt(width);
        int y = random.nextInt(height);
        int xl = random.nextInt(13);
        int yl = random.nextInt(15);
        g.drawLine(x, y, x+xl, y+yl);
    }
    /*
     * 获取随机的字符
     */
    public String getRandomString(int num){
        return String.valueOf(randString.charAt(num));
    }
}

  • CheckCodeController.java

新建CheckCodeController.java文件,主要控制验证码的生成及点击图片变换验证码

package com.ssmtravel.controller;

import com.ssmtravel.utils.CheckCodeUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


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

/**
 * 验证码
 */
@Controller
public class CheckCodeController {
	/**
	 * 获取生成验证码显示到页面
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value="/checkCode")
	public void checkCode(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		//设置相应类型,告诉浏览器输出的内容为图片
		response.setContentType("image/jpeg");

		//设置响应头信息,告诉浏览器不要缓存此内容
		response.setHeader("pragma", "no-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expire", 0);



		CheckCodeUtils checkCodeUtils = new CheckCodeUtils();
		try {
			checkCodeUtils.getRandcode(request, response);//输出图片方法
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

6.2 异步提交表单

// *********************************** 异步提交表单 *********************************
			$(function(){
				$(".submit").click(function () {
					var options = {
						type: "POST",
						url:"/ssm-travel/user/addUser",
						data:$("#registerForm").serialize(), // 序列化参数
						dataType: "json",
						error: function(request) {
							return false;
						},

						success: function(data) {
							if (data == "success"){
								$("#errorMsg").css("visibility","hidden");
								// 如果成功,则跳转注册成功页面
								location.href = "/ssm-travel/register_ok.html";

							}else {
								$("#errorMsg").css("visibility","visible");
								$("#errorMsg").html(data);
							}

						}
					};
					// 校验所有都为 true,则使用ajax提交表单
					if (xiaoyan_password() && xiaoyan_email() &&
							xiaoyan_name() && xiaoyan_telephone() && xiaoyan_birthday()){
						$.ajax(options);
					}
					return false;
				});

			});

6.3 mapper层

src\main\java\com\ssmtravel\mapper\UserMapper.java

.........
.........
.........
 // 激活邮箱,验证激活码code
    Boolean updateStatus(String code);

这时候即可创建 src\main\resources\com\ssmtravel\mapper\UserMapper.xml

<update id="updateStatus">
        update tab_user
        set status = 'Y'
        where code = #{code};
    </update>

6.4 service层

  • UserService.jave 接口
......
......
......
 // 激活邮箱
    Boolean activeUser(String code);
  • UserServiceImpl.java 实现
    @Override
    public Boolean activeUser(String code) {
        Boolean aBoolean = userMapper.updateStatus(code);
        return aBoolean;
    }

6.5 web层

// 1. 验证用户名是否存在
......
......
......
 // 2. 验证通过  添加用户
    @RequestMapping(value = "/addUser",produces={"application/json; charset=UTF-8"})
    @ResponseBody
    public String addUser(User user,HttpSession session,String check) throws IOException {

        // 先校验验证码,验证码通过,则进行下面操作,不通过则失败
        // 验证码

        // 从session、中获取验证码
        String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
        // 为了保证验证码使用一次就重新生成
        session.removeAttribute("CHECKCODE_SERVER");
        if (checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)) {

            err_msg = "验证码有误";
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(err_msg);
        }

        user.setStatus("N");// 表示未激活
        user.setCode(UuidUtil.getUuid()); // 生成激活码
        userService.saveUser(user); // 添加用户
        // 添加完成,发送邮件
        String content = "<a href='http://localhost:8000/ssm-travel/user/activeUser?code=" + user.getCode() + "'>点击激活</a> ";
        MailUtils.sendMail(user.getEmail(),content,"激活邮件");


        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString("success");
    }

    // 3. 邮箱激活
    @RequestMapping(value = "/activeUser")
    @ResponseBody
    public void activeUser(String code, HttpServletResponse response) throws IOException {
        Boolean activeUser = userService.activeUser(code);
        System.out.println(activeUser);
        String msg = null;
        if (activeUser){
            //激活成功
            msg = "<p>激活成功,请<a href='http://localhost:8000/ssm-travel/login.html'>登录</a><p>";
        }else {
            // 激活失败
            msg = "激活失败,请联系管理员";
        }
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().print(msg);

    }

1.需要使用 UuidUtil工具类生成激活码,同时发送邮件,邮件正文就是“点击激活”,当用户点击则会携带激活码访问:/activeUser,获取到激活码,与数据库查询激活码比较,正确则让用户跳转登录,否则激活失败。
2.用户初始激活状态为 “N”,当用户激活成功,改为“Y”。
3. 发送邮件,需要 使用 MailUtils工具类发送,需要邮箱名称和授权码才能发送,具体可在网上自行搜索。

到此,注册功能就完成了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值