依然是springMVC+mysql的用户登陆小项目(全注释图解超详细)

要提到的是,这篇博客的主干内容是参考自:https://blog.csdn.net/u012393192/article/details/79741148
首先是老生常谈的创建项目:
在这里插入图片描述
要注意的是,这里最好用自己导入的maven,不然会很慢:具体可以参考这个:https://blog.csdn.net/yup1212/article/details/81631030
在这里插入图片描述
然后老老实实创建这几个文件夹,这里要注意的是,按照上面的创建方法,是没有java和resources这两个文件夹的,需要自己创建,可以参考这篇博客:https://blog.csdn.net/qq_41115379/article/details/110939947
在这里插入图片描述
然后然后就是老老实实的把这些代码都放入,以下都是按照我自己的顺序来的
1.pom.xml

  <dependencies>
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.0</version>
      <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
      <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>6.0.6</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.0.3.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.0.3.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-test 测试-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.0.3.RELEASE</version>
      <scope>test</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.4</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
      <version>1.5.8.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
      <version>1.5.7.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.0.3.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.3.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.3.RELEASE</version>
    </dependency>
  </dependencies>

2.domain层的LoginLog

package com.smart.domain;

import java.io.Serializable;
import java.util.Date;
//这些应该是最早创建的
public class LoginLog implements Serializable {
    private int loginLogId;
    //这里有个用户id
    private int userId;
    private String ip;
    private Date loginDate;
    //然后是一系列get set方法

    public int getLoginLogId() {
        return loginLogId;
    }

    public void setLoginLogId(int loginLogId) {
        this.loginLogId = loginLogId;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public Date getLoginDate() {
        return loginDate;
    }

    public void setLoginDate(Date loginDate) {
        this.loginDate = loginDate;
    }
}

3.domain层的User

package com.smart.domain;

import java.io.Serializable;
import java.util.Date;

//继承这个Ser是为了序列化操作
public class User implements Serializable {
    private int userId;
    private String userName;
    private String password;
    private int credits;
    private String lastIP;
    private Date lastVisit;

    //然后是一系列get set方法

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getCredits() {
        return credits;
    }

    public void setCredits(int credits) {
        this.credits = credits;
    }

    public String getLastIP() {
        return lastIP;
    }

    public void setLastIP(String lastIP) {
        this.lastIP = lastIP;
    }

    public Date getLastVisit() {
        return lastVisit;
    }

    public void setLastVisit(Date lastVisit) {
        this.lastVisit = lastVisit;
    }
}

4.Dao层的LoginLogDao

package com.smart.dao;

import com.smart.domain.LoginLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.Objects;

//首先加上在dao层的备注
//并且这一层是用来和数据库进行外接的
@Repository
public class LoginLogDao {
    //私有化属性
    private JdbcTemplate jdbcTemplate;
    //保存登录日志SQL
    private final static String INSERT_LOGIN_LOG_SQL = "INSERT INTO t_login_log (user_id,ip,login_datetime) VALUES (?,?,?)";
    public void insertLoginLog(LoginLog loginLog){
        //创建一个用来存的,并对应插入到数据库中
        Object[] args={loginLog.getUserId(),loginLog.getIp(),loginLog.getLoginDate()};
        //刚好对应这两个参数
        jdbcTemplate.update(INSERT_LOGIN_LOG_SQL,args);

    }
    //这里为什么要自动导入方法呢,留个疑问,它是可以导入方法,但是目的不是通过set方法来消除依赖嘛
    //难道是因为 这个是private 所以是需要有一个set方法,来实现和public一样的作用?
    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
        this.jdbcTemplate=jdbcTemplate;
    }


}

5.Dao层的UserDao

package com.smart.dao;

import com.smart.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;

//同理也写下注解
@Repository
public class UserDao {
    //JdbcTemplate是spring 对jdbc封装,有execute:执行所有sql操作 update 执行insert,update,delete的操作
    //和queryXxx 用于DQL数据查询语句
    private JdbcTemplate jdbcTemplate;
    //这里也导入进去
    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    //首先第一个是更加用户名和密码来获取匹配的用户
    //第一个参数是 userName 用户名
    //第二个参数是 password 密码
    //返回1 表示用户名密码正确 0表示用户名密码错误
    public int getMatchCount(String userName,String password){
        String sqlStr="SELECT count(*) FROM t_user WHERE user_name=? and password=?";
        //然后这里是查询作用,并且返回参数是根据最后一个参数,这个稍微理解一下就行了吧
        return jdbcTemplate.queryForObject(sqlStr,new Object[]{userName,password},Integer.class);
    }

    //然后再写两条静态的,直接查找就行的那种,这种final是说明不能修改嘛,这里也不太清楚为什么这两句可以单独先写出来
    private final static String MATCH_COUNT_SQL="SELECT * FROM t_user WHERE user_name=?";
    private final static String UPDATE_LOGIN_INFO_SQL="UPDATE t_user SET last_visit=?,last_ip=?,credits=?WHERE user_id=?";
    //第二个就是通过用户名来获取对象,也就是刚刚的第一句话
    //参数是用户名,可是这里为什么要用final 也是搞不太清楚
    //返回值是user 对象
    public User findUserByUserName(final String userName){
        //创建对象
        final  User user=new User();
        //调用sql,RowCallbackHandler这个方法需要看一下
        //主要是在于 这个结果有很多行,所以需要增加一个这个

        jdbcTemplate.query(MATCH_COUNT_SQL, new Object[]{userName}, new RowCallbackHandler() {
            public void processRow(ResultSet rs) throws SQLException{
                //我理解是在于 主要这个userName在参数中已经输入了,而id 和credits则是没有set的,是需要导入的
                user.setUserId(rs.getInt("user_id"));
                user.setUserName(userName);
                user.setCredits(rs.getInt("credits"));
            }
        });
        return user;
    }
    //第三个方法是更新用户积分,最后登录ip和最后登录时间
    public void updateLoginInfo(User user){
        //依次输入那些参数
        jdbcTemplate.update(UPDATE_LOGIN_INFO_SQL,new Object[]{user.getLastVisit(),user.getLastIP(),user.getCredits(),user.getUserId()});
    }
}

6.service层的UserService

package com.smart.service;

import com.smart.dao.LoginLogDao;
import com.smart.dao.UserDao;
import com.smart.domain.LoginLog;
import com.smart.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

//其次就是最为难懂的service层
@Service
public class UserService {
    //感觉他的作用就是把Dao层的进行了再次调用
    //设置两个私有的属性.通过set来让他们变的公有
    private UserDao userDao;
    private LoginLogDao loginLogDao;
    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Autowired
    public void setLoginLogDao(LoginLogDao loginLogDao) {
        this.loginLogDao = loginLogDao;
    }
    //然后这里就是调用那些User的方法
    //第一个方法是判断有没有匹配的用户,如果有的话就是1,没有的话就是0
    public boolean hasMatchUser(String userName,String password){
        int match=userDao.getMatchCount(userName,password);
        return match>0;
    }
    //第二个方法是找到对应的user,通过username
    public User findUserByUserName(String userName){
        return userDao.findUserByUserName(userName);
    }
    //第三个方法先是调用了一个transactional 暂时不能;理解
    @Transactional
    public void loginSuccess(User user){
        user.setCredits(5+user.getCredits());
        LoginLog loginLog=new LoginLog();
        //这里也是需要有userid的
        loginLog.setUserId(user.getUserId());
        loginLog.setIp(user.getLastIP());
        loginLog.setLoginDate(user.getLastVisit());
        //再是调用了dao层的代码
        userDao.updateLoginInfo(user);
        //他只有一个插入数据,而这些数据已经刚刚被保存好了
        loginLogDao.insertLoginLog(loginLog);
    }
}

7.web层的LoginCommand

package com.smart.web;
//这个我也不太清楚,可能是因为登录只需要账号和密码吧
public class LoginCommand {
    private String userName;
    private String password;

    public String getUserName() {
        return userName;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

8.web层的LoginController

package com.smart.web;

import com.smart.domain.User;
import com.smart.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

//加入注解
@Controller
public class LoginController {
    private UserService userService;
    //这里就是和前端页面有接触了,并且有点难以理解了
    //首先是index.html。处理这个请求
    @RequestMapping(value = "/index.html")
    public String loginPage(){
        return "login";
    }
    //然后是登录请求
    @RequestMapping("/loginCheck.html")
    public ModelAndView loginCheck(HttpServletRequest request,LoginCommand loginCommand){
        //一个请求和一个登录需要用的参数
        boolean isValidUser=userService.hasMatchUser(loginCommand.getUserName(),loginCommand.getPassword());
        //然后判断是否有效
        if(!isValidUser){
            return new ModelAndView("logError");
        }else{
            //也就是能登录
            User user= userService.findUserByUserName(loginCommand.getUserName());
            //这部分细细的看
            user.setLastIP(request.getLocalAddr());
            user.setLastVisit(new Date());
            userService.loginSuccess(user);
            request.getSession().setAttribute("user",user);
            return new ModelAndView("main");
        }
    }
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

9.WEB-iNF下 jsp下的logError.jsp

<%--
  Created by IntelliJ IDEA.
  User: wzw324
  Date: 2020/12/9
  Time: 15:31
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>error</title>
</head>
<body>
<form action="<c:url value="/index.html" />" method="post">
    <table align="center" >
        <tr>
            <td>error</td>
        </tr>
        <tr>
            <td colspan="2",align="center">
                <input type="submit" value="返回" />
            </td>
        </tr>
    </table>
</form>
</body>
</html>

10.WEB-iNF下 jsp下的login.jsp

<%--
  Created by IntelliJ IDEA.
  User: wzw324
  Date: 2020/12/9
  Time: 15:24
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!--引用核心标签-->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
    <title>login</title>
    <script>
        function checkUser(){
            var result=document.getElementById("userid").value;
            var passowrd=document.getElementById("password").value;
            if(result==""){
                alert("用户名不能为空");
                return false;
            }
            if(password=""){
                alert("密码不能为空");
                return false;
            }
        }
    </script>
</head>
<body>
<%--<c:if test="${!empty error}">--%>
<%--<font color="red"><c:out value="%{error}" /></font>--%>
<%--</c:if>--%>
<form action="<c:url value="/loginCheck.html" />" method="post" onsubmit="return checkUser()">
    <table align="center" >
        <tr>
            <td>用户名:</td><td><input type="text" name="userName" id="userid" /></td>
        </tr>
        <tr>
            <td>密码:</td><td><input type="password" name="password" id="userpassid" /></td>
        <tr/>
        <tr>
            <td colspan="2",align="center">
                <input type="submit" value="登录" id="check" />
                <input type="reset" value="重置" />
            </td>
        </tr>
    </table>
</form>
</body>
</html>

119.WEB-iNF下 jsp下的main.jsp

<%--
  Created by IntelliJ IDEA.
  User: wzw324
  Date: 2020/12/9
  Time: 15:33
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>你好</title>
</head>
<body>
${user.userName},当前积分为${user.credits};
</body>
</html>

12.resources下的 smart-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    <!--扫描类包,将标注为注解的类自动转化为Bean,同时完成Bean的注入-->
    <context:component-scan base-package="com.smart.dao"/>
    <context:component-scan base-package="com.smart.service"/>
    <!--对数据库的配置-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" primary="true">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <!--mysql现在是需要指定时区的-->
        <property name="url" value="jdbc:mysql://localhost:3306/sampledb?serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="admin"/>
    </bean>
    <!--引入jdbc配置文件-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <aop:config proxy-target-class="true">
        <aop:pointcut id="serviceMethod" expression="(execution(* com.smart.service..*(..))) and
        (@annotation(org.springframework.transaction.annotation.Transactional))" />
        <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
</beans>

13.resources下的smart-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!--先扫描-->
    <context:component-scan base-package="com.smart.web"/>
    <!--配置视图解析器,将ModelAndView及字符串解析为具体页面-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

最后是web.xml
要注意的是,这里的web.xml最好还是删除重新新建一个xml config的。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:smart-context.xml</param-value>
        <!--这里默认是/WEB-INF/applicationContext.xml.classpath关键字特指类路径下加载,多个配置文件可用逗号或空格分隔-->
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>smart</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:smart-servlet.xml</param-value>
            <!-- 默认是/WEB-INF/[servlet名字]-servlet.xml -->
        </init-param>
        <load-on-startup>1</load-on-startup>
        <!--启动优先级-->
    </servlet>
    <servlet-mapping>
        <servlet-name>smart</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
</web-app>

最后的程序样式差不多是这样
在这里插入图片描述
然后按照代码,需要在自己的mysql创建一个对应的数据库
(ps这里数据库的登录密码需要和smart-context里的dataSource 配置一样,主要是端口和账号密码)
首先可以通过
在这里插入图片描述
测试连接一下
在这里插入图片描述
然后在命令行创建一个sampledb数据库
使用 create database sampledb;
然后show databases看一下
在这里插入图片描述

然后就要在数据库里新建一些表和属性了,这里建议使用Navicat哈哈哈
t_user表
在这里插入图片描述
t_login_log表
在这里插入图片描述

然后在t_user表中新建一个用户,方便查找
在这里插入图片描述
在Navicat里做好之后,都是可以在命令行查看的
查看表:
在这里插入图片描述
看表里面的属性
在这里插入图片描述
最后看看那个新建好的用户
在这里插入图片描述
现在就差最后一步,也就是配置Tomcat了
在这里插入图片描述
在这里插入图片描述

这个名字无关紧要的
在这里插入图片描述
(ps经过测试,要把这个给删了,不然他界面会一直在这边,并且要删了之后,可能需要重启电脑,反正我是又新建了一个tomcat)
在这里插入图片描述

运行结果:
在这里插入图片描述
但是之后的操作,出现了
在这里插入图片描述
网上看是需要把mysql-connector-java从6.0.6,改成5.1.6 ,这个报错就不存在了
在这里插入图片描述
继续展示
在这里插入图片描述
在这里插入图片描述

一 本课程是怎么样的一门课程(面介绍) 1 1 课程的背景 ERP是(Enterprise Resource Planning 企业资源计划系统)的概念 是美国GartnerGroup公司于1990年提出的 其确切定义是:MRPⅡ(企业制造资源计划)下一代的制造业系统和资源计划软件 ERP系统包括以下主要功能:供应链管理 销售与市场 分销 客户服务 财务管理 制造管理 库存管理 工厂与设备维护 人力资源 报表 制造执行系统 Manufacturing Executive System MES 工作流服务和企业信息系统等 此外 还包括金融投资管理 质量管理 运输管理 项目管理 法规与标准和过程控制等补充功能 1 2 课程内容简介 本课程将会以项目功能为驱动 以功能为载体依次从浅入深的讲解目前Java Web开发中使用的最新技术 课程中除了数据增删改查这种传统功能外 还涉及到权限设计 树形菜单 站内聊天 报表开发等实用的设计方法或技术实现 1 3 项目介绍 本课程使用的项目来自于价值80万的商业ERP 为了教学与学习的方便而做了一些简化 只保留了CRM与进销存模块的功能 ERP:企业资源计划 CRM:客户关系管理 进销存:采购(进) >入库(存) >销售(销)">一 本课程是怎么样的一门课程(面介绍) 1 1 课程的背景 ERP是(Enterprise Resource Planning 企业资源计划系统)的概念 是美国GartnerGroup公司于1990年提出的 其确切定义是:MRPⅡ(企业制造资源计划)下一代的制造 [更多]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值