【途牛旅游项目】项目环境搭建,实现登陆功能

项目准备

熟悉静态页面
查看真实在线的途牛旅游项目
其实也是一个商城而已,重点项目搭建,核心模块:登录

前言

(1)前言
为了巩固web基础知识,提升综合运用能力,故而讲解此案例。
要求,每位同学能够独立完成此案例。
(2)项目演示
01-静态页面
让客户可以直观的看到项目完成的效果
(3)复制到项目
新建web-app
复制到项目
启动

三层架构

(1)三层架构
!在这里插入图片描述

技术选型

(1)Web层
a)Servlet:前端控制器
b)html:视图
c)Filter:过滤器
d)BeanUtils:数据封装
e)Jackson:json序列化工具
(2)Service层
f)Javamail:java发送邮件工具
g)Redis:nosql内存数据库
h)Jedis:java的redis客户端
(3)Dao层
i)Mysql:数据库
j)Mybatis:对jdbc进行封装

项目搭建

项目初始化,目录结构

在这里插入图片描述
bean包:存放java实体类
dao包:数据操作层
   Mysql:数据库(Mybatis:对jdbc进行封装,MySQL:数据库)
Service包:业务逻辑层
   主要包括三大类:(Javamail:java发送邮件工具,Redis:nosql内存数据库,Jedis:java的redis客户端)
util包:存放工具类
Web包

Servlet:前端控制器
Filter:过滤器
listener:监听器

导入pom.xml依赖

<?xml version="1.0" encoding="UTF-8"?>


4.0.0

<groupId>com.hjy</groupId>
<artifactId>Travel</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
    <module>MyTravel</module>
    <module>MyTravelTest01</module>
</modules>

<name>Travel</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <!--servlet-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>

    <!-- MySql -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.32</version>
    </dependency>
    <!-- Mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <!--日志包-->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    <!--beanUtils-->
    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.9.2</version>
        <scope>compile</scope>
    </dependency>
    <!--jackson-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.3.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.3.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.3.3</version>
    </dependency>


    <!--javaMail-->
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>javax.mail-api</artifactId>
        <version>1.5.6</version>
    </dependency>
    <dependency>
        <groupId>com.sun.mail</groupId>
        <artifactId>javax.mail</artifactId>
        <version>1.5.3</version>
    </dependency>
    <!--jedis-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.7.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.12</version>
    </dependency>

    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

</dependencies>

<build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
        <plugins>
            <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.1.0</version>
            </plugin>
            <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.0.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-install-plugin</artifactId>
                <version>2.5.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8.2</version>
            </plugin>
            <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
            <plugin>
                <artifactId>maven-site-plugin</artifactId>
                <version>3.7.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-project-info-reports-plugin</artifactId>
                <version>3.0.0</version>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

创建数据库

在这里插入图片描述

登录功能

在这里插入图片描述

最终实现截图

在这里插入图片描述

实现登录功能

实现登录功能

  1. 创建测试类
    //测试user业务层
    public class TestUserService {

    //测试登录
    @Test
    public void test01(){
    UserService userService = new UserService();

     //创建user数据
     User user = new User();
     user.setUsername("861221293");
     user.setPassword("ABC123456");
     //user.setStatus("Y");//用户激活
    
     //测试登录
     int code = userService.login(user);
     if(code == 1){
         System.out.println("登录成功");
     }else if(code == -1){
         System.out.println("用户名或密码错误");
     }else if(code == -2){
         System.out.println("用户未激活");
     }
    

    }
    }

  2. 创建业务层UserService
    //user业务层
    public class UserService {

    private static UserDao userDao = null;

    //登录用户
    public int login(User user) {
    userDao = GetDaoUtils.getMapper(UserDao.class);

     User u = userDao.getUserByUsernamePassword(user);
     if(u == null){
         return -1;  //账号密码匹配找不到
     }else {
         //判断用户user是否激活
         if(u.getStatus().equals("Y")){
             return 1;   //账号密码正确,且已经激活
         }else {
             return -2;  //账号未激活
         }
     }
    

    }
    }

  3. 创建实体类 - User用户类和Msg错误提示类
    //User类
    public class User {
    private int uid;
    private String username; //登录用户名
    private String password; //密码
    private Date birthday; //生日
    private String name; //昵称
    private String sex; //性别
    private String telephone; //电话号码
    private String email; //邮箱
    private String status; //激活状态
    private String code; //激活码(UUID)
    //省略getter/setter方法
    }

//Msg信息提示类
public class Msg {
private int code;
private Object data;
//省略getter/setter方法
}

  1. 创建dao层
    public interface UserDao {
    // 通过usernmae和password查询用户
    public User getUserByUsernamePassword(User user);
    }

  2. 创建dao的映射文件

<?xml version="1.0" encoding="UTF-8" ?> select uid,username,password,name,birthday,sex,telephone,email,status,code from tab_user where username = #{username} and password = #{password}
  1. 创建属性文件,连接数据库db.properties
    #mysql jdbc 属性文件里面不能有分号
    jdbc.driver = com.mysql.jdbc.Driver
    jdbc.url = jdbc:mysql://localhost:3306/travelnetwork?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    jdbc.username = root
    jdbc.password = 861221293

  2. 编写日志配置log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
  1. 配置Spring核心配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>

<!--1. 引入jdbc的属性文件,在配置中通过占位使用 -->
<context:property-placeholder location="classpath*:db.properties" />

<!--2. <context:component-scan>扫描包中注解所标注的类(@Component、@Service、@Controller、@Repository) -->
<context:component-scan base-package="com.xgf"/>

<!--3. 由spring管理    配置数据源数据库连接(从jdbc属性文件中读取参数) -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="driverClassName" value="${jdbc.driver}"/>
</bean>

<!--  通过spring来管理Mybatis的sqlSessionFactory对象创建,将MyBatis的二级缓存配置configLocation粘入  -->
<!--4. 通过完全限定名匹配查找  创建SqlSessionFactoryBean  -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
</bean>

<!-- 5. mybatis提供的一个注解扫描标签(搜索映射器 Mapper 接口),通过自动扫描注解的机制,创建每个dao接口定义的bean  -->
<mybatis:scan base-package="com.xgf.dao"/>
  1. 创建获取class类的工具类GetDaoUtils
    // 获取bean工具类
    public class GetDaoUtils {

    private static ApplicationContext applicationContext = null;

    //静态代码块 只加载一次
    static {
    //加载配置文件
    applicationContext = new ClassPathXmlApplicationContext(“com/xgf/config/applicationContext.xml”);
    }

    public static T getMapper(Class classFile) {
    return (T) applicationContext.getBean(classFile);
    }
    }

  2. 运行测试类,测试逻辑是否有问题
    测试结果,测试成功

Preparing: select uid,username,password,name,birthday,sex,telephone,email,status,code from tab_user where username = ? and password = ?

  1. 编写随机生成验证码的业务逻辑类

/*

  • 生成验证码,并将验证码转化为图片的业务层

  • */
    public class VerificationCodeService {

    public VerificationCodeService() {
    }

    // 生成验证码字符串 – 随机数
    public String createRandomCode() {
    String str = “ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”;//所有随机数字符串集合
    //Random类 产生指定范围内的随机数
    Random random = new Random();

      StringBuilder sb = new StringBuilder();
      //随机截取4个字符
      for(int i =0 ;i < 4; i++){//4个随机数
          //包括开头不包括结尾 从0到str.length()-1里面随机产生一个整数
          int index = random.nextInt(str.length());//从0到str.length()不包括最后一个 右边开区间
          char randomStr = str.charAt(index);//安装随机产生的值获取字符
          sb.append(randomStr);//StringBuilder拼接字符串
    
      }
      return sb.toString();
    

    }

    // 将生成的随机字符串验证码转化为图片
    public BufferedImage changeStringToImage(String code) {
    Random rd = new Random();
    //创建一个画布
    int width = 80;
    int height = 30;
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    //创建画笔
    Graphics g = image.getGraphics();
    //给画笔设置颜色(绘制随机验证码的时候的验证码颜色)
    g.setColor(new Color(240,240,240)); //#00000 FFFFFF
    //设置验证码的 背景色
    g.fillRect(0, 0, width, height);
    // 设置字体
    g.setFont(new Font(“宋体”,Font.BOLD,16));

      g.setColor(new Color(0,0,0));  //#00000   FFFFFF
      // g.drawString(checkCodeStr, 20, 20);
      for (int i = 0; i <4 ; i++) {
          //画字符
          g.setColor(new Color(rd.nextInt(120),rd.nextInt(120),rd.nextInt(120)));
          g.drawString(code.charAt(i)+"", 16*i + rd.nextInt(16), 15 + rd.nextInt(10) );
          if(i % 2 == 0) {//画线
              g.setColor(new Color(rd.nextInt(120), rd.nextInt(120), rd.nextInt(120)));
              g.drawLine(rd.nextInt(75), rd.nextInt(28), rd.nextInt(75), rd.nextInt(28));
          }
      }
      return image;
    

    }
    }

  1. 编写图片验证码的servlet

// 验证码-生成验证码显示成图片的servlet
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    //服务器通知浏览器不要缓存
    response.setHeader("pragma","no-cache");
    response.setHeader("cache-control","no-cache");
    response.setHeader("expires","0");
    //1:创建一个验证码的业务
    VerificationCodeService vcs = new VerificationCodeService();
    //2:生产一个随机的4个字符组成的字符串
    String verificationCode =  vcs.createRandomCode();
    System.out.println(verificationCode);

    //将验证码保存到session中
    HttpSession session = request.getSession();
    session.setAttribute("verificationCode",verificationCode);

// request.setAttribute(“verificationCode”,verificationCode);

    //3:将字符串转成图片
    //BufferedImage类将图片生成到内存中,然后直接发送给浏览器
    BufferedImage image =  vcs.changeStringToImage(verificationCode);

    //4:使用OutputStream写到浏览器

// System.out.println(image);
//获取输出流
ServletOutputStream outputStream = response.getOutputStream();

    ImageIO.write(image,"jpeg",outputStream);//参1,内存中的图片  参2,格式  参3,字节输出流
    outputStream.flush();
    outputStream.close();//关流

// request.getRequestDispatcher("/").forward(request,response);
}
}

  1. 登录servlet
    @WebServlet("/LoginServlet")
    public class LoginServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    UserService userService = new UserService();
    HttpSession session = request.getSession();//获取session对象,里面主要是验证码和当前user
    Msg msg = new Msg();//提示信息
    
    //用户输入的验证码
    String inputCheckCode = request.getParameter("inputCheckCode");
    //从session中获取系统当前生成的验证码
    String verificationCode = (String) session.getAttribute("verificationCode");
    System.out.println("inputCheckCode : " + inputCheckCode + " ;\t verificationCode : " + verificationCode);
    
    //inputCheckCode 与 verificationCode
    //相同表示验证码不正确,将提示信息写到页面的错误提示
    if (inputCheckCode == null || !inputCheckCode.equalsIgnoreCase(verificationCode)) {
        //验证码不看大小写
        msg.setCode(-3);
        msg.setData("验证码输入出错,请重新输入验证码");
    
        //将字符串转换为json数据格式返回给浏览器
        String json = new ObjectMapper().writeValueAsString(msg);
        response.getWriter().println(json);
        return; //返回不继续执行
    }
    
    
    //获取请求参数
    Map<String, String[]> map = request.getParameterMap();
    //当前登录用户
    User loginUser = new User();
    try {
        //参1 javaBean 参2 map 封装bean对象
        BeanUtils.populate(loginUser, map);//将map里面所有的参数赋值给javaBean(login就是输入的username和password)
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    
    //调用service处理参数,查询当前登录username和password是否存在
    int code = userService.login(loginUser);
    //响应给浏览器 ajax 是响应json给浏览器就可以
    msg.setCode(code);//设置code
    
    if (code == 1) {
        msg.setData("登录成功,欢迎您的使用Login Success");
        //将登录user保存到session中
        session.setAttribute("user", loginUser);
        //判断是否开启免登陆
        //登录成功且开启了十天免登陆  就要保存/覆盖cookie
        String ssh = request.getParameter("ssh");
        //从session中删除生成的验证码 不移除的话可能会覆盖新的验证码
        session.removeAttribute("verificationCode");
    } else if (code == -1) {
        msg.setData("您输入的用户名或密码错误,请重新输入Incorrect user name or password");
    
    } else if (code == -2) {
        msg.setData("您的账号还没有激活,请前往激活The account is activated");
    }
    
    //将字符串转成json数据格式,返回给浏览器显示提示信息msg
    String json = new ObjectMapper().writeValueAsString(msg);
    response.getWriter().println(json);
    

    }
    }

  2. 编写filter,全局编码解决
    //解决全站乱码问题,处理所有的请求,拦截所有设置编码
    @WebFilter("/*")
    public class CharchaterFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    System.out.println(“CharchaterFilter”);
    //设置请求编码
    req.setCharacterEncoding(“UTF-8”);
    //设置响应编码
    resp.setContentType(“text/html;charset=UTF-8”);
    //放行
    chain.doFilter(req, resp);
    }

    public void destroy() {

    }
    }

  3. 编写页面jsp,点击验证码进行图片更换

</div>
<div class="login-box">
    <div class="title">
        <img src="images/login_logo.png" alt="">
        <span>欢迎登录途牛旅游账户</span>
    </div>
    <div class="login_inner">

        <!--登录错误提示消息-->
        <div id="errorMsg" class="alert alert-danger" ></div>
        <form id="loginForm" action="" method="post" accept-charset="utf-8">
            <input type="hidden" name="action" value="login"/>
            <input id="username" name="username" type="text" placeholder="请输入账号">
            <input id="password" name="password" type="password" placeholder="请输入密码" autocomplete="off">
            <div class="verify">
                <input name="inputCheckCode" type="text" placeholder="请输入验证码" autocomplete="off">
                <span><img src="checkCodeServlet" alt="" onclick="changeCheckCode(this)"></span>
                <script type="text/javascript">
                    //图片点击事件
                    function changeCheckCode(img) {
                        img.src="checkCodeServlet?"+new Date().getTime();//添加时间戳
                    }
                </script>
            </div>

            <div class="submit_btn" >
                <button id="btn_login" type="button">登录</button>
                <div class="auto_login">
                    <%-- ssh : 免密码登录 --%>
                    <input type="checkbox" name="ssh" value="ssh" class="checkbox" style="margin-left: 10px">
                    <span >十天免登陆</span>
                </div>
            </div>
        </form>
        <div class="reg" >没有账户?<a href="javascript:;">立即注册</a></div>
    </div>
</div>
  1. aJax实现异步登录,并判断输入是否合法,防止非法注入
  1. 运行结果
    在这里插入图片描述
    登陆成功
    在这里插入图片描述
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值