Java网络开发(Tomcat)—— 登陆 和 注册功能 的实现 和 迭代升级

news2024/11/27 1:15:52

目录

  • 引出
  • 登陆功能---从html到jsp
    • 1.登陆--用post请求
    • 2.用html文件的form表单登陆
      • (1)index.html页面
      • (2)login.html登陆的页面
      • (3)LoginServlet.java处理输入信息的代码
      • (4)登陆成功:
    • 3.如果失败在原页面显示信息----用jsp文件登陆
      • (1)login.jsp页面
      • (2)LoginServlet.java处理登陆业务---共享msg
  • 注册功能---注册验证码
    • 4.注册逻辑 和 注册成功后跳转到登陆页面
    • 5.如何防止用户恶意注册----用验证码限制
      • (1)前端显示验证码
      • (2)后端判断验证是否正确
      • (3)完整代码
  • 登陆成功和退出登陆
    • 6.登陆成功和退出登陆---保存session和删除session
      • (1)前端页面,comIndex.jsp
      • (2)进行登陆,保存session
      • (3)退出系统servlet,LogoutServlet.jsp
  • 总结

引出

1.验证用户名密码正确的思路;
2.从html文件到jsp文件的登陆进化—静态到动态;
3.用验证码的方式防止不断注册;
4.注册成功后再跳转到登陆页面—重定向;
4.如何保存登陆的用户信息----session;


登陆功能—从html到jsp

1.登陆–用post请求

思路:

1.通过username 和 password 查询对象出来,如果对象有,登陆成功,否则失败;

2.通过username 和 password 查询数量,如果数量为1,登陆成功,否则失败;

3.【推荐】SpringSecurity 推荐的方式:用username 查一个对象出来;

(1)查不到,登陆失败(没有注册过,数据库没有这个用户名);

(2)查到了,用户名正确,用查询出来的这一条记录和前端发送过来的密码对比:

​ 如果正确,登陆成功,否则,登陆失败;

dao层的接口和实现:

接口要有:(1)新增一个数据到数据库;(2)根据用户名查询一条记录出来;

dao层的接口:

package com.tianju.dao;

import com.tianju.entity.ComUser;

/**
 * 公司用户的Dao类
 */
public interface IComUserDao {
    /**
     * 新增一个公司用户
     * @param comUser 新增用户
     * @return 影响行数
     */
    Integer add(ComUser comUser);

    /**
     * 根据用户名查一条记录出来
     * @param username 查询的用户名
     * @return 查询出的用户
     */
    ComUser queryByUsername(String username);

}

dao接口的实现:

package com.tianju.dao.impl;

import com.tianju.dao.IComUserDao;
import com.tianju.entity.ComUser;
import com.tianju.util.DBUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.util.List;

public class ComUserDaoImpl implements IComUserDao {
    private JdbcTemplate db = DBUtils.getJdbcTemplate();
    public RowMapper<ComUser> rowMapper = new BeanPropertyRowMapper<>(ComUser.class);
    @Override
    public Integer add(ComUser comUser) {
        String sql = "INSERT INTO com_user(id,username,password,sex,birthday)" +
                "values (null,?,?,?,?)";
        return db.update(sql,comUser.getUsername(),comUser.getPassword(),comUser.getSex(),comUser.getBirthday());
    }

    @Override
    public ComUser queryByUsername(String username) {
        String sql = "SELECT * FROM com_user WHERE username=?";
        List<ComUser> find = db.query(sql, rowMapper,username);
        if (find.size()>0){
            return find.get(0);
        }
        return null;
    }
}

2.用html文件的form表单登陆

在这里插入图片描述

(1)index.html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<img src="img/register.jpg" width="200px"><br>
<a href="/day01/html/login.html" target="_blank">登陆</a><br>
<a href="html/register.html" target="_blank">注册</a><br>
<a href="html/idcard.html" target="_blank">身份证归属地</a><br>
<a href="/day01/html/loginNew.html">新版登陆页面</a><br>
<a href="/day01/bookTypes/list">显示图书类型的表格--前端在java中拼出来</a><br>
<a href="/day01/bookList/jsp">显示图书类型的表格--用jsp</a>


</body>
</html>

在这里插入图片描述

(2)login.html登陆的页面

其中密码输入的input框的type设置成 password

密码 :<input type="password" name="password"><br>

在这里插入图片描述

action 要用绝对路径 :/项目名/链接

1)有 / 为绝对路径,从ip/端口/day01/开始拼接 ,会从localhost:8080位置开始拼接路径
2)无 / 为相对路径,浏览器会删除最后一级目录,然后把相对目录地址拼接上去

如果是绝对路径,会从localhost:8080位置开始拼接路径

浏览器路径为:localhost:8080/day01/a
<a href="/b">跳转</a>
跳转后路径为:localhost:8080/b

如果是相对路径,浏览器会删除最后一级目录,然后把相对目录地址拼接上去

浏览器路径为:localhost:8080/day01/a
<a href="b">跳转</a>
跳转后路径为:localhost:8080/day01/b

get和post
查询用get:链接里显示输入的值;写到请求头中
登陆用post:链接里不会显示输入的值;写到请求体中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陆的页面</title>
</head>
<body>
    <form action="/day01/loginUserNew" method="post">
        <h1>新版登陆页面</h1>
        <img src="../img/register.jpg" width="200px"><br>
        用户名:<input type="text" name="username"><br>&nbsp;&nbsp;码:<input type="password" name="password"><br>
        <input type="submit" value="登陆">
        <input type="reset" value="重置">
    </form>
    <a href="../index.html">返回主界面</a>

</body>
</html>

在这里插入图片描述

(3)LoginServlet.java处理输入信息的代码

业务流程:

1)输入不为空;

2)验证用户名和密码;

2)登陆成功;

/**
 * 用户登陆的服务,注意不能用log
 * 1.username + password 查询对象出来,对象有,登陆成功,否则失败;
 * 2.查询数量出来,1成功,否则失败;
 * 3.【建议】springSecurity 推荐,用username 查一个对象;
 *     3.1 查不到,登陆失败(没有注册过,数据库无这个用户名);
 *     3.2 查到了,用户名正确,就用这一条记录的密码和前端发送的密码对比;
 *         如果正确,登陆成功,不登录失败;
 */

@WebServlet("/loginUserNew")
public class LoginServlet extends HttpServlet {
    private IUserService  userService = new UserServiceImpl();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决编码的问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 获取前端传来的用户名
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)){
            resp.getWriter().write("<h1>必填项为空</h1>");
            return;
        }

        // 登陆错误,重新输入
        User user = userService.findByUsername(username);
        if (user==null || !password.equals(user.getPassword())){
            resp.getWriter().write("<h1>用户名|密码错误</h1>");
            return;
        }
        String out = "<h1>用户名"+user.getUsername() +"/"+ user.getNickname() +"登陆成功"+"</h1>";
        resp.getWriter().write(out);

    }
}

在这里插入图片描述

(4)登陆成功:

在这里插入图片描述

3.如果失败在原页面显示信息----用jsp文件登陆

(1)login.jsp页面

用一个span框,获取共享的msg信息

    <span style="color: darkred">${msg}</span><br>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户登陆页面e</title>
</head>
<body>
<form action="/day06/comUser/login" method="post">
    用户名:<input type="text" name="username"><br>
    密&nbsp;&nbsp;码:<input type="password" name="password"><br>
    <span style="color: darkred">${msg}</span><br>
    <input type="submit" value="登陆">

</form>

</body>
</html>

(2)LoginServlet.java处理登陆业务—共享msg

请求转发,内部转发,jsp本质也是servlet

        if (comUser==null || !comUser.getPassword().equals(SecureUtil.md5(password))){
            req.setAttribute("msg", "用户名 | 密码错误");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }

完整代码:

/**
 * 用户登陆的servlet
 */
@WebServlet("/comUser/login")
public class LoginServlet extends HttpServlet {
    private IComUserService comUserService = new ComUserServiceImpl();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 编码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 输入不为空
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)){
            // 输入为空
            req.setAttribute("msg", "输入为空,请检查");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }

        // 进行验证
        ComUser comUser = comUserService.queryByUsername(username);
        if (comUser==null || !comUser.getPassword().equals(SecureUtil.md5(password))){
            req.setAttribute("msg", "用户名 | 密码错误");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }
        // 跳转到操作页面
        resp.sendRedirect(req.getContextPath()+"/compMess/comIndex.jsp");
        
    }
}

在这里插入图片描述

注册功能—注册验证码

4.注册逻辑 和 注册成功后跳转到登陆页面

用验证码的方式防止恶意注册;

注册成功重定向到登陆页面:

		// 5.注册成功跳转到登陆页面
        resp.sendRedirect(req.getContextPath()+"/comUser/login.jsp");

5.如何防止用户恶意注册----用验证码限制

(1)前端显示验证码

验证码的图片请求servlet

    验证码:<input type="text" name="imgCode"><img src="/day06/register/image/get">

<%--    如果要让验证码在点击时自动更新--%>
    验证码:<input type="text" name="imgCode">
    <img src="/day06/register/image/get" οnclick="this.src='/day06/register/image/get?'+new Date().getMilliseconds()">

servlet处理请求:

(1)把验证码—4位数字存到session中;

(2)把验证码的图片放到响应中,发送给前端jsp,进行展示;

@WebServlet("/register/image/get")
public class ImageServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 随机生成验证码
        String randomStr = ImageCodeUtils.getRandomStr(4);

        // 验证码存到session空间中
        HttpSession session = req.getSession();
        session.setAttribute("yzm", randomStr);

        // 根据验证码在缓存中生成一张图片
        BufferedImage bufferedImage = ImageCodeUtils.createImageCode(100, 36, randomStr);

        // 把缓存中的图片以png的格式,放到响应的输出流中
        ImageIO.write(bufferedImage, "png", resp.getOutputStream());

    }
}

注意这里有个错误:共享的时候不能是session,查了好久这个bug

在这里插入图片描述

一个卡了一会儿的bug

在这里插入图片描述

生成的图片分析:

在这里插入图片描述

(2)后端判断验证是否正确

在图片的servlet中,把图片的验证码4位数字存到session空间中;

        // 验证码存到session空间中
        HttpSession session = req.getSession();
        session.setAttribute("yzm", randomStr);

在注册的register的servlet中,获取session,从session中获取验证码数字,进行判断

  • 忽略大小写
        // +++++判断验证码是否正确
        HttpSession session = req.getSession();
        // 从session中获取验证码
        String yzm = (String)session.getAttribute("yzm");
        // 忽略大小写 .equalsIgnoreCase
        if (!yzm.equalsIgnoreCase(imgCode)){
            req.setAttribute("msg", "验证码不正确");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }

验证码对比流程:

在这里插入图片描述

(3)完整代码

处理注册业务的RegisterServlet.java文件


@WebServlet("/comUser/register")
public class RegisterServlet extends HttpServlet {
    private IComUserService comUserService = new ComUserServiceImpl();
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决编码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 用户注册的业务逻辑
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String rePassword = req.getParameter("rePassword");
        String sex = req.getParameter("gender");
        String birthday = req.getParameter("birthday");
        System.out.println(username+password+rePassword+sex+birthday);
        // +++加入+验证码输入
        String imgCode = req.getParameter("imgCode");

        // 1.输入不为空;
        if (StringUtils.isBlank(username)
        || StringUtils.isBlank(password)
        || StringUtils.isBlank(rePassword)
        || StringUtils.isBlank(sex)
        || StringUtils.isBlank(birthday)
        || StringUtils.isBlank(imgCode)){
            // 如果为空,显示一条信息;转发给jsp
            req.setAttribute("msg", "输入为空,请检查");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }

        // +++++判断验证码是否正确
        HttpSession session = req.getSession();
        // 从session中获取验证码
        String yzm = (String)session.getAttribute("yzm");
        // 忽略大小写 .equalsIgnoreCase
        if (!yzm.equalsIgnoreCase(imgCode)){
            req.setAttribute("msg", "验证码不正确");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }


        // 2.用户名不重复;
        ComUser comUserDb = comUserService.queryByUsername(username);
        if (comUserDb!=null){
            // 用户名重复
            req.setAttribute("msg", "用户名重复,请重新输入");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }

        // 3.两次密码输入一致;
        if (!password.equals(rePassword)){
            // 两次密码不一致
            req.setAttribute("msg", "两次密码输入不一致,请检查");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }


        // 进行密码加密存储
        ComUser comUser = new ComUser();
        comUser.setPassword(SecureUtil.md5(password));
        comUser.setUsername(username);
        try {
            comUser.setBirthday(sdf.parse(birthday));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        comUser.setSex(sex);

        System.out.println(comUser);


        // 4.保存信息到数据库
        comUserService.add(comUser);

        // 5.注册成功跳转到登陆页面
        resp.sendRedirect(req.getContextPath()+"/comUser/login.jsp");

    }
}

生成验证码的ImageServlet.java文件:

/**
 * 验证码的servlet
 * 随机生成验证码,验证码存到session空间中;
 * 把验证码图片以png的格式,放到响应的输出流中;
 */
@WebServlet("/register/image/get")
public class ImageServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 随机生成验证码
        String randomStr = ImageCodeUtils.getRandomStr(4);

        // 验证码存到session空间中
        HttpSession session = req.getSession();
        session.setAttribute("yzm", randomStr);

        // 根据验证码在缓存中生成一张图片
        BufferedImage bufferedImage = ImageCodeUtils.createImageCode(100, 36, randomStr);

        // 把缓存中的图片以png的格式,放到响应的输出流中
        ImageIO.write(bufferedImage, "png", resp.getOutputStream());

    }
}

ImageCodeUtils.java --生成验证码图片的工具类

package com.tianju.util;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 生成图片验证码
 */
public class ImageCodeUtils {

    //根据传入的位数,生成随机字符
    public static String getRandomStr(int length)
    {
        String s = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";

//        Random random = new Random(System.currentTimeMillis());
        Random random = new Random();

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int i1 = random.nextInt(s.length());
            sb.append(s.charAt(i1));
        }
        return sb.toString();
    }

    public static void main(String[] args) throws IOException, InterruptedException {

        for (int i = 0; i < 100; i++) {
            Thread.sleep(10);
            String randomStr = getRandomStr(4);
            System.out.println(randomStr);
        }
//        //BuffereImage 图片缓冲流
//        BufferedImage bufferedImage = createImageCode(100, 34, "ABCD");//生成图片的缓冲流
//        //把缓冲流,写到某个输出流
//        ImageIO.write(bufferedImage,"jpg",new FileOutputStream("/Users/edz/Desktop/11.jpg"));
    }

    public static BufferedImage createImageCode(int width, int height, String code) {
        int codeSize = code.length();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Random rand = new Random();
        Graphics2D g2 = image.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        Color[] colors = new Color[5];
        Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA,
                Color.ORANGE, Color.PINK, Color.YELLOW };
        float[] fractions = new float[colors.length];
        for (int i = 0; i < colors.length; i++) {
            colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
            fractions[i] = rand.nextFloat();
        }
        Arrays.sort(fractions);

        g2.setColor(Color.GRAY);// 设置边框色
        g2.fillRect(0, 0, width, height);

        Color c = getRandColor(200, 250);
        g2.setColor(c);// 设置背景色
        g2.fillRect(0, 2, width, height - 4);

        // 绘制干扰线
        Random random = new Random();
        g2.setColor(getRandColor(160, 200));// 设置线条的颜色
        for (int i = 0; i < 20; i++) {
            int x = random.nextInt(width - 1);
            int y = random.nextInt(height - 1);
            int xl = random.nextInt(6) + 1;
            int yl = random.nextInt(12) + 1;
            g2.drawLine(x, y, x + xl + 40, y + yl + 20);
        }

        // 添加噪点
        float yawpRate = 0.05f;// 噪声率
        int area = (int) (yawpRate * width * height);
        for (int i = 0; i < area; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int rgb = getRandomIntColor();
            image.setRGB(x, y, rgb);
        }

        shear(g2, width, height, c);// 使图片扭曲

        g2.setColor(getRandColor(100, 160));
        int fontSize = height - 4;
        Font font = new Font("Algerian", Font.ITALIC, fontSize);
        g2.setFont(font);
        char[] chars = code.toCharArray();
        for (int i = 0; i < codeSize; i++) {
            AffineTransform affine = new AffineTransform();
            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1),
                    (width / codeSize) * i + fontSize / 2, height / 2);
            g2.setTransform(affine);
            g2.drawChars(chars, i, 1, ((width - 10) / codeSize) * i + 5, height / 2 + fontSize / 2 - 10);
        }

        g2.dispose();
        return image;
    }

    private static Color getRandColor(int fc, int bc) {
        Random random = ThreadLocalRandom.current();

        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    private static int getRandomIntColor() {
        int[] rgb = getRandomRgb();
        int color = 0;
        for (int c : rgb) {
            color = color << 8;
            color = color | c;
        }
        return color;
    }

    private static int[] getRandomRgb() {
        Random random = ThreadLocalRandom.current();
        int[] rgb = new int[3];
        for (int i = 0; i < 3; i++) {
            rgb[i] = random.nextInt(255);
        }
        return rgb;
    }

    private static void shear(Graphics g, int w1, int h1, Color color) {
        shearX(g, w1, h1, color);
        shearY(g, w1, h1, color);
    }

    private static void shearX(Graphics g, int w1, int h1, Color color) {
        Random random = ThreadLocalRandom.current();
        int period = random.nextInt(2);

        boolean borderGap = true;
        int frames = 1;
        int phase = random.nextInt(2);

        for (int i = 0; i < h1; i++) {
            double d = (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * phase) / frames);
            g.copyArea(0, i, w1, 1, (int) d, 0);
            if (borderGap) {
                g.setColor(color);
                g.drawLine((int) d, i, 0, i);
                g.drawLine((int) d + w1, i, w1, i);
            }
        }

    }

    private static void shearY(Graphics g, int w1, int h1, Color color) {
        Random random = ThreadLocalRandom.current();
        int period = random.nextInt(40) + 10; // 50;

        boolean borderGap = true;
        int frames = 20;
        int phase = 7;
        for (int i = 0; i < w1; i++) {
            double d = (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * phase) / frames);
            g.copyArea(i, 0, 1, h1, 0, (int) d);
            if (borderGap) {
                g.setColor(color);
                g.drawLine(i, (int) d, i, 0);
                g.drawLine(i, (int) d + h1, i, h1);
            }

        }
    }

}

登陆成功和退出登陆

6.登陆成功和退出登陆—保存session和删除session

登陆成功后,将登陆成功的用户存到session----用于确定当前的操作是谁做的

        // +登陆成功的用户存到session----用于确定当前的操作是谁做的
        req.getSession().setAttribute("user", userDb);

退出登陆后,把保存的session信息删除,并重新回到登陆页

        HttpSession session = req.getSession();
        session.invalidate(); // 清理session
        resp.sendRedirect(req.getContextPath()+"/user/login.jsp");

完整的业务逻辑代码:

在这里插入图片描述

(1)前端页面,comIndex.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆成功的index页面</title>
</head>
<body>
<a href="/day06/company/messList" target="iframe">查询公司所有信息</a>
<a href="/day06/user/logout">退出系统</a>
<iframe width="100%" height="80%" name="iframe"></iframe>

</body>
</html>

(2)进行登陆,保存session

/**
 * 用户登陆的servlet
 */
@WebServlet("/comUser/login")
public class LoginServlet extends HttpServlet {
    private IComUserService comUserService = new ComUserServiceImpl();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 编码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 输入不为空
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)){
            // 输入为空
            req.setAttribute("msg", "输入为空,请检查");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }

        // 进行验证
        ComUser comUser = comUserService.queryByUsername(username);
        if (comUser==null || !comUser.getPassword().equals(SecureUtil.md5(password))){
            req.setAttribute("msg", "用户名 | 密码错误");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }

        // ++++++登陆成功的用户对象存储到session中=====用户确定后续的操作是谁做的
        req.getSession().setAttribute("user", comUser);

        // 跳转到操作页面---重定向
        resp.sendRedirect(req.getContextPath()+"/compMess/comIndex.jsp");

    }
}

(3)退出系统servlet,LogoutServlet.jsp


/**
 * 退出登陆的servlet,清除session缓存
 */
@WebServlet("/user/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.invalidate(); // 清除session
        // 重定向,回到登陆页面
        resp.sendRedirect(req.getContextPath()+"/index.jsp");
    }
}


总结

1.验证用户名密码正确:通过username查一条信息出来,对比密码;
2.用jsp文件代替html文件实现共享msg的提醒,比如用户名|密码不正确;
3.用验证码的方式防止不断注册,点击图片自动更细;
4.注册成功后再跳转到登陆页面—重定向;
4.用session空间保存登陆成功的用户对象;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/598415.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式事务一 事物以及分布式事物介绍

一 事务简介 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中&#xff0c;一个事务由一组SQL语句组成。事务应该具有4个属性&#xff1a;原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。 原子性&#xff08;at…

MyBatis - Spring Boot 集成 MyBatis

文章目录 1.版本要求2.导入依赖3.自动配置2.可配置项 MyBatis-Spring-Boot-Starter 可以帮助你更快地在 Spring Boot 之上构建 MyBatis 应用。通过使用该模块我们能够快速实现以下目的&#xff1a; 构建单体应用程序将几乎不需要样板配置使用更少的 XML 配置 1.版本要求 MyB…

Apache Kafka - 构建数据管道 Kafka Connect

文章目录 概述主要概念ConnectorTasksWorkesConvertersTransformsDead Letter Queue 主要使用场景主要价值Kafka Connect API vs Producer 和 Consumer API构建数据管道时需要考虑的主要问题ETL VS ELT数据整合方式的不同ETL 和 ELT 各有优缺点: 概述 Kafka Connect 是一个工具…

Linux二——Web基础与HTTP协议

Web基础与HTTP协议 一、Web基础1. 域名的概念2.域名空间结构3.域名注册4.网页的概念5. HTML概念6.网页基本标签1 二、HTTP协议1.HTTP概念2.HTML的基本标签3.头标签中常用标签4.内容标签中常用的标签 三、动态网页与静态网页1.静态网页2.动态网页3.动态网页和静态网页的区别4.动…

软件测试目的是什么?软件测试公司可提供哪些测试服务类型?

随着科技的不断发展&#xff0c;软件行业的发展也越来越迅速。然而&#xff0c;随着软件的增多和复杂性的提高&#xff0c;开发者们需要更多的手段来确保软件质量。软件测试就是通过一系列的测试来发现软件的问题&#xff0c;从而提高软件的质量。 一、软件测试目的是什么? …

Unity中的UniTask如何取消指定的任务或所有的任务

今天儿童节&#xff0c;犬子已经9个多月了&#xff0c;今天是他的第一个儿童节。中年得子&#xff0c;其乐无穷无尽啊… 〇、 示例效果 一连创建5个异步任务[id 从0~4]&#xff0c;先停止其中的第id 4的任务&#xff0c;再停止所有的任务 一、CancellationTokenSource有什…

利用矩阵分解实现图像压缩(实验)

机器学习的课程&#xff0c;老师布置了一个实验报告&#xff0c;当我看到实验内容&#xff0c;傻眼了&#xff0c;手写计算矩阵特征值和特征向量的函数&#xff0c;这给我整无语了&#xff0c;直接调用已有的不好吗&#xff0c; 我直接摆烂。 实验报告放这了&#…

【C#图解教程】 第六章 方法(上)

方法的结构 方法是一块具有名称的代码&#xff0c;在类和结构中都经常用到 局部变量 局部变量位于方法内部&#xff0c;在方法中声明时产生&#xff0c;在方法执行结束时结束 类型推断与var关键字 某些情况下&#xff0c;在声明的开始部分包含类型名是多余的&#xff0c;因为…

Python-python判断语句:布尔类型和比较运算符、if语句的基本格式、if else语句、if el if else语句、判断语句的嵌套、实战案例

版本说明 当前版本号[20230601]。 版本修改说明20230601初版 知识总览图 目录 文章目录 版本说明知识总览图目录Python判断语句布尔类型和比较运算符布尔类型布尔类型的定义 比较运算符 if语句的基本格式if判断语句if语句的注意点 if else 语句语句注意点 if elif else语句注…

7min 到 40s:SpringBoot 优化居然可以玩出这么多花样!

0 背景 公司 SpringBoot 项目在日常开发过程中发现服务启动过程异常缓慢&#xff0c;常常需要6-7分钟才能暴露端口&#xff0c;严重降低开发效率。通过 SpringBoot 的 SpringApplicationRunListener 、BeanPostProcessor 原理和源码调试等手段排查发现&#xff0c;在 Bean 扫描…

“灵巧小工具”一个将图片处理成打印纸尺寸的丰富功能完全免费无水印的图片处理工具

今天推荐一款微信小程序“灵巧小工具”&#xff0c;经常有打印图片需求的用户赶紧收藏了。 可以先扫码体验一番&#xff1a; 下面介绍一下它的主要功能&#xff1a; 1.照片&#xff08;1寸、2寸、5寸、6寸&#xff09; 支持1寸&#xff0c;2寸照片自动排版&#xff0c;生成相纸…

JavaSE】Java基础语法(四十):UDP通信程序

文章目录 1. UDP发送数据2. UDP接收数据【应用】3. UDP通信程序练习【应用】4. UDP三种通讯方式 1. UDP发送数据 Java中的UDP通信 UDP协议是一种不可靠的网络协议&#xff0c;它在通信的两端各建立一个Socket对象&#xff0c;但是这两个 Socket只是发送&#xff0c;接收数据的对…

IPv6 6to4隧道配置和验证实验

IPv6 6to4隧道配置和验证实验 【实验目的】 熟悉IPv6 6to4隧道的概念。 掌握IPv6和IPv4共存的实现方法。 掌握IPv6 6to4地址编址规则。 掌握IPv6 6to4隧道的配置。 验证配置。 【实验拓扑】 设备参数如下表所示。 设备 接口 IP地址 子网掩码 默认网关 R1 S0/0 19…

cuda编程学习——CUDA共享内存性能优化(九)

前言 参考资料&#xff1a; 高升博客 《CUDA C编程权威指南》 以及 CUDA官方文档 CUDA编程&#xff1a;基础与实践 樊哲勇 文章所有代码可在我的GitHub获得&#xff0c;后续会慢慢更新 文章、讲解视频同步更新公众《AI知识物语》&#xff0c;B站&#xff1a;出门吃三碗饭 …

绝不可错过!R语言与ggplot2实现SCI论文数据分析神器

一、介绍 1.1 R语言和ggplot2 语言是一种强大的数据分析和统计建模工具&#xff0c;具有广泛的应用领域。 ggplot2是基于R语言的数据可视化工具&#xff0c;具有强大的绘图功能和灵活性。 1.2 数据分析中的重要性 R语言和ggplot2在数据分析中具有广泛的应用&#xff0c;能够帮助…

有些香港云主机为啥更容易遭遇停机风险?

​对于搭建过外贸网站的站长们来说&#xff0c;在面对香港云主机的选择时&#xff0c;往往遇到且出现较为频繁的两个词便是&#xff1a;免费香港云主机和付费香港云主机。其中&#xff0c;一些所谓的免费香港云主机&#xff0c;尤其是长久免费使用&#xff0c;恐怕用户们就要承…

ES6中函数新增了哪些扩展?

参数 &#x1f355;&#x1f355;&#x1f355;ES6允许为函数的参数设置默认值 函数的形参是默认声明的&#xff0c;不能使用let或const再次声明 function foo(x5){let x 1;//errconst x 2;//err }参数默认值可以与解构赋值的默认值结合起来使用 function foo({x,y 5}){co…

华为OD机试真题B卷 Java 实现【分奖金】,附详细解题思路

一、题目描述 公司老板做了一笔大生意&#xff0c;想要给每位员工分配一些奖金&#xff0c;想通过游戏的方式来决定每个人分多少钱。按照员工的工号顺序&#xff0c;每个人随机抽取一个数字。按照工号的顺序往后排列&#xff0c;遇到第一个数字比自己数字大的&#xff0c;那么…

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分

前言 本篇在讲什么 OpenGL蓝宝书第八章学习笔记之曲面细分 本篇适合什么 适合初学OpenGL的小白 本篇需要什么 对C语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻…

CI/CD:如何使用 GitLab 执行 SpringBoot 前后端分离项目的持续集成与持续交付(持续部署)?

一、GitLab Runner 安装 官网各系统 & 各方式安装说明&#xff1a;https://docs.gitlab.com/runner/install/ 本文基于阿里云 CentOS 安装 GitLab Runner &#xff08;Linux Shell 方式&#xff0c;非 Docker 方式&#xff09; 1.1 GitLab Runner 介绍 GitLab Runner 是…