JavaWeb简历管理模块

模块简介

要求

在这里插入图片描述

开发工具

IDEA2020.3 + MySQL.8.0.22 + tomcat9

静态效果展示

首页
在这里插入图片描述
详情页面
添加页面

总结

代码还算干净,页面美观;但花的时间有点长;

代码仓库地址

我的码云仓库

项目代码笔记

数据库和JDBC代码

这部分代码还是蛮干净的

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/resume?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
user=****
password=****
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtil {
    public static String driver;
    public static String url;
    public static String user;
    public static String password;

    static {
        init();
    }

    /**
     * 初始哈输入库连接配置
     */
    public static void init() {
        Properties properties = new Properties();
        String configFile = "database.properties";
        InputStream inputStream = JdbcUtil.class.getClassLoader().getResourceAsStream(configFile);
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        driver = properties.getProperty("driver");
        url = properties.getProperty("url");
        user = properties.getProperty("user");
        password = properties.getProperty("password");
    }

    /**
     * 获取数据库连接
     *
     * @return connection
     * @throws SQLException
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, user, password);
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }


    /**
     * 关闭资源
     *
     * @param conn:数据库连接
     * @param statement:处理对象
     * @param resultSet:结果集
     * @return 是否关闭成功 成功:true
     */
    public static boolean closeResource(Connection conn, PreparedStatement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
                resultSet = null;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (statement!=null){
            try {
                statement.close();
                statement = null;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn!=null){
            try {
                conn.close();
                conn = null;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return true;
    }

    /**
     * 统一查询接口
     *
     * @param connection:数据库连接
     * @param sql:待执行的sql
     * @param params:sql中的参数
     * @return ResultSet:返回的结果
     * @throws SQLException
     */
    public static ResultSet selectQuery(Connection connection,PreparedStatement statement,String sql,Object...params) {
        ResultSet resultSet = null;
        try {
            // 记录引用
            statement = connection.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                statement.setObject(i+1,params[i]);
            }
            resultSet = statement.executeQuery();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return resultSet;
    }

    /**
     * 统一更新接口
     *
     * @param connection:数据库连接
     * @param sql:待执行的sql
     * @param params:sql中的参数
     * @return int:影响的条数
     * @throws SQLException
     */
    public static int updateQuery(Connection connection,PreparedStatement statement,String sql,Object...params){
        int result = 0;
        try {
            statement = connection.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                statement.setObject(i+1,params[i]);
            }
            result = statement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return result;
    }
}

项目结构

项目结构图

文件上传和接收

文件上传

<!--文件上传的表单必须添加这个属性 enctype-->
<form action="upload" method="post" enctype="multipart/form-data">
    <input type="text" name="name" id="name"><br>
    <input type="file" name="file" id="file"><br>
    <input type="submit" value="上传">
</form>

接收代码

package cm.resume.util;

import cm.resume.entity.Resume;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class RequestUtil {
    public static Resume getResumeFromRequest(HttpServletRequest request) {
        Resume resume = new Resume();
        Class<Resume> clazz = Resume.class;

        // -------------------- 设置路径 -----------------
        String path = request.getServletContext().getRealPath("upload");
        String tmpPath = path + "\\tmp";

        // -------------------- 获取form的input 内容 -----------------
        Map<String, String> propMap = new HashMap<>();
        Map<String, FileItem> fileMap = new HashMap<>();
        // 获取所有input的属性key : value
        parseFileFrom(request, tmpPath, propMap, fileMap);

        // -------------------- 设置resume的非文件属性 -----------------
        propMap.forEach((key, value) -> {
            try {
                Method method = clazz.getDeclaredMethod(key, String.class);
                method.setAccessible(true);
                method.invoke(resume, value);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        // -------------------- 设置resume的文件属性 -----------------
        fileMap.forEach((key, value) -> {
            FileItem fileItem = fileMap.get(key);
            // 上传的是文件,获得文件上传字段中的文件名
            // 注意IE或FireFox中获取的文件名是不一样的,IE中是绝对路径,Chrome,FireFox中只是文件名。
            String fileName = fileItem.getName();
            if (fileName == null || fileName.isEmpty()) {
                return;
            }
            String lastEx = fileName.substring(fileName.lastIndexOf("."));
            fileName = UUID.randomUUID() + lastEx;

            // 将FileItem对象中保存的主体内容保存到某个指定的文件中。
            // 如果FileItem对象中的主体内容是保存在某个临时文件中,该方法顺利完成后,临时文件有可能会被清除
            resume.setPicture(fileName);
            try {
                fileItem.write(getFile(path + "\\" + fileName));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return resume;
    }

    public static void parseFileFrom(HttpServletRequest request, String path,
                                     Map<String, String> propMap,
                                     Map<String, FileItem> fileMap) {
        if (request == null || propMap == null || fileMap == null) {
            return;
        }

        DiskFileItemFactory factory = new DiskFileItemFactory();
        //设置工厂的内存缓冲区大小,默认是10K
        factory.setSizeThreshold(1024 * 1024 * 10);
        //设置工厂的临时文件目录:当上传文件的大小大于缓冲区大小时,将使用临时文件目录缓存上传的文件
        factory.setRepository(getFile(path));

        //文件上传解析器
        ServletFileUpload upload = new ServletFileUpload(factory);

        //设置所有上传数据的最大值,单位字节long  1M
        upload.setSizeMax(1024 * 1024 * 20);
        //设置单个文件上传的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        //设置编码格式
        upload.setHeaderEncoding("UTF-8");

        try {
            //解析请求,将表单中每个输入项封装成一个FileItem对象
            List<FileItem> itemList = upload.parseRequest(request);
            String name = null;

            for (FileItem item : itemList) {
                // 得到input中的name属性的名
                name = item.getFieldName();

                if (item.isFormField()) {
                    // 得到input中的name属性的值
                    propMap.put(name, getProperty(item));
                } else {
                    fileMap.put(name, item);
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }

    public static File getFile(String path) {
        File file = new File(path);
        // 先判断文件是否存在
        // 如果文件不存在,创建文件然后判断是否创建文件是否成功
        if (!file.exists() || !file.mkdirs()) {
            try {
                throw new IOException("文件创建失败");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    public static String getProperty(FileItem item) {
        String value = null;

        // 只处理普通输入项
        if (item != null && item.isFormField()) {
            try {
                // 得到输入项中的值
                value = item.getString("UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return value;
    }
}

jQuery实现ajax

$.ajax({
        type:"GET",
        url:$("#path").val()+"/resume",
        // url:"http://localhost:8888"+"/resume",
        data:{method:"remove",resumeId:obj.attr("resumeId")},
        dataType:"json",
        success:function(data){
            if(data.delResult == "true"){//删除成功:移除删除行
                cancleBtn();
                obj.parents("tr").remove();
            }else if(data.delResult == "false"){//删除失败
                alert("path->"+path + "resumeList.js 对不起,删除简历:【"+obj.attr("resumeName")+"】失败");
                changeDLGContent("对不起,删除简历:【"+obj.attr("resumeName")+"】失败");
            }else if(data.delResult == "notexist"){
                alert("path->"+path + "resumeList.js 对不起,简历:【"+obj.attr("resumeName")+"】不存在");
                changeDLGContent("对不起,简历:【"+obj.attr("resumeName")+"】不存在");
            }
        },
        error:function(data){
            alert("data.delResult->"+data.delResult);
            alert("path--->"+path + "\tthis.url->"+this.url +"\t"+ "resumeList.js 对不起,删除失败");
            changeDLGContent("对不起,删除失败369");
        }
    });

分页

sql代码

String sql = "select" + selectFieldsStr +
             "from" + tableName + " " +
             "order by create_time DESC limit ?,?";

java代码

public class Page {
    /**
     * 当前页码
     */
    private int currentPageNo = 1;

    /**
     * 记录总数
     */
    private int totalCount = 0;

    /**
     * 页面容量(一页展示的条数)
     */
    private int pageSize = 0;

    /**
     * 页面总数
     */
    private int totalPageCount = 1;

    public Page() {
    }

    public Page(int currentPageNo, int totalCount, int pageSize) {
        this.currentPageNo = currentPageNo;
        this.pageSize = pageSize;
        // 设置记录总数和页面总数
        this.setTotalCount(totalCount);
    }

    public int getCurrentPageNo() {
        return currentPageNo;
    }

    public void setCurrentPageNo(int currentPageNo) {
        if (currentPageNo > 0) {
            this.currentPageNo = currentPageNo;
        }
    }

    public int getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(int totalCount) {
        if(totalCount > 0){
            this.totalCount = totalCount;
            //设置总页数
            this.setTotalCount(calculationPageCount(this.pageSize,this.totalCount));
        }
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        if (pageSize > 0) {
            this.pageSize = pageSize;
        }
    }

    public int getTotalPageCount() {
        return totalPageCount;
    }

    public void setTotalPageCount(int totalPageCount) {
        if (totalPageCount >= 0) {
            this.totalPageCount = totalPageCount;
        }
    }

    /**
     * 计算分页参数: 页面总数 this.totalPageCount
     */
    public static int calculationPageCount(int pageSize,int totalCount) {
        if (pageSize == 0) {
            return 0;
        }
        if (totalCount % pageSize == 0) {
            return totalCount / pageSize;
        }else if(totalCount % pageSize > 0){
            return totalCount / pageSize + 1;
        }else {
            return 0;
        }
    }
}

Jsp代码

<div class="page-bar">
    <ul class="page-num-ul clearfix">
        <li>共${param.totalCount }条记录&nbsp;&nbsp; ${param.currentPageNo }/${param.totalPageCount }页</li>
        <c:if test="${param.currentPageNo > 1}">
            <a href="javascript:page_nav(document.forms[0],1);">首页</a>
            <a href="javascript:page_nav(document.forms[0],${param.currentPageNo-1});">上一页</a>
        </c:if>
        <c:if test="${param.currentPageNo < param.totalPageCount }">
            <a href="javascript:page_nav(document.forms[0],${param.currentPageNo+1 });">下一页</a>
            <a href="javascript:page_nav(document.forms[0],${param.totalPageCount });">最后一页</a>
        </c:if>
        &nbsp;&nbsp;
    </ul>
    <span class="page-go-form"><label>跳转至</label>
	     <input type="text" name="inputPage" id="inputPage" class="page-key"/>页
	     <button type="button" class="page-btn"
                 onClick='jump_to(document.forms[0],document.getElementById("inputPage").value)'>GO</button>
		</span>
</div>

使用selenium自动测试

谷歌浏览器selenium插件 + 谷歌浏览器驱动

测试示例(工具导出)

import org.junit.Test;
import org.junit.Before;
import org.junit.After;


import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import java.util.*;

public class TestdetailTest {
    private WebDriver driver;
    private Map<String, Object> vars;
    JavascriptExecutor js;

    @Before
    public void setUp() {
        System.setProperty(ConstValue.driverName, ConstValue.chromePath);
        driver = new ChromeDriver();
        js = (JavascriptExecutor) driver;
        vars = new HashMap<String, Object>();
    }

    @After
    public void tearDown() {
        driver.quit();
    }

    @Test
    public void testdetail() {
        // Test name: test_detail
        // Step # | name | target | value
        // 1 | open | / |
        driver.get("http://localhost:8888/");
        // 2 | setWindowSize | 1366x768 |
        driver.manage().window().setSize(new Dimension(1366, 768));
        // 3 | click | linkText=简历管理 |
        driver.findElement(By.linkText("简历管理")).click();
        // 4 | click | css=tr:nth-child(2) .viewResume > img |
        driver.findElement(By.cssSelector("tr:nth-child(2) .viewResume > img")).click();
        // 5 | click | id=evaluation-box |
        driver.findElement(By.id("evaluation-box")).click();
        // 6 | click | id=evaluation |
        driver.findElement(By.id("evaluation")).click();
        // 7 | click | id=experience |
        driver.findElement(By.id("experience")).click();
        // 8 | click | id=skill |
        driver.findElement(By.id("skill")).click();
        // 9 | click | id=ethnic |
        driver.findElement(By.id("ethnic")).click();
        // 10 | click | name=picture |
        driver.findElement(By.name("picture")).click();
        // 11 | click | linkText=专业技能 |
        driver.findElement(By.linkText("专业技能")).click();
        // 12 | click | linkText=在校经历 |
        driver.findElement(By.linkText("在校经历")).click();
        // 13 | click | linkText=回到主页 |
        driver.findElement(By.linkText("回到主页")).click();
        // 14 | click | css=#submit-box > input |
        driver.findElement(By.cssSelector("#submit-box > input")).click();
    }
}

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值