【JavaWEB】项目实战-黑马面面

个人博客:www.hellocode.top
⭐所有文章均在上方博客首发,其他平台同步更新
本文专栏:《Java Web从入门到实战》
如没有Java基础,请先前往《Java零基础指南》专栏学习相应知识
⚡如有问题,欢迎指正,一起学习~~


文章目录

      • 工程搭建
        • 系统架构
        • 技术架构
        • 需求分析
        • 工程结构
        • 页面结构
      • 企业模块
        • 数据层
        • 业务层
        • 表现层
      • 部门模块
        • 分析
        • 代码
        • 用户模块
      • 完整项目


前台

注册

【JavaWEB】项目实战-黑马面面_第1张图片

登录

【JavaWEB】项目实战-黑马面面_第2张图片

首页

【JavaWEB】项目实战-黑马面面_第3张图片

试卷

【JavaWEB】项目实战-黑马面面_第4张图片

后台

登录

【JavaWEB】项目实战-黑马面面_第5张图片

首页

【JavaWEB】项目实战-黑马面面_第6张图片

管理

【JavaWEB】项目实战-黑马面面_第7张图片

【JavaWEB】项目实战-黑马面面_第8张图片

【JavaWEB】项目实战-黑马面面_第9张图片

编辑

【JavaWEB】项目实战-黑马面面_第10张图片

【JavaWEB】项目实战-黑马面面_第11张图片

工程搭建

系统架构

【JavaWEB】项目实战-黑马面面_第12张图片

  • 前后台共用一组数据(存储到MySQL)
  • 均采用三层架构(表现层、业务层、持久层)

技术架构

【JavaWEB】项目实战-黑马面面_第13张图片

需求分析

【JavaWEB】项目实战-黑马面面_第14张图片

图中连线表示一对多的情况,有原点的一方为多

  • 日志应该是遍布整个系统的,各个操作都可以留下操作日志
  • ss——系统模块,st——后台业务模块,tr——前台业务模块
  • 这三个模块名称直接对应数据库中各个表的表前缀

工程结构

  • 创建Maven工程(web工程)
  • 导入项目依赖的 坐标
  • 补全目录结构
    • src
      • java
      • resources
      • webapp
    • test
      • java
      • resources

【JavaWEB】项目实战-黑马面面_第15张图片

  • 创建三层架构开发的包层次结构
    • domain(实体类)
    • dao(持久层)
    • service(业务层)
    • web(表现层)
      • controller
      • filters
    • utils(工具类)
    • factory(工厂类)

【JavaWEB】项目实战-黑马面面_第16张图片

pom.xml

【JavaWEB】项目实战-黑马面面_第17张图片


<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/maven-v4_0_0.xsd">

  <modelVersion>4.0.0modelVersion>
  <packaging>warpackaging>

  <name>heimammname>
  <groupId>top.hellocodegroupId>
  <artifactId>heimammartifactId>
  <version>1.0-SNAPSHOTversion>

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

  <dependencies>
    
    <dependency>
      <groupId>org.mybatisgroupId>
      <artifactId>mybatisartifactId>
      <version>3.5.3version>
    dependency>
    
    <dependency>
      <groupId>com.github.pagehelpergroupId>
      <artifactId>pagehelperartifactId>
      <version>5.1.2version>
    dependency>
    
    <dependency>
      <groupId>mysqlgroupId>
      <artifactId>mysql-connector-javaartifactId>
      <version>5.1.46version>
    dependency>
    
    <dependency>
      <groupId>com.alibabagroupId>
      <artifactId>druidartifactId>
      <version>1.1.21version>
    dependency>
    
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>4.12version>
      <scope>testscope>
    dependency>
    
    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>javax.servlet-apiartifactId>
      <version>3.1.0version>
      <scope>providedscope>
    dependency>
    
    <dependency>
      <groupId>javax.servlet.jspgroupId>
      <artifactId>javax.servlet.jsp-apiartifactId>
      <version>2.3.3version>
      <scope>providedscope>
    dependency>
    
    <dependency>
      <groupId>commons-beanutilsgroupId>
      <artifactId>commons-beanutilsartifactId>
      <version>1.9.4version>
    dependency>
    
    <dependency>
      <groupId>org.apache.commonsgroupId>
      <artifactId>commons-lang3artifactId>
      <version>3.9version>
    dependency>
    
    <dependency>
      <groupId>jstlgroupId>
      <artifactId>jstlartifactId>
      <version>1.2version>
    dependency>
    
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-annotationsartifactId>
      <version>2.9.0version>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-coreartifactId>
      <version>2.9.0version>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-databindartifactId>
      <version>2.9.0version>
    dependency>
    
    <dependency>
      <groupId>commons-fileuploadgroupId>
      <artifactId>commons-fileuploadartifactId>
      <version>1.3.1version>
    dependency>
    
    <dependency>
      <groupId>org.apache.poigroupId>
      <artifactId>poiartifactId>
      <version>4.0.1version>
    dependency>
    <dependency>
      <groupId>org.apache.poigroupId>
      <artifactId>poi-ooxmlartifactId>
      <version>4.0.1version>
    dependency>
    <dependency>
      <groupId>org.apache.poigroupId>
      <artifactId>poi-ooxml-schemasartifactId>
      <version>4.0.1version>
    dependency>
  dependencies>

  <build>
    <plugins>
      
      <plugin>
        <groupId>org.apache.tomcat.mavengroupId>
        <artifactId>tomcat7-maven-pluginartifactId>
        <version>2.1version>
        <configuration>
          <port>80port>
          <path>/path>
        configuration>
      plugin>
    plugins>
  build>

project>

sql导入

内容有点多,直接给大家sql文件,大家直接下载吧

heima_mm.sql

页面结构

【JavaWEB】项目实战-黑马面面_第18张图片

【JavaWEB】项目实战-黑马面面_第19张图片

  • AdminLTE后台框架是一款建立在bootstrap 和 jQuery 之上的开源模板主题工具,其中内置了多个模块页面,可以用于快速创建响应式Html5网站,并免去了书写大量的CSS与JS的工作
  • 后台框架很多,大家选择自己喜欢的进行删减修改即可

企业模块

  • 先从简单的模块开始做(企业模块——单表查询)
  • Company归属于后台模块,所以在对应的包下再建一个包store

数据层

domain

private String id;
private String name;	// 名称
private Date expirationDate;	// 注册日期
private String address;		// 地址
private String licenseId;		// 营业执照编号
private String representative;		// 法人
private String phone;		// 电话
private String companySize;		// 规模
private String industry;		// 所属行业
private String remarks;			// 备注 / 描述
private String state;			// 状态
private String city;			// 所在地

dao

  • 因为是使用MaBatis,所以只写接口即可,实现使用动态代理方式
  • 同样在dao下再建一个store包
public interface CompanyDao {
    int save(Company company);		// 保存
    int delete(Company company);    // 删除
    int update(Company company);    // 修改
    Company findById(String id);    // 通过id查询
    List<Company> findAll();        // 查询全部
}

配置文件

  • 配置文件统一放到资源目录下(resources)
  • 需要的配置文件
    • MyBatis总配置文件(SqlMapConfig.xml)
    • 每个模块的映射配置文件(CompanyDao.xml)
    • 数据库配置文件(jdbc.properties)

resources的配置文件所在目录应该和上面的dao等工程目录一致

resources中新建top.hellocode.dao.store,然后把CompanyDao.xml放进去

SqlMapConfig.xml


DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    
    <properties resource="jdbc.properties">properties>


    
    <typeAliases>
        
        <package name="top.hellocode.domain">package>
    typeAliases>

    
    <plugins>
        
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <property name="helperDialect" value="mysql" />
            <property name="reasonable" value="true" />
        plugin>
    plugins>

    
    <environments default="mysql">
        
        <environment id="mysql">
            
            <transactionManager type="JDBC">transactionManager>
            
            <dataSource type="POOLED" >
                
                <property name="driver" value="${jdbc.driver}">property>
                <property name="url" value="${jdbc.url}">property>
                <property name="username" value="${jdbc.username}">property>
                <property name="password" value="${jdbc.password}">property>
            dataSource>
        environment>
    environments>



    
    <mappers>
        
        <package name="top.hellocode.dao">package>
    mappers>


configuration>

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.23.129/heima_mm
jdbc.username=root
jdbc.password=密码

CompanyDao.xml


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.store.CompanyDao">

    
    <resultMap id="BaseResultMap" type="com.itheima.domain.store.Company">
        <id column="id" jdbcType="VARCHAR" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="expiration_date" jdbcType="TIMESTAMP" property="expirationDate"/>
        <result column="address" jdbcType="VARCHAR" property="address"/>
        <result column="license_id" jdbcType="VARCHAR" property="licenseId"/>
        <result column="representative" jdbcType="VARCHAR" property="representative"/>
        <result column="phone" jdbcType="VARCHAR" property="phone"/>
        <result column="company_size" jdbcType="VARCHAR" property="companySize"/>
        <result column="industry" jdbcType="VARCHAR" property="industry"/>
        <result column="remarks" jdbcType="VARCHAR" property="remarks"/>
        <result column="state" jdbcType="INTEGER" property="state"/>
        <result column="city" jdbcType="VARCHAR" property="city"/>
    resultMap>

    
    <sql id="Base_Column_List">
        id, name, expiration_date, address, license_id, representative, phone, company_size,
        industry, remarks, state, city
    sql>

    
    <select id="findAll" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from st_company
    select>

    
    <select id="findById" parameterType="java.lang.String" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from st_company
        where id = #{id,jdbcType=VARCHAR}
    select>

    
    <delete id="delete" parameterType="java.lang.String">
        delete from st_company where id = #{id,jdbcType=VARCHAR}
    delete>

    
    <insert id="save" parameterType="com.itheima.domain.store.Company">
        insert into st_company (id, name, expiration_date,
        address, license_id, representative,
        phone, company_size, industry,
        remarks, state,
        city)
        values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{expirationDate,jdbcType=TIMESTAMP},
        #{address,jdbcType=VARCHAR}, #{licenseId,jdbcType=VARCHAR}, #{representative,jdbcType=VARCHAR},
        #{phone,jdbcType=VARCHAR}, #{companySize,jdbcType=VARCHAR}, #{industry,jdbcType=VARCHAR},
        #{remarks,jdbcType=VARCHAR}, #{state,jdbcType=INTEGER},
        #{city,jdbcType=VARCHAR})
    insert>

    
    <update id="update" parameterType="com.itheima.domain.store.Company">
        update st_company
        set name = #{name,jdbcType=VARCHAR},
        expiration_date = #{expirationDate,jdbcType=TIMESTAMP},
        address = #{address,jdbcType=VARCHAR},
        license_id = #{licenseId,jdbcType=VARCHAR},
        representative = #{representative,jdbcType=VARCHAR},
        phone = #{phone,jdbcType=VARCHAR},
        company_size = #{companySize,jdbcType=VARCHAR},
        industry = #{industry,jdbcType=VARCHAR},
        remarks = #{remarks,jdbcType=VARCHAR},
        state = #{state,jdbcType=INTEGER},
        city = #{city,jdbcType=VARCHAR}
        where id = #{id,jdbcType=VARCHAR}
    update>
mapper>

工具类

  • MapperFactory:负责创建mapper工厂的工具类
    • 读取配置文件
    • 返回sqlSession对象
    • 返回mapper对象
package top.hellocode.factory;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
 * 用于生成dao接口代理实现类的工厂
 * @author 黑马程序员
 * @Company http://www.itheima.com
 */
public class MapperFactory {

    private static SqlSessionFactory factory;
    private static ThreadLocal<SqlSession> tl = new ThreadLocal<SqlSession>();

    static {
        InputStream in = null;
        try {
            //1.读取mybatis主配置文件
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建构建者对象
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //3.使用构建者创建SqlSessionFactory工厂
            factory = builder.build(in);
        }catch (Exception e){
            //打印异常信息到控制台
            e.printStackTrace();
            //抛出错误提示程序终止执行
            throw new ExceptionInInitializerError("初始化SqlSessionFactory失败");
        }finally {
            //释放流对象
            if(in != null){
                try{
                    in.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 获取SqlSession对象
     * @return
     * 保留此方法是为了后面对业务层方法增强,利用AOP添加事务
     */
    public static SqlSession getSqlSession(){
         return factory.openSession(false);
    }

    /**
     * 获取Dao接口的代理实现类
     * @param daoClass dao接口字节码
     * @return
     */
    public static <T> T getMapper(SqlSession sqlSession,Class<T> daoClass){
        //1.判断传入的SqlSession是否为null
        if(sqlSession == null){
            return null;
        }
        //2.不为null,创建代理实现类
        return sqlSession.getMapper(daoClass);
    }
}
  • TransactionUtil:事务管理工具类
    • 提交事务
    • 回滚事务
    • 关闭事务
package top.hellocode.utils;

import org.apache.ibatis.session.SqlSession;

/**
 * 事务控制类
 * @author 黑马程序员
 * @Company http://www.itheima.com
 */
public class TransactionUtil {

    /**
     * 提交释放
     * @param sqlSession
     */
    public static void commit(SqlSession sqlSession){
        if(sqlSession!=null) {
            sqlSession.commit();
        }
    }

    /**
     * 回滚释放
     * @param sqlSession
     */
    public static void rollback(SqlSession sqlSession){
        if(sqlSession!=null) {
            sqlSession.rollback();
        }
    }

    /**
     * 单独释放
     * @param sqlSession
     */
    public static void close(SqlSession sqlSession){
        if(sqlSession!=null) sqlSession.close();
    }
}

业务层

对于任意一个模块来说,当你不清楚具体功能时,可以先把它的基础功能做出来

基础功能

  • 增、删、改、查
  • 查单个
  • 查全部
  • 分页查(分页插件)
int save(Company company);		// 保存
int delete(Company company);    // 删除
int update(Company company);    // 修改
Company findById(String id);    // 通过id查询
List<Company> findAll();        // 查询全部
PageInfo findAll(int page, int size);   // 分页查询

CompanyServiceImpl

package top.hellocode.service.store.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.SqlSession;
import top.hellocode.dao.store.CompanyDao;
import top.hellocode.domain.store.Company;
import top.hellocode.factory.MapperFactory;
import top.hellocode.service.store.CompanyService;
import top.hellocode.utils.TransactionUtil;

import java.util.List;
import java.util.UUID;

/**
 * @author HelloCode
 * @site https://www.hellocode.top
 * @date 2022年05月16日 20:20
 */
public class CompanyServiceImpl implements CompanyService {

    @Override
    public void save(Company company) {
        SqlSession sqlSession = null;
        try{
            // 获取sqlSession对象
            sqlSession = MapperFactory.getSqlSession();
            // 获取Dao
            CompanyDao companyDao = MapperFactory.getMapper(sqlSession,CompanyDao.class);

            // id并不在表现层接收,使用uuid自动生成
            String id = UUID.randomUUID().toString();
            company.setId(id);

            // 调用Dao层操作
            companyDao.save(company);
            // 提交事务
            TransactionUtil.commit(sqlSession);
        }catch (Exception e){
            TransactionUtil.rollback(sqlSession);   // 回滚事务
            throw new RuntimeException(e);      // 抛出异常
            // 记录日志(占位,功能未实现)
        }finally {
            try{
                TransactionUtil.close(sqlSession);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    @Override
    public void delete(Company company) {
        SqlSession sqlSession = null;
        try{
            // 获取sqlSession对象
            sqlSession = MapperFactory.getSqlSession();
            // 获取Dao
            CompanyDao companyDao = MapperFactory.getMapper(sqlSession,CompanyDao.class);

            // 调用Dao层操作
            companyDao.delete(company);
            // 提交事务
            TransactionUtil.commit(sqlSession);
        }catch (Exception e){
            TransactionUtil.rollback(sqlSession);   // 回滚事务
            throw new RuntimeException(e);      // 抛出异常
            // 记录日志(占位,功能未实现)
        }finally {
            try{
                TransactionUtil.close(sqlSession);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    @Override
    public void update(Company company) {
        SqlSession sqlSession = null;
        try{
            // 获取sqlSession对象
            sqlSession = MapperFactory.getSqlSession();
            // 获取Dao
            CompanyDao companyDao = MapperFactory.getMapper(sqlSession,CompanyDao.class);

            // 调用Dao层操作
            companyDao.update(company);
            // 提交事务
            TransactionUtil.commit(sqlSession);
        }catch (Exception e){
            TransactionUtil.rollback(sqlSession);   // 回滚事务
            throw new RuntimeException(e);      // 抛出异常
            // 记录日志(占位,功能未实现)
        }finally {
            try{
                TransactionUtil.close(sqlSession);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    @Override
    public Company findById(String id) {
        SqlSession sqlSession = null;
        try{
            // 获取sqlSession对象
            sqlSession = MapperFactory.getSqlSession();
            // 获取Dao
            CompanyDao companyDao = MapperFactory.getMapper(sqlSession,CompanyDao.class);

            // 调用Dao层操作
            return companyDao.findById(id);
        }catch (Exception e){
            throw new RuntimeException(e);      // 抛出异常
            // 记录日志(占位,功能未实现)
        }finally {
            try{
                TransactionUtil.close(sqlSession);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    @Override
    public List<Company> findAll() {
        SqlSession sqlSession = null;
        try{
            // 获取sqlSession对象
            sqlSession = MapperFactory.getSqlSession();
            // 获取Dao
            CompanyDao companyDao = MapperFactory.getMapper(sqlSession,CompanyDao.class);

            // 调用Dao层操作
            return companyDao.findAll();
        }catch (Exception e){
            throw new RuntimeException(e);      // 抛出异常
            // 记录日志(占位,功能未实现)
        }finally {
            try{
                TransactionUtil.close(sqlSession);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    @Override
    public PageInfo findAll(int page, int size) {
        SqlSession sqlSession = null;
        try{
            // 获取sqlSession对象
            sqlSession = MapperFactory.getSqlSession();
            // 获取Dao
            CompanyDao companyDao = MapperFactory.getMapper(sqlSession,CompanyDao.class);

            // 调用Dao层操作
            PageHelper.startPage(page, size);
            List<Company> all = companyDao.findAll();
            PageInfo pageInfo = new PageInfo<>(all);
            return pageInfo;
        }catch (Exception e){
            throw new RuntimeException(e);      // 抛出异常
            // 记录日志(占位,功能未实现)
        }finally {
            try{
                TransactionUtil.close(sqlSession);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

实现分页功能时,startPage需要写在查询之前

测试用例(CompanyServiceTest)

package top.hellocode.service.store;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import top.hellocode.domain.store.Company;
import top.hellocode.service.store.impl.CompanyServiceImpl;

/**
 * @author HelloCode
 * @site https://www.hellocode.top
 * @date 2022年05月16日 20:27
 */
public class CompanyServiceTest {
    private static CompanyService companyService = null;
    @BeforeClass
    public static void init(){
        companyService = new CompanyServiceImpl();
    }
    @Test
    public void testSave(){
        Company company = new Company();
        company.setName("测试数据");
        companyService.save(company);
    }
    @Test
    public void testFindAll(){
        Company company = new Company();
        System.out.println(companyService.findAll(1, 100));
    }
    @AfterClass
    public static void destory(){
        companyService = null;
    }
}
  • 在实际开发时,每写一个方法最好写一个测试用例,来及时的排错
  • 配置resources中的文件夹结构时,不要直接新建一个多级目录,例如top.hellocode.dao
    系统会直接创建一个名为top.hellocode.dao的文件夹,而不是多级目录

表现层

  • 页面保存位置:WEB-INFO下
  • 功能访问:使用请求参数operation的值区分是何种操作
  • 功能分发:使用if…else…进行功能分发,根据operation的参数值转向不同的操作
  • 数据获取:调用业务层接口
  • 数据共享:request范围数据共享
  • 分页功能实现:按照规范开发,名称与common.jsp文件命名的相同即可(快速开发)

列表页面

list.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../../base.jsp"%>




    
    
    
    黑马面面管理系统
    
    
    
    
    
    



企业管理 企业列表

列表

企业名称 所在地 地址 企业法人 联系方式 所属行业 状态 操作
${item.name} ${item.city} ${item.address} ${item.representative} ${item.phone} ${item.industry} ${item.state ==0?'未审核':'已审核'}
private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 获取数据
    CompanyService companyService = new CompanyServiceImpl();
    int page = 1;
    int size = 5;
    if(StringUtils.isNotBlank(request.getParameter("page"))){
        page = Integer.parseInt(request.getParameter("page"));
    }
    if(StringUtils.isNotBlank(request.getParameter("size"))){
        page = Integer.parseInt(request.getParameter("size"));
    }

    PageInfo all = companyService.findAll(page, size);
    // 将数据保存到指定的位置
    request.setAttribute("page",all);
    // 跳转页面
    request.getRequestDispatcher("/WEB-INF/pages/store/company/list.jsp").forward(request,response); //将页面放到web-info下(安全)
}

添加页面

  • 跳转到添加页面(toAdd)、保存操作(save)

toAdd

  • 跳转到add.jsp页面
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ include file="../../base.jsp"%>




    
    
    
    黑马面面管理系统
    
    
    
    
    


企业管理 企业表单

企业信息
企业名称
营业执照
所在城市
企业地址
法人代表
联系电话
公司规模
所属行业
状态
到期时间
" id="expirationDate">
备注
private void toAdd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 跳转页面
    request.getRequestDispatcher("/WEB-INF/pages/store/company/add.jsp").forward(request,response); //将页面放到web-info下(安全)
}

save

  1. 获取到表单中提交的数据,封装成一个对象(BeanUtils)
  2. 数据持久化:调用业务层接口save
  3. 跳转回list页面
package top.hellocode.utils;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

/**
 * 填充表单数据到javabean的工具类
 * @author zhy
 *
 */
public class BeanUtil {
	/**
	 * 封装表单中的数据到javabean中
	 * @param request	表单中的数据
	 * @param clazz		封装到哪个javabean
	 * @return	封装好的javabean对象
	 * 使用的是泛型。泛型必须先声明再使用。声明必须在返回值之前
	 * T指的就是泛型,它可以是任意字符,只是作为一个占位符。
	 * 声明时用什么字符,使用时就得用什么
	 */
	public static <T> T fillBean(HttpServletRequest request,Class<T> clazz){
		//1.定义一个T类型的javabean
		T bean = null;
		try{
			//2.实例化bean对象
			bean = clazz.newInstance();
			//3.使用BeanUtils的方法进行封装
			BeanUtils.populate(bean, request.getParameterMap());
			//4.返回
			return bean;
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}



	/**
	 * 封装表单中的数据到javabean中,带有日期格式数据
	 * @param request	表单中的数据
	 * @param clazz		封装到哪个javabean
	 * @return	封装好的javabean对象
	 * 使用的是泛型。泛型必须先声明再使用。声明必须在返回值之前
	 * T指的就是泛型,它可以是任意字符,只是作为一个占位符。
	 * 声明时用什么字符,使用时就得用什么
	 */
	public static <T> T fillBean(HttpServletRequest request,Class<T> clazz,String datePattern){
		//1.定义一个T类型的javabean
		T bean = null;
		try{
			//2.实例化bean对象
			bean = clazz.newInstance();
			//3.创建日期转换器对象
			DateConverter converter = new DateConverter();
			converter.setPattern(datePattern);
			//4.设置转换器
			ConvertUtils.register(converter, Date .class);
			//5.使用BeanUtils的方法进行封装
			BeanUtils.populate(bean, request.getParameterMap());
			//6.返回
			return bean;
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}

	/**
	 * 文件上传的表单填充
	 * @param items	文件上传的表单项
	 * @param clazz	要封装的实体类字节码
	 * @param 	泛型
	 * @return		返回封装好的对象
	 */
	public static <T> T fillBean(List<FileItem> items,Class<T> clazz){
		//1.定义一个T类型的javabean
		T bean = null;
		try{
			//2.实例化Bean
			bean = clazz.newInstance();
			//3.遍历文件项集合
			for(FileItem item : items){
				//4.判断是不是文件
				if(item.isFormField()){//表单字段,不是文件
					//5.取出表单中的name属性取值
					String fieldName = item.getFieldName();
					//6.使用UTF-8字符集取出表单数据
					String fieldValue = item.getString("UTF-8");
					//7.创建属性描述器对象
					PropertyDescriptor pd = new PropertyDescriptor(fieldName,clazz);
					//8.获取写方法(setXXX方法)
					Method method = pd.getWriteMethod();
					//9.把数据填充到bean中
					method.invoke(bean,fieldValue);
				}
			}
			//10.返回
			return bean;
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}
}

上面的 BeanUtil是对BeanUtils的一个再封装,简化操作

private void save(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 获取数据并封装对象
    Company company = BeanUtil.fillBean(request,Company.class,"yyyy-MM-dd");
    // 调用业务层接口
    CompanyService companyService = new CompanyServiceImpl();
    companyService.save(company);
    // 跳转页面
    response.sendRedirect(request.getContextPath() + "/store/company?operation=list");
}

修改和删除功能

update

  1. 查询要修改的ID
  2. 将数据加载到指定区域,供页面获取
  3. 跳转页面
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../../base.jsp"%>




    
    
    
    黑马面面管理系统
    
    
    
    
    


企业管理 编辑企业信息

企业信息
企业名称
营业执照
所在城市
企业地址
法人代表
联系电话
公司规模
所属行业
状态
备注
private void toEdit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 拿到要编辑的数据
    String id = request.getParameter("id");
    // 调用业务层方法查询数据
    CompanyService companyService = new CompanyServiceImpl();
    Company company = companyService.findById(id);
    request.setAttribute("company",company);
    // 跳转页面
    request.getRequestDispatcher("/WEB-INF/pages/store/company/update.jsp").forward(request,response); //将页面放到web-info下(安全)
}

private void edit(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 获取数据并封装对象
    Company company = BeanUtil.fillBean(request,Company.class,"yyyy-MM-dd");
    // 调用业务层接口
    CompanyService companyService = new CompanyServiceImpl();
    companyService.update(company);
    // 跳转页面
    response.sendRedirect(request.getContextPath() + "/store/company?operation=list");
}

删除



private void delete(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 获取数据并封装对象
    Company company = BeanUtil.fillBean(request,Company.class);
    // 调用业务层接口
    CompanyService companyService = new CompanyServiceImpl();
    companyService.delete(company);
    // 跳转页面
    response.sendRedirect(request.getContextPath() + "/store/company?operation=list");
}

优化

通过上面的代码我们可以发现,Servlet中每个方法都需要new一个CompanyService对象,因此我们可以把它抽取出来

  • 在controller包下创建一个BaseServlet类,让它继承HttpServlet
  • 成员变量就可以写上需要反复创建的对象
  • 继承了HttpServlet类,所以可以重写init方法,在init方法中完成对成员变量的赋值
  • 让CompanyServlet继承BaseServlet(因为BaseServlet继承了HttpServlet,所以CompanyServlet同样可以使用HttpServlet中的方法)

BaseServlet

package top.hellocode.web.controller;

import top.hellocode.service.store.CompanyService;
import top.hellocode.service.store.impl.CompanyServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

/**
 * @author HelloCode
 * @site https://www.hellocode.top
 * @date 2022年05月19日 22:04
 */
public class BaseServlet extends HttpServlet {
    protected CompanyService companyService;

    @Override
    public void init() throws ServletException {
        companyService = new CompanyServiceImpl();
    }
}

CompanyServlet

package top.hellocode.web.controller.company;

import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import top.hellocode.domain.store.Company;
import top.hellocode.service.store.CompanyService;
import top.hellocode.service.store.impl.CompanyServiceImpl;
import top.hellocode.utils.BeanUtil;
import top.hellocode.web.controller.BaseServlet;

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

/**
 * @author HelloCode
 * @site https://www.hellocode.top
 * @date 2022年05月16日 21:34
 */

// uri:/store/company?operation=list

@WebServlet("/store/company")
public class CompanyServlet extends BaseServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String operation = request.getParameter("operation");   // 操作标志
        if("list".equals(operation)){   // 进入列表页
            this.list(request,response);
        }else if("toAdd".equals(operation)){
            this.toAdd(request,response);
        }else if("save".equals(operation)){
            this.save(request,response);
        }else if("toEdit".equals(operation)){
            this.toEdit(request,response);
        }else if("edit".equals(operation)){
            this.edit(request,response);
        }else if("delete".equals(operation)){
            this.delete(request,response);
        }
    }

    private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取数据
//        CompanyService companyService = new CompanyServiceImpl();
        int page = 1;
        int size = 5;
        if(StringUtils.isNotBlank(request.getParameter("page"))){
            page = Integer.parseInt(request.getParameter("page"));
        }
        if(StringUtils.isNotBlank(request.getParameter("size"))){
            page = Integer.parseInt(request.getParameter("size"));
        }

        PageInfo all = companyService.findAll(page, size);
        // 将数据保存到指定的位置
        request.setAttribute("page",all);
        // 跳转页面
        request.getRequestDispatcher("/WEB-INF/pages/store/company/list.jsp").forward(request,response); //将页面放到web-info下(安全)
    }

    private void toAdd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 跳转页面
        request.getRequestDispatcher("/WEB-INF/pages/store/company/add.jsp").forward(request,response); //将页面放到web-info下(安全)
    }

    private void save(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取数据并封装对象
        Company company = BeanUtil.fillBean(request,Company.class,"yyyy-MM-dd");
        // 调用业务层接口
//        CompanyService companyService = new CompanyServiceImpl();
        companyService.save(company);
        // 跳转页面
        response.sendRedirect(request.getContextPath() + "/store/company?operation=list");
    }

    private void toEdit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 拿到要编辑的数据
        String id = request.getParameter("id");
        // 调用业务层方法查询数据
//        CompanyService companyService = new CompanyServiceImpl();
        Company company = companyService.findById(id);
        request.setAttribute("company",company);
        // 跳转页面
        request.getRequestDispatcher("/WEB-INF/pages/store/company/update.jsp").forward(request,response); //将页面放到web-info下(安全)
    }

    private void edit(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取数据并封装对象
        Company company = BeanUtil.fillBean(request,Company.class,"yyyy-MM-dd");
        // 调用业务层接口
//        CompanyService companyService = new CompanyServiceImpl();
        companyService.update(company);
        // 跳转页面
        response.sendRedirect(request.getContextPath() + "/store/company?operation=list");
    }
    private void delete(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取数据并封装对象
        Company company = BeanUtil.fillBean(request,Company.class);
        // 调用业务层接口
//        CompanyService companyService = new CompanyServiceImpl();
        companyService.delete(company);
        // 跳转页面
        response.sendRedirect(request.getContextPath() + "/store/company?operation=list");
    }

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

部门模块

  • 在企业中,部门可能存在一级部门、二级部门
  • 在开发时,可以先按单表进行开发,后面再把相应的关系加上(自关联)
  • 用户模块属于系统功能,放在system下

分析

private String id;
private String deptName;	// 部门名称
private String parentId;	// 所属部门id
private Integer state;		// 状态
  • 基本操作:参看单表增删改查
  • 注意
    • 替换时注意大小写匹配
    • 替换前要清晰认知替换的内容是什么,同时规范命名习惯,避免出错

部门模块自连接

  • 在domain中加一个字段
    private Dept parent

  • 在映射配置文件中配置关系映射

    <association
    	property="parent"
        javaType="top.hellocode.domain.system.Dept"
        column="parent_id"
        select="top.hellocode.dao.system.DeptDao.findById"
                 />
    

注意:添加页和修改页进入前需要加载到列表数据

代码

add

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../../base.jsp"%>



    
    
    黑马面面管理系统


    

系统管理 部门管理

list

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../../base.jsp"%>




    
    
    
    黑马面面管理系统
    
    
    
    



系统管理 部门管理

部门列表

部门名称 所属部门 状态 操作
${dept.deptName } ${dept.parent.deptName } ${dept.state ==0?'未启用':'使用中'}

update

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../../base.jsp"%>



    
    
    黑马面面管理系统


    

系统管理 部门管理

DeptDao.xml


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="top.hellocode.dao.system.DeptDao">
    
    <resultMap id="BaseResultMap" type="top.hellocode.domain.system.Dept">
        <id column="dept_id" jdbcType="VARCHAR" property="id"/>
        <result column="dept_name" jdbcType="VARCHAR" property="deptName"/>
        <result column="parent_id" jdbcType="VARCHAR" property="parentId"/>
        <result column="state" jdbcType="DECIMAL" property="state"/>
        <association
            property="parent"
            javaType="top.hellocode.domain.system.Dept"
            column="parent_id"
            select="top.hellocode.dao.system.DeptDao.findById"
            />
    resultMap>

    
    <sql id="Base_Column_List">
        dept_id, dept_name, parent_id, state
    sql>

    
    <select id="findAll"  resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from ss_dept
    select>

    
    <select id="findById" parameterType="java.lang.String" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from ss_dept
        where dept_id = #{id,jdbcType=VARCHAR}
    select>

    
    <delete id="delete" parameterType="java.lang.String">
        delete from ss_dept  where dept_id = #{id,jdbcType=VARCHAR}
    delete>

    
    <insert id="save" parameterType="top.hellocode.domain.system.Dept">
        insert into ss_dept (dept_id, dept_name, parent_id,state)
        values (#{id,jdbcType=VARCHAR}, #{deptName,jdbcType=VARCHAR}, #{parentId,jdbcType=VARCHAR},#{state,jdbcType=DECIMAL})
    insert>

    
    <update id="update" parameterType="top.hellocode.domain.system.Dept">
        update ss_dept
        set dept_name = #{deptName,jdbcType=VARCHAR},
        parent_id = #{parentId,jdbcType=VARCHAR},
        state = #{state,jdbcType=DECIMAL}
        where dept_id = #{id,jdbcType=VARCHAR}
    update>

mapper>

DeptServlet

package top.hellocode.web.controller.system;

import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import top.hellocode.domain.system.Dept;
import top.hellocode.utils.BeanUtil;
import top.hellocode.web.controller.BaseServlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @author HelloCode
 * @site https://www.hellocode.top
 * @date 2022年05月20日 22:56
 */


// uri:/system/dept?operation=list

@WebServlet("/system/dept")
public class DeptServlet extends BaseServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String operation = request.getParameter("operation");   // 操作标志
        if("list".equals(operation)){   // 进入列表页
            this.list(request,response);
        }else if("toAdd".equals(operation)){
            this.toAdd(request,response);
        }else if("save".equals(operation)){
            this.save(request,response);
        }else if("toEdit".equals(operation)){
            this.toEdit(request,response);
        }else if("edit".equals(operation)){
            this.edit(request,response);
        }else if("delete".equals(operation)){
            this.delete(request,response);
        }
    }

    private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取数据
//        DeptService deptService = new DeptServiceImpl();
        int page = 1;
        int size = 5;
        if(StringUtils.isNotBlank(request.getParameter("page"))){
            page = Integer.parseInt(request.getParameter("page"));
        }
        if(StringUtils.isNotBlank(request.getParameter("size"))){
            page = Integer.parseInt(request.getParameter("size"));
        }

        PageInfo all = deptService.findAll(page, size);
        // 将数据保存到指定的位置
        request.setAttribute("page",all);
        // 跳转页面
        request.getRequestDispatcher("/WEB-INF/pages/system/dept/list.jsp").forward(request,response); //将页面放到web-info下(安全)
    }

    private void toAdd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 加载数据
        List<Dept> all = deptService.findAll();
        request.setAttribute("deptList",all);
        // 跳转页面
        request.getRequestDispatcher("/WEB-INF/pages/system/dept/add.jsp").forward(request,response); //将页面放到web-info下(安全)
    }

    private void save(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取数据并封装对象
        Dept dept = BeanUtil.fillBean(request,Dept.class,"yyyy-MM-dd");
        // 调用业务层接口
//        DeptService deptService = new DeptServiceImpl();
        deptService.save(dept);
        // 跳转页面
        response.sendRedirect(request.getContextPath() + "/system/dept?operation=list");
    }

    private void toEdit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 拿到要编辑的数据
        String id = request.getParameter("id");

        // 加载数据
        List<Dept> all = deptService.findAll();
        request.setAttribute("deptList",all);
        // 调用业务层方法查询数据
        Dept dept = deptService.findById(id);
        request.setAttribute("dept",dept);
        // 跳转页面
        request.getRequestDispatcher("/WEB-INF/pages/system/dept/update.jsp").forward(request,response); //将页面放到web-info下(安全)
    }

    private void edit(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取数据并封装对象
        Dept dept = BeanUtil.fillBean(request,Dept.class,"yyyy-MM-dd");
        // 调用业务层接口
//        DeptService deptService = new DeptServiceImpl();
        deptService.update(dept);
        // 跳转页面
        response.sendRedirect(request.getContextPath() + "/system/dept?operation=list");
    }
    private void delete(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取数据并封装对象
        Dept dept = BeanUtil.fillBean(request,Dept.class);
        // 调用业务层接口
//        DeptService deptService = new DeptServiceImpl();
        deptService.delete(dept);
        // 跳转页面
        response.sendRedirect(request.getContextPath() + "/system/dept?operation=list");
    }

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

用户模块

  • 同样属于系统模块(system)
private String id;
private String email;   // 邮箱
private String username;    // 姓名
private String password;    // 密码
private Long state;         // 状态
private String gender;      // 性别
private String telephone;   // 电话
private Date birthday;  // 出生年月
private Date joinDate;  // 入职时间
private String deptId;  // 部门id

private Dept dept;

保存

  • 在业务层save之前,需要对密码进行加密(MD5)
  • 使用工具类:MD5Util
package top.hellocode.utils;

import java.security.MessageDigest;
import sun.misc.BASE64Encoder;

/**
 * 密码加密工具类
 * @author 黑马程序员
 * @Company http://www.itheima.com
 */
public class MD5Util {

    /**
     * 密码加密
     * @param password
     * @return
     * @throws Exception
     */
    public static String  md5(String password){
        try {
            //1.创建加密对象
            MessageDigest md5 = MessageDigest.getInstance("md5");
            //2.加密密码
            byte[] by = md5.digest(password.getBytes());
            //3.创建编码对象
            BASE64Encoder encoder = new BASE64Encoder();
            //4.对结果编码
            return encoder.encode(by);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}

修改

  • 需要对能修改的内容进行限制
  • 比如:性别、出生日期、入职日期等并不值得修改
  • 三种方案
    • 读取库中的信息,覆盖现有的数据
    • 修改update语句(只对需要修改的进行操作)
    • 不显示不需要修改的数据
<update id="update" parameterType="top.hellocode.domain.system.User">
    update ss_user
    user_name = #{userName,jdbcType=VARCHAR},
    state = #{state,jdbcType=DECIMAL},
    gender = #{gender,jdbcType=CHAR},
    telephone = #{telephone,jdbcType=VARCHAR},
    dept_id = #{deptId,jdbcType=VARCHAR}
    where user_id = #{id,jdbcType=VARCHAR}
update>

理论上应该提供两个update方法,一个全,一个部分

list

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../../base.jsp"%>




    
    
    
    黑马面面管理系统
    
    
    
    



系统管理 用户管理

用户列表

邮箱 用户名 性别 所属部门 状态 操作
${item.email } ${item.userName} ${item.gender ==0?'男':'女'} ${item.dept.deptName } ${item.state ==0?'停用':'启用'}

完整项目

因平台字数限制,后续内容请点击前往个人博客查阅

项目完整代码:https://github.com/HelloCode66/JavaWEB_heimamm

你可能感兴趣的:(Java,WEB从入门到实战,java,java-ee,后端)