送水公司后台管理系统第二天 用户、客户和送水工管理

送水公司后台管理系统

1用户登录

前端页面使用Thymeleaf模板(跟JSP页面类似),但是它的功能比JSP强大并且用法简洁

在登录页面输入用户名和密码,然后点击“登录”按钮,跳转到“后台管理系统”的主页

1.1 修改父工程的POM文件

在父工程的POM文件中新添加前端框架的依赖

   		<webjars.bootstrap.version>3.3.7webjars.bootstrap.version>
        <webjars.jquery.version>3.3.1webjars.jquery.version>

			
            <dependency>
                <groupId>org.webjarsgroupId>
                <artifactId>bootstrapartifactId>
                <version>${webjars.bootstrap.version}version>
            dependency>
            
            <dependency>
                <groupId>org.webjarsgroupId>
                <artifactId>jqueryartifactId>
                <version>${webjars.jquery.version}version>
            dependency>

1.2 创建子模块(Module)

1.3 定义子模块的POM文件


    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
            
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logbackgroupId>
                    <artifactId>*artifactId>
                exclusion>
                <exclusion>
                    <groupId>org.apache.logging.log4jgroupId>
                    <artifactId>*artifactId>
                exclusion>
            exclusions>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-devtoolsartifactId>
            <scope>runtimescope>
            <optional>trueoptional>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-log4jartifactId>
            <version>1.3.8.RELEASEversion>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
            
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintagegroupId>
                    <artifactId>junit-vintage-engineartifactId>
                exclusion>
            exclusions>
        dependency>

        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>

        
        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-boot-starterartifactId>
        dependency>

        
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druid-spring-boot-starterartifactId>
        dependency>
        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>
        
        <dependency>
            <groupId>io.springfoxgroupId>
            <artifactId>springfox-swagger2artifactId>
        dependency>
        <dependency>
            <groupId>io.springfoxgroupId>
            <artifactId>springfox-swagger-uiartifactId>
        dependency>

        
        <dependency>
            <groupId>cn.hutoolgroupId>
            <artifactId>hutool-allartifactId>
        dependency>
        
        <dependency>
            <groupId>log4jgroupId>
            <artifactId>log4jartifactId>
        dependency>

        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>jcl-over-slf4jartifactId>
        dependency>
        
        <dependency>
            <groupId>org.junit.platformgroupId>
            <artifactId>junit-platform-launcherartifactId>
        dependency>
        <dependency>
            <groupId>org.junit.platformgroupId>
            <artifactId>junit-platform-commonsartifactId>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-thymeleafartifactId>
        dependency>
        
        <dependency>
            <groupId>org.webjarsgroupId>
            <artifactId>bootstrapartifactId>
        dependency>
        
        <dependency>
            <groupId>org.webjarsgroupId>
            <artifactId>jqueryartifactId>
        dependency>
    dependencies>

1.4 定义子模块YML配置文件

resource目录下定义application.yml文件。如图所示:

送水公司后台管理系统第二天 用户、客户和送水工管理_第1张图片

# 配置服务器端口号
server:
  port: 8091
# 数据库连接和Druid连接池配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/minzu?useUnicode=true&characterEncoding=UTF8&useSSL=false
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      min-idle: 5
      max-active: 10
      max-wait: 3000
 # 配置Thymeleaf模板,该模板的后缀为.html,后缀为Classpath下面的/templates/water/
  thymeleaf:
    suffix: .html
    prefix: classpath:/templates/water/
    # 禁用Thymeleaf缓存
    cache: false
# MyBatis-Plus配置 
mybatis-plus:
  configuration:
  	# 实体类属性支持驼峰映射
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 主键自动增长
  global-config:
    db-config:
      id-type: auto

1.5 定义日志配置文件

resource目录下定义log4j.properties文件。如图所示:

送水公司后台管理系统第二天 用户、客户和送水工管理_第2张图片

# 将日志级别为DEBUG的日志信息输出到file(文件)和console(控制台)这两个目的地
log4j.rootLogger=INFO, file, console
# 文件输出的相关设置
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/caojie.log    
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n

#控制台输出的相关设置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss SSS} %5p %c{1}:%L - %m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

1.6 定义相关的package

entities包下面放置实体类

mapper包下面放置Mapper接口,主要用来在实体类的属性和数据库表字段之间做映射,封装了数据库的增删改查操作

service包定义了业务逻辑

controller包定义了控制器,专门用于处理浏览器发起的请求

如图所示:

送水公司后台管理系统第二天 用户、客户和送水工管理_第3张图片

1.7 定义SpringBoot主启动类

package com.shouyi;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * TODO
 *
 * @author caojie
 * @version 1.0
 */
@SpringBootApplication
@MapperScan("com.shouyi.mapper")
public class ShouyiSpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShouyiSpringBootApplication.class,args);
    }
}

1.8 定义Account实体类

package com.shouyi.entities;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * TODO
 * @author caojie
 * @version 1.0
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_account")
public class Account {

    private Integer aid;

    private String userName;

    private String userPwd;

    private String userEmail;

    private String userMobile;
}

1.9 定义Mapper接口

package com.shouyi.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.shouyi.entities.Account;
import org.springframework.stereotype.Repository;

/**
 * TODO
 * AccountMapper是一个映射器接口,它在数据库表的字段和Java实体类属性之间做映射
 * @author caojie
 * @version 1.0
 */
@Repository
public interface AccountMapper extends BaseMapper<Account> {
}

1.10 编写登录业务逻辑接口

package com.shouyi.service;

import com.shouyi.entities.Account;

/**
 * TODO: 用户登录业务逻辑接口
 *
 * @author caojie
 * @version 1.0
 */
public interface AccountService {

    /**
     * 用户登录
     * 步骤:
     * 1 根据用户名查询对应的账户信息
     * 2 判断账户是否为空,如果为空登录失败,返回false
     * 3 如果账户非空,对用户输入的密码进行MD5加密
     * 4 比较数据库的密码和加密的密码是否相等
     * 5 如果相等,登录成功返回true,否则,登录失败返回false
     * @param userName 用户名
     * @param userPwd 密码
     * @return true登录成功,false登录失败
     */
    boolean login(String userName,String userPwd);
}

1.11 编写登录业务逻辑实现类

package com.shouyi.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shouyi.entities.Account;
import com.shouyi.mapper.AccountMapper;
import com.shouyi.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * TODO:登录业务逻辑实现类
 * 被@Service注解修饰的类,是业务逻辑接口的实现类
 * @author caojie
 * @version 1.0
 */
@Service
@Slf4j
public class AccountServiceImpl implements AccountService {
	/**
	自动装配AccountMapper对象
	*/
    @Autowired
    private AccountMapper accountMapper;

    /**
     * 用户登录
     * 步骤:
     * 1 根据用户名查询对应的账户信息
     * 2 判断账户是否为空,如果为空登录失败,返回false
     * 3 如果账户非空,对用户输入的密码进行MD5加密
     * 4 比较数据库的密码和加密的密码是否相等
     * 5 如果相等,登录成功返回true,否则,登录失败返回false
     *
     * @param
     * @return true登录成功,false登录失败
     */
    @Override
    public boolean login(String userName,String userPwd) {
        log.info("userName = "+userName+" userPwd = "+userPwd);
        QueryWrapper<Account> qw = new QueryWrapper<>();
        qw.eq("user_name",userName);
        // 根据用户名查询对应的账号信息
        Account account = accountMapper.selectOne(qw);
        if (null == account) {
            return false;
        }
		// 对表单输入的密码进行MD5加密
        String encodePwd = DigestUtil.md5Hex(userPwd);
		// 比较数据库密码和加密的密码是否相等,条件成立:登录成功,否则登录失败
        if (Objects.equals(encodePwd,encodePwd)) {
            return true;
        } else {
            return false;
        }
    }
}

1.12 编写Controller控制器

package com.shouyi.controller;

import com.shouyi.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * TODO: 用户登录对应的控制器,用来处理用户登录的业务逻辑 
 * @author caojie
 * @version 1.0
 * @date 2021/10/21 11:15
 */
@Controller
@Slf4j
public class AccountController {

    @Autowired
    private AccountService accountService;

    /**
     * 处理浏览器用户登录的请求
     * 步骤:
     * 1 调用业务逻辑层对象AccountService的login方法判断用户名密码是否正确
     * 2 如果用户明密码正确,表示登录成功,跳转到送水公司后台管理系统主页
     * 3 否则,给出提示,不进行跳转
     * @param userName 表单采集的用户名
     * @param userPwd 表单采集的密码
     * @return 登录成功,跳转到送水公司后台管理系统主页,登录失败给出提示,重新回到登录页面
     */
    @RequestMapping(value="/login",method = RequestMethod.POST)
    public String loginAccount(String userName, String userPwd, Model model) {
        boolean result = accountService.login(userName, userPwd);
        if (result) {
            return "waterMainMenu";
        } else {
            model.addAttribute("loginFail","用户名密码错误");
            return "index";
        }
    }
}

1.13 导入静态资源文件

​ 项目所有静态资源都放在resource目录下,css存放层叠样式表,fonts存放页面字体信息,images存放项目用到的图片。

送水公司后台管理系统第二天 用户、客户和送水工管理_第4张图片

1.14 导入静态页面

项目所有静态页面都放在resource目录下

送水公司后台管理系统第二天 用户、客户和送水工管理_第5张图片

1 index.html 登录页面

DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>Logintitle>
		<meta charset="utf-8">
		<link th:href="@{/css/style2.css}" rel='stylesheet' type='text/css' />
head>
<body>
	 

	 <div class="main">
		<div class="login-form">

			<h1>用户登录h1>
				<div class="head">
					<img src="../../images/user.png" alt=""/>
				div>
				<form th:action="@{/login}" th:method="post">
					<input type="text" class="text" name="userName" required >
					<input type="password" name="userPwd" required>
					<div class="submit">
						<input type="submit" name="submit" value="登录" >
					div>	
					<p><a href="#">Forgot Password ?a>p>
					<p style="color:red" th:if="${not #strings.isEmpty(loginFail)}" th:text="${loginFail}">p>
				form>
		div>
		 	<div class="copy-right">
				<p>Copyright © 2014.Company name All rights reserved.<a target="_blank" href="http://sc.chinaz.com/moban/">a>p>
			div>
		div>

<div style="display:none"><script src='http://v7.cnzz.com/stat.php?id=155540&web_id=155540' language='JavaScript' charset='gb2312'>script>div>
body>
html>
  1. waterMainMenu.html
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title> XXX送水公司后台管理系统title>


<link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.css}">
<link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap-theme.css}">

<link rel='stylesheet' th:href='@{/css/material-design-iconic-font.min.css}'>

<link rel="stylesheet" th:href="@{/css/style.css}">

head>
<body>

<div id="viewport">

  
  <div id="sidebar">
    <header>
      <a href="#">公司后台管理a>
    header>
    <ul class="nav">
      <li>
        <a>
          <i class="zmdi zmdi-view-dashboard">i> 客户管理
        a>
      li>
      <li>
        <a>
          <i class="zmdi zmdi-link">i> 送水工管理
        a>
      li>
      <li>
        <a>
          <i class="zmdi zmdi-widgets">i> 送水历史管理
        a>
      li>
      <li>
        <a>
          <i class="zmdi zmdi-widgets">i> 计算工资
        a>
      li>
      <li>
        <a>
          <i class="zmdi zmdi-widgets">i> 统计送水数量
        a>
      li>
      <li>
        <a>
          <i class="zmdi zmdi-widgets">i> 修改密码
        a>
      li>
    ul>
  div>
  
  
  <div id="content">
    <nav class="navbar navbar-default">
      <div class="container-fluid" >
        <ul class="nav navbar-nav navbar-right">
          <li>
            <a href="#"><i class="zmdi zmdi-notifications text-danger">i>
            a>
          li>
          <li><a href="#">测试用户123a>li>
        ul>
      div>
    nav>
    <div class="container-fluid">

    div>
  div>

div>

body>
html>

1.15启动应用程序

http://localhost:8091/

1客户列表

点击“客户管理”,显示客户信息列表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dQuH7zSG-1650766048455)(assets/1634816951797.png)]

1.1定义Customer实体类

package com.shouyi.entities;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * TODO: 客户实体类
 * @author caojie
 * @version 1.0
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_customer")
public class Customer {
    /**
     * 客户编号
     */
    private Integer cid;
    /**
     * 客户名称
     */
    private String custName;
    /**
     * 客户地址
     */
    private String custAddress;
    /**
     * 客户联系方式
     */
    private String custMobile;
    /**
     * 水票数量
     */
    private String custTicket;
}

1.2 定义Mapper接口

package com.shouyi.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.shouyi.entities.Customer;
import org.springframework.stereotype.Repository;

/**
 * TODO:客户管理的映射器,在客户表和实体类之间做映射
 * @author caojie
 * @version 1.0
 */
@Repository
public interface CustomerMapper extends BaseMapper<Customer> {
}

1.3 编写业务逻辑接口Service

package com.shouyi.service;

import com.shouyi.entities.Customer;

import java.util.List;

/**
 * TODO: 客户管理
 * @author caojie
 * @version 1.0
 */
public interface CustomerService {

    /**
     * 返回所有客户信息
     * @return 客户列表
     */
    List<Customer> listCustomer();
}

1.4 编写Service实现类

package com.shouyi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shouyi.entities.Customer;
import com.shouyi.mapper.CustomerMapper;
import com.shouyi.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * TODO:客户管理接口实现类
 *
 * @author caojie
 * @version 1.0
 */
@Service
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private CustomerMapper customerMapper;
    /**
     * 返回所有客户信息
     *
     * @return 客户列表
     */
    @Override
    public List<Customer> listCustomer() {
        return customerMapper.selectList(null);
    }
}

1.5 编写Controller控制器

package com.minzu.controller;

import com.minzu.entities.Customer;
import com.minzu.service.CustomerService;
import com.minzu.service.impl.CustomerServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

/**
 * TODO: 客户管理的控制器,处理客户管理所有的请求
 *
 * @author caojie
 * @version 1.0
 * @date 2021/10/22 8:29
 */
@Controller
@RequestMapping("/cust")
@Slf4j
public class CustomerController {
    /**
     * 控制器依赖业务逻辑,按照类型自动装配CustomerService对象
     */
    @Autowired
    private CustomerService customerService  ;

    /**
     * 用户点击"客户管理"超链接按钮,显示所有的客户信息
     * 步骤:
     * 1 调用CustomerService对象的listCustomer方法查询所有的客户信息
     * 2 将客户信息渲染到客户列表页面
     * 3 跳转到客户列表页面
     * @param model 在前端和后端之间传递数据的对象
     * @return 客户列表页面
     */
    @RequestMapping("/listCust")
    public String listCustomer(Model model) {
        List<Customer> custList = customerService.listCustomer();
        model.addAttribute("custList",custList);
        return "customerList";
    }
}

1.6 导入静态页面

DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title> XXX送水公司后台管理系统title>

    
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.css}">
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap-theme.css}">
    
    <link rel='stylesheet' th:href='@{/css/material-design-iconic-font.min.css}'>
    
    <link rel="stylesheet" th:href="@{/css/style.css}">

head>
<body>

<div id="viewport">

    
    <div id="sidebar">
        <header>
            <a href="#">公司后台管理a>
        header>
        <ul class="nav">
            <li>
                <a >
                    <i class="zmdi zmdi-view-dashboard">i> 客户管理
                a>
            li>
            <li>
                <a>
                    <i class="zmdi zmdi-link">i> 送水工管理
                a>
            li>
            <li>
                <a>
                    <i class="zmdi zmdi-widgets">i> 送水历史管理
                a>

        ul>
    div>

    
    <div id="content">
        <nav class="navbar navbar-default">
            <div class="container-fluid" >
                <ul class="nav navbar-nav navbar-right">
                    <li>
                        <a href="#"><i class="zmdi zmdi-notifications text-danger">i>
                        a>
                    li>
                    <li><a href="#">测试用户123a>li>
                ul>
            div>
        nav>
        <div class="container-fluid">
            <div class="row">
                <div class="col-md-12">
                    <table class="table table-hover table-striped">
                        <thead>
                        <tr>
                            <td>客户编号td>
                            <td>客户名称td>
                            <td>客户地址td>
                            <td>联系方式td>
                            <td>水票数量td>
                        tr>
                        thead>
                        <tbody>
                            
                        tbody>
                    table>
                div>
            div>
        div>
    div>
  div>
div>

body>
html>

1.7 修改主菜单

在“客户管理”菜单的超链接标签添加路径th:href="@{/cust/listCust}"

      <li>
        <a th:href="@{/cust/listCust}">
          <i class="zmdi zmdi-view-dashboard">i> 客户管理
        a>
      li>

1.8 运行程序

http://localhost:8091](http://localhost:8091

1.9存在的问题

​ 主页面waterMainMenu.html和客户列表页面custList.html存在大量重复的代码。如何解决?可以使⽤th:fragment 属性来定义被包含的模版⽚段,以供其他模版包含。

1.修改“主页面“的侧边栏

  <div id="sidebar" th:fragment="sidebar">
2. 修改“主页面“的导航块
<nav class="navbar navbar-default" th:fragment="navbar">
  1. 修改“客户管理”页面的侧边栏,去掉div标签里面的内容
    
	<div id="sidebar" th:replace="waterMainMenu::sidebar">

    div>

4.修改“客户管理“页面的导航块

       
		<nav class="navbar navbar-default" th:replace="waterMainMenu::navbar">

        nav>

2 添加客户

2.1 编写CustomerService接口

CustomerService接口增加saveCustomer方法

    /**
     * 添加客户信息
     * @param customer 表单采集的客户信息
     * @return 受影响行数,大于0添加成功,否则添加失败
     */
    int saveCustomer(Customer customer);

2.2 编写接口实现类

实现CustomerService接口的saveCustomer方法

    /**
     * 添加客户信息
     * @param customer 表单采集的客户信息
     * @return 受影响行数,大于0添加成功,否则添加失败
     */
    @Override
    public int saveCustomer(Customer customer) {
        return customerMapper.insert(customer);
    }

2.3 编写CustomerController

当客户提交表单,将表单的客户信息持久化到数据库中,添加成功返回“用户列表”页面

    /**
     * 点击“添加”按钮跳转到“添加客户”页面
     * @return “添加客户”页面
     */
    @RequestMapping("/preSaveCust")
    public String preSaveCust() {
        return "custSave";
    }

    /**
     * 添加客户信息,将表单输入的客户信息持久化到数据库中,添加成功返回客户列表页面
     * @param customer
     * @return
     */
    @RequestMapping(value = "/saveCust",method = RequestMethod.POST)
    public String saveCust(Customer customer) {
        log.info("Customer = "+customer);
        int rows = customerService.saveCustomer(customer);
        log.info("save customer row = "+rows);
        // 重定向到客户列表,将新添加的客户信息显示到客户列表
        return "redirect:/cust/listCust";
    }

2.4 在custList.html增加一个“添加”按钮

                <div class="col-md-12">
                    <div class="col-md-4">
                        <a class="btn btn-primary" th:href="@{/cust/preSaveCust}">添加客户a>
                    div>
				div>

2.5 新建"添加客户"页面custSave.html

DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title> XXX送水公司后台管理系统title>

    
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.css}">
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap-theme.css}">
    
    <link rel='stylesheet' th:href='@{/css/material-design-iconic-font.min.css}'>
    
    <link rel="stylesheet" th:href="@{/css/style.css}">

head>
<body>

<div id="viewport">

    
    <div id="sidebar" th:replace="waterMainMenu::sidebar">

    div>

    
    <div id="content">
        <nav class="navbar navbar-default" th:replace="waterMainMenu::navbar">

        nav>
        <div class="container-fluid">
            <div class="row">
                <div class="col-md-12">
                    <form class="form-horizontal" method="post" th:action="@{/cust/saveCust}" >
                        <div class="form-group">
                            <label  class="col-sm-2 control-label">客户名称label>
                            <div class="col-sm-5">
                                <input type="text" class="form-control" name="custName"  placeholder="客户名称">
                            div>
                        div>

                        <div class="form-group">
                            <label  class="col-sm-2 control-label">客户地址label>
                            <div class="col-sm-5">
                                <input type="text" class="form-control" name="custAddress"  placeholder="客户地址">
                            div>
                        div>

                        <div class="form-group">
                            <label  class="col-sm-2 control-label">联系方式label>
                            <div class="col-sm-5">
                                <input type="text" class="form-control" name="custMobile"  placeholder="联系方式">
                            div>
                        div>
                        <div class="form-group" >
                            <label  class="col-sm-2 control-label">水票数量label>
                            <div class="col-sm-5">
                                <input type="text" class="form-control" name="custTicket"  placeholder="水票数量">
                            div>
                        div>
                        <div class="form-group">
                            <div class="col-sm-offset-2 col-sm-5">
                                <input type="submit" class="btn btn-primary" name="submit"  value="提交">
                                  
                                <input type="reset" class="btn btn-warning" name="reset"  value="取消">
                            div>

                        div>
                    form>
                div>
            div>
        div>
    div>
div>
div>

body>
html>

3 搜索客户

客户名称作为搜索条件,查询满足条件的客户信息。例如:使用模糊查询,搜索所有包含“老”的客户信息。

送水公司后台管理系统第二天 用户、客户和送水工管理_第6张图片

3.1 编写CustomerService接口

CustomerService接口增加searchCustomer方法

    /**
     * 根据客户名称搜索满足条件客户信息
     * @param custName 客户名称
     * @return 客户列表
     */
    List<Customer> searchCustomer(String custName);

3.2 编写接口实现类

实现CustomerService接口的searchCustomer方法

    /**
     * 根据客户名称搜索满足条件客户信息
     *
     * @param custName 客户名称
     * @return 客户列表
     */
    @Override
    public List<Customer> searchCustomer(String custName) {
        QueryWrapper<Customer> qw = new QueryWrapper<>();
        qw.like("cust_name",custName);
        return customerMapper.selectList(qw);
    }

3.3 编写CustomerController

根据表单提供的“客户名称”,查询满足条件客户信息,最后返回客户列表页面。

    /**
     * 根据客户名称搜索满足条件的客户信息
     * @param custName 客户名称
     * @param model
     * @return 客户列表页面
     */
    @RequestMapping("/searchCustomer")
    public String searchCustomer(String custName,Model model) {
        log.info("search custName = "+custName);
        List<Customer> custList = customerService.searchCustomer(custName);
        // 满足条件的客户列表渲染到页面
        model.addAttribute("custList",custList);
        return "custList";
    }

3.4 编写搜索表单

                    <div class="col-md-8">
                        <form class="form-inline" th:action="@{/cust/searchCustomer}">
                            <input type="text" class="form-control" th:name="custName" placeholder="请输入客户名称"/>
                            <input type="submit" class="btn btn-primary" name="search" value="搜索"/>
                        form>
                    div>

4 根据ID删除客户信息

4.1编写CustomerService接口

CustomerService接口增加deleteCustomerById方法

    /**
     * 根据客户ID删除对应的客户信息
     * @param cid 客户ID
     * @return 受影响行数,大于0删除成功,否则删除失败
     */
    int deleteCustomerById(Integer cid);

4.2 编写接口实现类

实现CustomerService接口的deleteCustomerById方法

    /**
     * 根据客户ID删除对应的客户信息
     *
     * @param cid 客户ID
     * @return 受影响行数,大于0删除成功,否则删除失败
     */
    @Override
    public int deleteCustomerById(Integer cid) {
        QueryWrapper<Customer> qw = new QueryWrapper<>();
        qw.eq("cid",cid);
        return customerMapper.delete(qw);
    }

4.3 编写CustomerController

根据浏览器传入的客户ID删除对应的客户信息,然后返回客户列表

    /**
     * 根据客户ID删除客户信息,返回客户列表页面,显示删除之后的客户列表
     * @param cid 客户id
     * @return 客户列表
       /delCust?id=1
       Restful路径
       /cust/delCust/{id}
     */
    @RequestMapping("/delCust/{cid}")
    public String deleteCustomer(@PathVariable("cid") Integer cid) {
        log.info("delete Customer cid = "+ cid);
        int rows = customerService.deleteCustomerById(cid);
        log.info("delete customer rows = "+rows);
        // 查询已删除的客户列表信息
        return "redirect:/cust/listCust";
    }

4.4 客户列表页面增加删除按钮

                            
							<td>
                                <a class="glyphicon glyphicon-remove" th:href="@{'/cust/delCust/'+${cust.cid}}">a>
                            td>

5 修改客户

5.1数据回显

送水公司后台管理系统第二天 用户、客户和送水工管理_第7张图片

点击修改按钮,跳转到“修改客户”页面,显示要修改的客户信息。步骤如下:

1.在CustomerService接口新增加getCustomerById方法根据客户ID查询对应的客户信息。

 /**
     * 根据客户ID查询对应的客户信息
     * @param cid 客户ID
     * @return 客户信息
     */
    Customer getCustomerById(Integer cid);

2.在CustomerServiceImpl实现类覆写接口定义的getCustomerById方法根据客户ID查询对应的客户信息。

    /**
     * 根据客户ID查询客户信息
     * @param cid 客户id
     * @return 客户实体
     */
    @Override
    public Customer getCustomerById(Integer cid) {
        QueryWrapper<Customer> qw = new QueryWrapper<>();
        qw.eq("cid",cid);
        return customerMapper.selectOne(qw);
    }

3.在CustomerController控制器新增preUpateCustomer方法完成数据的回显。调用CustomerService接口的getCustomerById方法,将客户信息渲染到页面。

    /**
     * 点击“修改”按钮,页面传入的客户ID查询对应的客户信息,将查询的信息渲染到“修改客户”页面
     * @param cid 客户ID
     * @param model
     * @return “修改客户”页面
     */
    @RequestMapping("/preUpdateCust/{cid}")
    public String preUpdateCustomer(@PathVariable("cid") Integer cid,Model model) {
        log.info("update Customer cid = "+cid);
        Customer cust = customerService.getCustomerById(cid);
        model.addAttribute("cust",cust);
        // 水票数量渲染到前端
        return "custUpdate";
    }

4 在"客户列表"页面添加“修改按钮”

  <a class="glyphicon glyphicon-edit" th:href="@{'/cust/preUpdateCust/'+${cust.cid}}">a>

5.新增加“修改客户”页面。

DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title> XXX送水公司后台管理系统title>

    
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.css}">
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap-theme.css}">
    
    <link rel='stylesheet' th:href='@{/css/material-design-iconic-font.min.css}'>
    
    <link rel="stylesheet" th:href="@{/css/style.css}">

head>
<body>

<div id="viewport">

    
    <div id="sidebar" th:replace="waterMainMenu::sidebar">

    div>

    
    <div id="content">
        <nav class="navbar navbar-default" th:replace="waterMainMenu::navbar">

        nav>
        <div class="container-fluid">
            <div class="row">
                <div class="col-md-12">
                    <form class="form-horizontal" method="post" th:action="@{/cust/updateCust}" >
                        <input type="hidden" th:value="${cust.cid}" name="cid"/>
                        <div class="form-group">
                            <label  class="col-sm-2 control-label">客户名称label>
                            <div class="col-sm-5">
                                <input type="text"
                                       class="form-control"
                                       th:value="${cust.custName}"
                                       name="custName">
                            div>
                        div>

                        <div class="form-group">
                            <label  class="col-sm-2 control-label">客户地址label>
                            <div class="col-sm-5">
                                <input type="text"
                                       class="form-control"
                                       th:value="${cust.custAddress}"
                                       name="custAddress">
                            div>
                        div>

                        <div class="form-group">
                            <label  class="col-sm-2 control-label">联系方式label>
                            <div class="col-sm-5">
                                <input type="text"
                                       class="form-control"
                                       th:value="${cust.custMobile}"
                                       name="custMobile">
                            div>
                        div>
                        <div class="form-group" >
                            <label  class="col-sm-2 control-label">水票数量label>
                            <div class="col-sm-5">
                                <input type="text"
                                       class="form-control"
                                       th:value="${cust.custTicket}"
                                       name="custTicket">
                            div>
                        div>
                        <div class="form-group">
                            <div class="col-sm-offset-2 col-sm-5">
                                <input type="submit" class="btn btn-primary" name="submit"  value="提交">
                                  
                                <input type="reset" class="btn btn-warning" name="reset"  value="取消">
                            div>

                        div>
                    form>
                div>
            div>
        div>
    div>
div>

div>

body>
html>

5.2 修改表单客户信息

送水公司后台管理系统第二天 用户、客户和送水工管理_第8张图片

在“修改客户”页面提交表单,将修改的数据持久化到数据库

1.在CustomerService接口新增加updateCustomer方法修改客户信息。

    /**
     * 修改客户信息
     * @param customer 浏览器表单采集的客户信息
     * @return 受影响行数,大于0修改成功,否则修改失败
     */
    int updateCustomer(Customer customer);

2.在CustomerServiceImpl实现类覆写接口定义的updateCustomer方法修改客户信息。

    /**
     * 修改客户信息
     * @param customer 浏览器表单采集的客户信息
     * @return 受影响行数,大于0修改成功,否则修改失败
     */
    @Override
    public int updateCustomer(Customer customer) {
        QueryWrapper<Customer> qw = new QueryWrapper<>();
        // update ..... where cid = ?
        qw.eq("cid",customer.getCid());
        return customerMapper.update(customer,qw);
    }

3.在CustomerController控制器新增upateCustomer方法修改客户信息,然后返回客户列表显示已修改的信息

    @RequestMapping(value = "/updateCust",method = RequestMethod.POST)
    public String updateCustomer(Customer customer) {
        log.info("update customer = "+customer);
        int rows = customerService.updateCustomer(customer);
        log.info("update rows = "+rows);
        // 修改成功查询客户列表,跳转到客户页面
        return "redirect:/cust/listCust";
    }

1 添加送水工

​ 在浏览器采集送水工信息(名称、底薪、提成、照片),然后将送水工信息持久化(插入)到对应的表中。添加送水工的核心步骤是将浏览器选择的照片上传到服务器。

送水公司后台管理系统第二天 用户、客户和送水工管理_第9张图片

1.1 编写yml

​ 配置上传文件的配置信息

# 配置浏览器上传图像到服务器的路径
location: D:/upLoad/picture/

  # 配置静态资源路径
  # Springboot有四个地方可以放静态资源
  #  classpath:/static/
  #  classpath:/public/
  # classpath:/resources/
  # classpath:/META-INF/resource/
  resources:
    static-locations: classpath:/static/,classpath:/public/,classpath:/resources/,classpath:/META-INF/resource/,file:${location}    
  # 配置上传文件大小限制
  servlet:
    multipart:
      max-request-size: 100MB
      max-file-size: 100MB    

1.2 编写WorkerService接口

​ 定义添加送水工对应的方法saveWorker

    /**
     * 添加送水工
     * @param worker 送水工信息
     * @return 受影响行数,大于0添加成功,否则添加失败
     */
    int saveWorker(Worker worker);

1.3 编写接口实现类

​ 在接口实现类WorkerServiceImpl中实现接口的方法

    @Override
    public int saveWorker(Worker worker) {
        return workerMapper.insert(worker);
    }

1.4 编写控制器

​ 从yml配置文件中读取服务器存放上传图像的路径

    /**
     * 从yml配置文件中读取服务器存放上传图像的路径
     */
    @Value("${location}")
    private String location;

​ 在WorkerController控制器中定义preSaveWorker方法,当用户点击“添加”按钮跳转到添加页面workerSave.html

    @RequestMapping("/preSaveWorker")
    public String preSaveWorker(){
        return "workerSave";
    }

​ 在WorkerController控制器中定义saveWorker方法。当用户提交表单将浏览器选择的文件上传到服务器中,并且将送水工信息持久化到数据库中,最后返回“送水工”列表页面,能够查看添加之后的送水工信息。

    /**
     添加送水工信息
     步骤:
     1 将浏览器选择的图像上传到服务器指定的路径
     1.1 获取上传文件的名称
     1.2 获取上传文件后缀的索引
     1.3 获取上传文件的后缀,例如:.png
     1.4 获取上传文件的前缀。前缀的格式为:1970-01-01距离现在的纳秒数。例如:1565634653563456
     1.5 拼接上传文件的前缀和后缀,例如:1565634653563456.png
     1.6 创建服务器存放浏览器上传文件的File对象
     1.7 判断File对象的物理路径是否存在,如果不存在就创建该路径
     1.8 创建上传文件的File对象
     1.9 调用MultipartFile对象的transferTo方法上传文件。
     1.10 将上传文件名称设置到Worker对象中
     2 调用workerService对象的saveWorker方法,将送水工信息持久化到数据库
     3 重定向到送水工列表,显示新增加的送水工信息

     * @param worker 送水工信息
     * @param file  封装了浏览器选择的送水工图像
     * @return
     */
	@RequestMapping(value="/workerSave",method = RequestMethod.POST)
    public String saveWorker(Worker worker, MultipartFile file) {
        // 条件成立:表示用户在浏览器上传了图像
        if(null != file) {
            // 获取上传文件的名称
            String fileName = file.getOriginalFilename();
            // 获取上传文件后缀的索引
            int index = fileName.lastIndexOf(".");
            // 获取上传文件的后缀,例如:.png
            String suffix = fileName.substring(index);
            // 返回1970-01-01距离现在的毫秒数作为上传文件的前缀
            // 例如: 1565634653563456
            long prefix = System.nanoTime();
            // 拼接上传文件的前缀和后缀,例如:1565634653563456.png
            String uploadFileName = prefix + suffix;
            // 创建服务器存放浏览器上传文件的File对象
            File uploadFile = new File(location);
            // 条件成立:表示路径不存在,在服务器磁盘上创建改路径
            if(!uploadFile.exists()) {
                uploadFile.mkdirs();
            }
            // 创建上传文件的File对象
            File path = new File(uploadFile,uploadFileName);
            try {
                file.transferTo(path);
            } catch (IOException e) {
                log.error("上传失败",e);
                e.printStackTrace();
            }
            worker.setWorkerImage(uploadFileName);
        }
        int rows = workerService.saveWorker(worker);

        log.info("worker save rows = "+rows);
        return "redirect:/worker/workerList";
    }

1.5 修改workerList.html页面

在workerList.html页面增加添加按钮

                <div class="col-md-12">
                    <div class="col-md-4">
                        <a class="btn btn-primary" th:href="@{/worker/preSaveWorker}">添加a>
                    div>
                div>

                            <td>
                                
                                <img class="myWorkerImage"
                                     th:if="${#strings.isEmpty(worker.workerImage)}"
                                     src="../../images/user.png" />
                                
                                <img class="myWorkerImage"
                                    th:if="${not #strings.isEmpty(worker.workerImage)}"
                                    th:src="'http://localhost:8091/'+${worker.workerImage}"/>
                            td>

1.6 编写workerSave.html页面

DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title> XXX送水公司后台管理系统title>

    
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.css}">
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap-theme.css}">
    
    <link rel='stylesheet' th:href='@{/css/material-design-iconic-font.min.css}'>
    
    <link rel="stylesheet" th:href="@{/css/style.css}">

head>
<body>

<div id="viewport">

    
    <div id="sidebar" th:replace="waterMainMenu::sidebar">

    div>

    
    <div id="content">
        <nav class="navbar navbar-default" th:replace="waterMainMenu::navbar">

        nav>
        <div class="container-fluid">
            <div class="row">
                <div class="col-md-12">
                    <form class="form-horizontal" enctype="multipart/form-data"
                          method="post" th:action="@{/worker/workerSave}" >
                        <div class="form-group">
                            <label  class="col-sm-2 control-label">送水工名称label>
                            <div class="col-sm-5">
                                <input type="text" class="form-control"
                                       name="workerName"  placeholder="送水工名称">
                            div>
                        div>

                        <div class="form-group">
                            <label  class="col-sm-2 control-label">送水工底薪label>
                            <div class="col-sm-5">
                                <input type="text" class="form-control"
                                       name="workerSalary"  placeholder="送水工底薪">
                            div>
                        div>

                        <div class="form-group" >
                            <label  class="col-sm-2 control-label">送水工提成label>
                            <div class="col-sm-5">
                                <input type="text" class="form-control"
                                       name="workerMoney"  placeholder="送水工提成">
                            div>
                        div>

                        <div class="form-group">
                            <label  class="col-sm-2 control-label">送水工照片label>
                            <div class="col-sm-5">
                                <input type="file" class="form-control" name="file">
                            div>
                        div>
                        <div class="form-group">
                            <div class="col-sm-offset-2 col-sm-5">
                                <input type="submit" class="btn btn-primary" name="submit"  value="提交">
                                  
                                <input type="reset" class="btn btn-warning" name="reset"  value="取消">
                            div>

                        div>
                    form>
                div>
            div>
        div>
    div>
div>

div>

body>
html>

2 修改送水工

2.1 数据回显

点击“修改”按钮,跳转到“修改送水工”页面,显示送水工信息

送水公司后台管理系统第二天 用户、客户和送水工管理_第10张图片

2.1.1 编写WorkerService接口

​ 定义getWorkerById方法,根据送水工ID获取对应的送水工信息

    /**
     * 根据送水工ID获取对应的送水工信息
     * @param wid 送水工id
     * @return 送水工信息
     */
    Worker getWorkerById(Integer wid);
2.1.2编写接口实现类

​ 接口实现类WorkerServiceImpl实现WorkerService接口的getWorkerById方法。

    /**
     * 根据送水工ID获取对应的送水工信息
     *
     * @param wid 送水工id
     * @return 送水工信息
     */
    @Override
    public Worker getWorkerById(Integer wid) {
        QueryWrapper<Worker> qw = new QueryWrapper<>();
        qw.eq("wid",wid);
        return workerMapper.selectOne(qw);
    }
2.1.3编写WorkerController控制器

定义preUpdateWorker方法,点击“修改”按钮,数据回显。根据id查询对应的送水工信息,并将信息渲染到“修改送水工”页面

    /**
     * 点击“修改”按钮,数据回显。根据id查询对应的送水工信息,并将信息渲染到“修改送水工”页面
     * @param wid 送水工id
     * @param model
     * @return “修改送水工”页面
     */
    @RequestMapping("/preUpdateWorker/{wid}")
    public String preUpdateWorker(@PathVariable("wid") Integer wid,Model model) {
        log.info("pre update worker wid = "+wid);
        Worker worker = workerService.getWorkerById(wid);
        model.addAttribute("worker",worker);
        return "workerUpdate";
    }
2.1.4 修改workerList.html页面

在页面中新增加修改按钮,点击“修改”按钮,跳转到workerUpdate页面,回显送水工信息

    <td>操作td>

                            <td>
                                <a class="glyphicon glyphicon-edit"
                                   th:href="@{'/worker/preUpdateWorker/'+${worker.wid}}">a>
                            td>

2.1.5 编写workerUpdate.html页面

该页面显示要修改的送水工信息(送水工名称、底薪、提成、照片)

DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title> XXX送水公司后台管理系统title>

    
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.css}">
    <link rel='stylesheet' th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap-theme.css}">
    
    <link rel='stylesheet' th:href='@{/css/material-design-iconic-font.min.css}'>
    
    <link rel="stylesheet" th:href="@{/css/style.css}">
    <style>
        img{
            width:100px;
            height:100px;
            border:1px solid red;
        }
    style>
head>
<body>

<div id="viewport">

    
    <div id="sidebar" th:replace="waterMainMenu::sidebar">

    div>

    
    <div id="content">
        <nav class="navbar navbar-default" th:replace="waterMainMenu::navbar">

        nav>
        <div class="container-fluid">
            <div class="row">
                <div class="col-md-12">
                    <form class="form-horizontal" enctype="multipart/form-data" method="post" th:action="@{/worker/updateWorker}" >
                        <input type="hidden" th:value="${worker.wid}" name="wid"/>
                        <input type="hidden" th:value="${worker.workerImage}" name="workerImage"/>

                        <div class="form-group">
                            <label  class="col-sm-2 control-label">送水工名称label>
                            <div class="col-sm-5">
                                <input type="text"
                                       class="form-control"
                                       th:value="${worker.workerName}"
                                       name="workerName">
                            div>
                        div>

                        <div class="form-group">
                            <label  class="col-sm-2 control-label">送水工底薪label>
                            <div class="col-sm-5">
                                <input type="text"
                                       class="form-control"
                                       th:value="${worker.workerSalary}"
                                       name="workerSalary">
                            div>
                        div>

                        <div class="form-group">
                            <label  class="col-sm-2 control-label">送水工提成label>
                            <div class="col-sm-5">
                                <input type="text"
                                       class="form-control"
                                       th:value="${worker.workerMoney}"
                                       name="workerMoney">
                            div>
                        div>
                        <div class="form-group" >
                            <label  class="col-sm-2 control-label">送水工照片label>
                            <div class="col-sm-3">
                                <input type="file" class="form-control" name="file">
                            div>
                            <div class="col-sm-2">
                                <img
                                        th:if="${not #strings.isEmpty(worker.workerImage)}"
                                        th:src="'http://localhost:8091/'+${worker.workerImage}"/>
                            div>
                        div>
                        <div class="form-group">
                            <div class="col-sm-offset-2 col-sm-5">
                                <input type="submit" class="btn btn-primary" name="submit"  value="提交">
                                  
                                <input type="reset" class="btn btn-warning" name="reset"  value="取消">
                            div>

                        div>
                    form>
                div>
            div>
        div>
    div>
div>

div>

body>
html>

2.2 提交表单修改送水工信息

2.2.1 编写WorkerService接口

定义updateWorker方法修改送水工信息

    /**
     * 修改送水工
     * @param worker 送水工信息
     * @return 受影响行数,大于0修改成功,否则修改失败
     */
    int updateWorker(Worker worker);
2.2.2 编写接口实现类

接口实现类WorkerServiceImpl实现updateWorker方法

    /**
     * 修改送水工
     * @param worker 送水工信息
     * @return 受影响行数,大于0修改成功,否则修改失败
     */
    @Override
    public int updateWorker(Worker worker) {
        QueryWrapper<Worker> qw = new QueryWrapper<>();
        qw.eq("wid",worker.getWid());
        return workerMapper.update(worker,qw);
    }
2.2.3 编写WorkerController控制器
    /**
     * 在“修改送水工”页面点击“提交”按钮,修改送水工信息,将修改的信息持久化到数据库
     * @param worker 送水工信息
     * @param file 封装了要上传文件的信息
     * @return 送水工列表请求路径,重新查询已修改的送水工信息
     */
    @RequestMapping(value="/updateWorker",method = RequestMethod.POST)
    public String updateWorker(Worker worker, MultipartFile file) {
        // 条件成立:表示用户在浏览器上传了图像
        if(null != file) {
            // 获取上传文件的名称
            String fileName = file.getOriginalFilename();
            // 获取上传文件后缀的索引
            int index = fileName.lastIndexOf(".");
            // 获取上传文件的后缀,例如:.png
            String suffix = fileName.substring(index);
            // 返回1970-01-01距离现在的纳秒数作为上传文件的前缀
            // 例如: 1565634653563456
            long prefix = System.nanoTime();
            // 拼接上传文件的前缀和后缀,例如:1565634653563456.png
            String uploadFileName = prefix + suffix;
            // 创建服务器存放浏览器上传文件的File对象
            File uploadFile = new File(location);
            // 条件成立:表示路径不存在,在服务器磁盘上创建改路径
            if(!uploadFile.exists()) {
                uploadFile.mkdirs();
            }
            // 创建上传文件的File对象
            // 参数1:上传文件的路径,参数2:上传文件的名称
            File path = new File(uploadFile,uploadFileName);
            try {
                file.transferTo(path);
            } catch (IOException e) {
                log.error("上传失败",e);
                e.printStackTrace();
            }
            worker.setWorkerImage(uploadFileName);
        }
        int rows = workerService.updateWorker(worker);

        log.info("worker update rows = "+rows);
        return "redirect:/worker/workerList";
    }

3 文件上传重构

什么是软件重构?重新组织代码结构,让你的程序更加整洁、高效的运行

为什么需要重构?添加送水工和修改送水工“上传文件”功能有大量重复的代码

    @RequestMapping("/preSaveWorker")
    public String preSaveWorker(){
        return "workerSave";
    }

    /**
     添加送水工信息
     步骤:
     1 将浏览器选择的图像上传到服务器指定的路径
     1.1 获取上传文件的名称
     1.2 获取上传文件后缀的索引
     1.3 获取上传文件的后缀,例如:.png
     1.4 获取上传文件的前缀。前缀的格式为:1970-01-01距离现在的纳秒数。例如:1565634653563456
     1.5 拼接上传文件的前缀和后缀,例如:1565634653563456.png
     1.6 创建服务器存放浏览器上传文件的File对象
     1.7 判断File对象的物理路径是否存在,如果不存在就创建该路径
     1.8 创建上传文件的File对象
     1.9 调用MultipartFile对象的transferTo方法上传文件。
     1.10 将上传文件名称设置到Worker对象中
     2 调用workerService对象的saveWorker方法,将送水工信息持久化到数据库
     3 重定向到送水工列表,显示新增加的送水工信息

     * @param worker 送水工信息
     * @param file  封装了浏览器选择的送水工图像
     * @return
     */
    @RequestMapping(value="/workerSave",method = RequestMethod.POST)
    public String saveWorker(Worker worker, MultipartFile file) {
        transferFile(worker, file);
        int rows = workerService.saveWorker(worker);

        log.info("worker save rows = "+rows);
        return "redirect:/worker/workerList";
    }

    /**
     * 处理浏览器上传文件的逻辑
     * @param worker
     * @param file
     */
    private void transferFile(Worker worker, MultipartFile file) {
        // 条件成立:表示用户在浏览器上传了图像
        if (null != file) {
            // 获取上传文件的名称
            String fileName = file.getOriginalFilename();
            // 获取上传文件后缀的索引
            int index = fileName.lastIndexOf(".");
            // 获取上传文件的后缀,例如:.png
            String suffix = fileName.substring(index);
            // 返回1970-01-01距离现在的纳秒数作为上传文件的前缀
            // 例如: 1565634653563456
            long prefix = System.nanoTime();
            // 拼接上传文件的前缀和后缀,例如:1565634653563456.png
            String uploadFileName = prefix + suffix;
            // 创建服务器存放浏览器上传文件的File对象
            File uploadFile = new File(location);
            // 条件成立:表示路径不存在,在服务器磁盘上创建改路径
            if (!uploadFile.exists()) {
                uploadFile.mkdirs();
            }
            // 创建上传文件的File对象
            // 参数1:上传文件的路径,参数2:上传文件的名称
            File path = new File(uploadFile, uploadFileName);
            try {
                file.transferTo(path);
            } catch (IOException e) {
                log.error("上传失败", e);
                e.printStackTrace();
            }
            worker.setWorkerImage(uploadFileName);
        }
    }

    /**
     * 点击“修改”按钮,数据回显。根据id查询对应的送水工信息,并将信息渲染到“修改送水工”页面
     * @param wid 送水工id
     * @param model
     * @return “修改送水工”页面
     */
    @RequestMapping("/preUpdateWorker/{wid}")
    public String preUpdateWorker(@PathVariable("wid") Integer wid,Model model) {
        log.info("pre update worker wid = "+wid);
        Worker worker = workerService.getWorkerById(wid);
        model.addAttribute("worker",worker);
        return "workerUpdate";
    }

    /**
     * 在“修改送水工”页面点击“提交”按钮,修改送水工信息,将修改的信息持久化到数据库
     * @param worker 送水工信息
     * @param file 封装了要上传文件的信息
     * @return 送水工列表请求路径,重新查询已修改的送水工信息
     */
    @RequestMapping(value="/updateWorker",method = RequestMethod.POST)
    public String updateWorker(Worker worker, MultipartFile file) {
        // 条件成立:表示用户在浏览器上传了图像
        transferFile(worker, file);
        int rows = workerService.updateWorker(worker);

        log.info("worker update rows = "+rows);
        return "redirect:/worker/workerList";
    }

	ginalFilename();
            // 获取上传文件后缀的索引
            int index = fileName.lastIndexOf(".");
            // 获取上传文件的后缀,例如:.png
            String suffix = fileName.substring(index);
            // 返回1970-01-01距离现在的纳秒数作为上传文件的前缀
            // 例如: 1565634653563456
            long prefix = System.nanoTime();
            // 拼接上传文件的前缀和后缀,例如:1565634653563456.png
            String uploadFileName = prefix + suffix;
            // 创建服务器存放浏览器上传文件的File对象
            File uploadFile = new File(location);
            // 条件成立:表示路径不存在,在服务器磁盘上创建改路径
            if (!uploadFile.exists()) {
                uploadFile.mkdirs();
            }
            // 创建上传文件的File对象
            // 参数1:上传文件的路径,参数2:上传文件的名称
            File path = new File(uploadFile, uploadFileName);
            try {
                file.transferTo(path);
            } catch (IOException e) {
                log.error("上传失败", e);
                e.printStackTrace();
            }
            worker.setWorkerImage(uploadFileName);
        }
    }

    /**
     * 点击“修改”按钮,数据回显。根据id查询对应的送水工信息,并将信息渲染到“修改送水工”页面
     * @param wid 送水工id
     * @param model
     * @return “修改送水工”页面
     */
    @RequestMapping("/preUpdateWorker/{wid}")
    public String preUpdateWorker(@PathVariable("wid") Integer wid,Model model) {
        log.info("pre update worker wid = "+wid);
        Worker worker = workerService.getWorkerById(wid);
        model.addAttribute("worker",worker);
        return "workerUpdate";
    }

    /**
     * 在“修改送水工”页面点击“提交”按钮,修改送水工信息,将修改的信息持久化到数据库
     * @param worker 送水工信息
     * @param file 封装了要上传文件的信息
     * @return 送水工列表请求路径,重新查询已修改的送水工信息
     */
    @RequestMapping(value="/updateWorker",method = RequestMethod.POST)
    public String updateWorker(Worker worker, MultipartFile file) {
        // 条件成立:表示用户在浏览器上传了图像
        transferFile(worker, file);
        int rows = workerService.updateWorker(worker);

        log.info("worker update rows = "+rows);
        return "redirect:/worker/workerList";
    }

你可能感兴趣的:(java,教程,java,restful,后端,架构)