Java单体应用 - 架构模式 - 04.实践练习

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java单体应用 - 架构模式 - 04.实践练习相关的知识,希望对你有一定的参考价值。

原文地址:http://www.work100.net/training/monolithic-architecture-test.html
更多教程:光束云 - 免费课程

实践练习

序号 文内章节 视频
1 构建项目结构
2 代码实现
3 网站实现
4 测试运行
5 总结

请参照如上章节导航进行阅读

1.构建项目结构

我们以用户登录功能进行演示 三层架构 + MVC架构 如何实现。

1.1.创建项目

打开 IDEA ,在前述章节 stage2 文件夹下创建文件夹 login-demo,如下图:

技术图片

技术图片

1.2.创建 POM 文件

创建文件夹后,在 login-demo 文件夹上 右击,然后 New - File,新建一个 pom.xml 文件,文件内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>net.work100.training.stage2</groupId>
    <artifactId>login-demo</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
    </dependencies>

</project>

1.3.创建目录结构

接下来,在 login-demo 文件夹下创建如下目录结构:

目录 含义
src/main/java 源码
src/main/resources 资源文件
src/main/webapp 网站文件
src/test/java 测试源码

技术图片

1.4.托管 POM 文件到 Maven

pom.xml 托管到 Maven,操作方式如下:

技术图片

托管后,点击 刷新 重新导入所有 Maven 项目,结果如下:

技术图片

1.5.创建包结构

在文件夹 src/main/java右击 - New - Package,包名为:net.work100.training.stage2.login.demo

然后创建我们的 三层 + MVC 包架构:

含义
dao 数据访问层
entity 实体类
service 服务层
web.controller Web控制器

技术图片

2.代码实现

2.1.定义实体类

entity 包上 右击 - New - Java Class 创建名为 User 的类。

User.java 文件代码如下:

package net.work100.training.stage2.login.demo.entity;

import java.io.Serializable;

/**
 * <p>Title: User</p>
 * <p>Description: 用户表</p>
 *
 * @author liuxiaojun
 * @date 2020-02-09 10:43
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-09   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class User implements Serializable {
    private String userName;
    private String loginId;
    private String loginPwd;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getLoginId() {
        return loginId;
    }

    public void setLoginId(String loginId) {
        this.loginId = loginId;
    }

    public String getLoginPwd() {
        return loginPwd;
    }

    public void setLoginPwd(String loginPwd) {
        this.loginPwd = loginPwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + ''' +
                ", loginId='" + loginId + ''' +
                '}';
    }
}

2.2.实现dao层

创建 UserDao 接口

在包 dao右击 - New - Java ClassKind 选择 Interface,接口命名为 UserDao

UserDao.java 代码如下:

package net.work100.training.stage2.login.demo.dao;

import net.work100.training.stage2.login.demo.entity.User;

/**
 * <p>Title: UserDao</p>
 * <p>Description: 用户数据访问</p>
 *
 * @author liuxiaojun
 * @date 2020-02-09 10:49
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-09   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public interface UserDao {
    /**
     * 登录验证
     *
     * @param loginId  登录ID
     * @param loginPwd 登录密码
     * @return
     */
    User login(String loginId, String loginPwd);
}

接口实现 UserDaoImpl

在包dao右击 - New - Package,类包名称为 impl,然后在包impl右击 - New - Java Class,新建类 UserDaoImpl

UserDaoImpl.java 文件代码如下:

package net.work100.training.stage2.login.demo.dao.impl;

import net.work100.training.stage2.login.demo.dao.UserDao;
import net.work100.training.stage2.login.demo.entity.User;

/**
 * <p>Title: UserDaoImpl</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-09 11:04
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-09   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class UserDaoImpl implements UserDao {

    @Override
    public User login(String loginId, String loginPwd) {
        // 根据 loginId 查询出用户信息
        User user = getUserByLoginId(loginId);
        if (user!=null) {
            // 验证 loginPwd 是否正确(区分大小写)
            if(user.getLoginPwd().equals(loginPwd)){
                return user;
            }
        }
        return null;
    }


    private User getUserByLoginId(String loginId){
        // 模拟 DB 存在的用户数据
        User dbUser = new User();
        dbUser.setUserName("Xiaojun");
        dbUser.setLoginId("admin");
        dbUser.setLoginPwd("admin");

        // 判断是否存在 loginId 的用户(忽略大小写)
        if(dbUser.getLoginId().equalsIgnoreCase(loginId)){
            return dbUser;
        }
        return null;
    }
}

2.3.实现service层

创建 UserService 接口

在包 service右击 - New - Java ClassKind 选择 Interface,接口命名为 UserService

UserService.java 代码如下:

package net.work100.training.stage2.login.demo.service;

/**
 * <p>Title: UserService</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-09 11:20
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-09   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public interface UserService {
    /**
     * 登录验证
     *
     * @param loginId  登录ID
     * @param loginPwd 登录密码
     * @return
     */
    boolean login(String loginId, String loginPwd);
}

接口实现 UserServiceImpl

在包 service右击 - New - Package,类包名称为 impl,然后在包impl右击 - New - Java Class,新建类 UserServiceImpl

UserServiceImpl.java 文件代码如下:

package net.work100.training.stage2.login.demo.service.impl;

import net.work100.training.stage2.login.demo.dao.UserDao;
import net.work100.training.stage2.login.demo.dao.impl.UserDaoImpl;
import net.work100.training.stage2.login.demo.service.UserService;

/**
 * <p>Title: UserServiceImpl</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-09 11:22
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-09   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class UserServiceImpl implements UserService {

    // 数据访问层的具体实现
    private UserDao userDao = new UserDaoImpl();

    @Override
    public boolean login(String loginId, String loginPwd) {
        return userDao.login(loginId, loginPwd) != null;
    }
}

2.4.实现Web控制器

在包 web.controller右击 - New - Java Class,新建一个 LoginController 控制器。

LoginController.java 代码如下:

package net.work100.training.stage2.login.demo.web.controller;

import net.work100.training.stage2.login.demo.service.UserService;
import net.work100.training.stage2.login.demo.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>Title: LoginController</p>
 * <p>Description: 登录控制器</p>
 *
 * @author liuxiaojun
 * @date 2020-02-09 11:36
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-09   liuxiaojun     初始创建
 * -----------------------------------------------
 */
public class LoginController extends HttpServlet {

    private UserService userService = new UserServiceImpl();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String loginId = req.getParameter("loginId");
        String loginPwd = req.getParameter("loginPwd");

        boolean success = userService.login(loginId, loginPwd);

        // 登录失败
        if (!success) {
            req.getRequestDispatcher("/fail.jsp").forward(req, resp);
        }
        // 登录成功
        else {
            req.getRequestDispatcher("/success.jsp").forward(req, resp);
        }
    }
}

LoginController 需要扩展继承 HttpServlet,所以我们需要在 pom.xml 文件中引入依赖的类包 javax.servlet-api

3.网站实现

3.1.构建网站目录结构

目录 含义
WEB-INF/web.xml 网站配置文件
index.jsp 登录页
success.jsp 登录成功
fail.jsp 登录失败

技术图片

3.2.网站配置文件

WEB-INF/web.xml 配置文件代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
   <display-name>login-demo</display-name>

   <servlet>
      <servlet-name>LoginController</servlet-name>
      <servlet-class>net.work100.training.stage2.login.demo.web.controller.LoginController</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>LoginController</servlet-name>
      <url-pattern>/login</url-pattern>
   </servlet-mapping>
</web-app>

3.3.登录页

index.jsp 文件代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<body>
<form action="/login" method="post">
    <input name="loginId" type="text" />
    <input name="loginPwd" type="password" />
    <input type="submit" value="登录" />
</form>
</body>
</html>

3.4.登录成功页

success.jsp 文件代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功</title>
</head>
<body>
登录成功
</body>
</html>

3.5.登录失败页

fail.jsp 文件代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>失败</title>
</head>
<body>
登录失败
</body>
</html>

4.测试运行

4.1.配置Tomcat

打开 Run/Debug Configurations,点击 + - Tomcat Server - Local ,然后点击 OK 确认

技术图片

Tomcat-Server 命名 login-demo,选择安装好的 Application Server

技术图片

切换到 Deployment 选项卡,添加 Artifact,有两种方式:

方式一

点击 + - Artifact

技术图片

弹出画面中选择 login-demo:war exploded

技术图片

方式二

右下角选择 Fix

技术图片

弹出画面中选择 login-demo:war exploded

技术图片

设置 Application context/,即为根目录:

技术图片

4.2.运行

点击下图 运行 按钮:

技术图片

运行成功后将打开浏览器,或者您手动打开浏览器,输入地址:

http://localhost:8080/

运行效果如下图:

技术图片

表单输入以下错误的登录数据:

名称
用户名 admin
密码 123456

页面将转向 登录失败 页面,如下图:

技术图片

表单输入以下正确的登录数据:

名称
用户名 admin
密码 admin

页面将转向 登录成功 页面,如下图:

技术图片

5.总结

如上详细讲解了 三层 + MVC 架构的典型实现方式,课件将每个步骤都进行了截图,请认真阅读文档并实践练习。

通过练习做到深刻理解三层架构及MVC架构,同时熟练掌握 IntelliJ IDEA 构建 Maven 项目的详细步骤。

后续的章节将不再对通过 IntelliJ IDEA 构建 Maven 项目的步骤进行讲解,将主要以代码实现为讲解内容。


上一篇:访问者模式

以上是关于Java单体应用 - 架构模式 - 04.实践练习的主要内容,如果未能解决你的问题,请参考以下文章

Java单体应用 - 架构模式 - 03.设计模式

微服务实践:从单体式架构迁移到微服务架构

Java单体应用 - 架构模式 - 01.三层架构

Java单体应用 - 架构模式 - 01.三层架构

Java单体应用 - 架构模式 - 03.设计模式-01.工厂模式

微服务实践:从单体式架构迁移到微服务架构