ssm项目-商城管理系统

news2025/1/17 3:58:25

1 逆向工程设计

1.1 xml文件配置(generatorConfig.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
	<context id="testTables" targetRuntime="MyBatis3">
		<commentGenerator>
			<!-- 是否去除自动生成的注释 true:是 : false:否 -->
			<property name="suppressAllComments" value="true" />
		</commentGenerator>
		<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
		<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/xiaomissm?useSSL=false&amp;serverTimezone=UTC&amp;allowPublicKeyRetrieval=true" userId="root"
			password="123456">
		</jdbcConnection>
		<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 
			NUMERIC 类型解析为java.math.BigDecimal -->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>

		<!-- targetProject:生成PO类的位置 -->
		<javaModelGenerator targetPackage="com.bjpowernode.pojo"
			targetProject=".\src">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
			<!-- 从数据库返回的值被清理前后的空格 -->
			<property name="trimStrings" value="true" />
		</javaModelGenerator>
        <!-- targetProject:mapper映射文件生成的位置 -->
		<sqlMapGenerator targetPackage="com.bjpowernode.mapper"
			targetProject=".\src">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
		</sqlMapGenerator>
		<!-- targetPackage:mapper接口生成的位置 -->
		<javaClientGenerator type="XMLMAPPER"
			targetPackage="com.bjpowernode.mapper"
			targetProject=".\src">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
		</javaClientGenerator>
		<!-- 指定数据库表 -->
		<table schema="" tableName="admin"></table>
		<table schema="" tableName="product_info"></table>
		<table schema="" tableName="product_type"></table>
	</context>
</generatorConfiguration>

1.2 工具类

public class GeneratorSqlmap {
    public GeneratorSqlmap() {
    }

    public void generator() throws Exception {
        List<String> warnings = new ArrayList();
        boolean overwrite = true;
        File configFile = new File("generatorConfig.xml");
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate((ProgressCallback)null);
    }

    public static void main(String[] args) throws Exception {
        try {
            GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
            generatorSqlmap.generator();
        } catch (Exception var2) {
            var2.printStackTrace();
        }

    }
}

1.3 结果展示

在这里插入图片描述
在这里插入图片描述

2 配置文件的设置

首先先建立一个maven 项目
在这里插入图片描述
在这里插入图片描述

2.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zcl</groupId>
    <artifactId>mimissm</artifactId>
    <version>1.0</version>
    <packaging>war</packaging>
    <!-- 集中定义依赖版本号 -->
    <properties>
        <junit.version>4.12</junit.version>
        <spring.version>5.3.9</spring.version>
        <mybatis.version>3.5.1</mybatis.version>
        <mybatis.spring.version>1.3.1</mybatis.spring.version>
        <mybatis.paginator.version>1.2.15</mybatis.paginator.version>
        <mysql.version>8.0.22</mysql.version>
        <slf4j.version>1.6.4</slf4j.version>
        <druid.version>1.1.12</druid.version>
        <pagehelper.version>5.1.2</pagehelper.version>
        <jstl.version>1.2</jstl.version>
        <servlet-api.version>3.0.1</servlet-api.version>
        <jsp-api.version>2.0</jsp-api.version>
        <jackson.version>2.9.6</jackson.version>
    </properties>
    <dependencies>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>${mybatis.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.miemiedev</groupId>
            <artifactId>mybatis-paginator</artifactId>
            <version>${mybatis.paginator.version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>${pagehelper.version}</version>
        </dependency>
        <!-- MySql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <!-- 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>

        <!-- junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>


        <!-- JSP相关 -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <scope>provided</scope>
            <version>${jsp-api.version}</version>
        </dependency>
        <!-- Jackson Json处理工具包 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20140107</version>
        </dependency>
        <!--文件异步上传-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

        <!--log4j 日志文件-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.2</version>
        </dependency>
    </dependencies>

    <!-- 插件配置 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
        <!--识别所有的配置文件-->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>

2.2 数据库连接配置文件

2.2.1 jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/zclshop?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
jdbc.username=root
jdbc.password=123456

2.2.2 mybatisConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--    分页插件的配置-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
    </plugins>
</configuration>

2.2.3 applicationContext_dao.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.xsd
                           http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd">
    <!--读取jdbc.properties-->
      <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--    创建数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--    创建SqlSessionFactoryBean-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--    配置数据源-->
    <property name="dataSource" ref="dataSource"/>
<!--    配置Mybatis的核心配置文件-->
        <property name="configLocation" value="classpath:mybatisConfig.xml"/>
<!--    配置实体类-->
        <property name="typeAliasesPackage" value="com.zcl.pojo"/>
    </bean>
    <!--    创建mapper文件扫描-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.zcl.mapper"/>
    </bean>
</beans>

2.2 事务配置文件

<?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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--<import resource="classpath:applicationContext_dao.xml"></import>-->
<!--    设置业务逻辑层的包扫描器,目的是在指定的路径下,使用@Service注解的类,Spring负责创建对象,并添加依赖-->
<context:component-scan base-package="com.zcl.service"></context:component-scan>
<!--    设置事物管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

<!--    添加事务的切面-->
    <tx:advice id="myadvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*select*" read-only="true"/>
            <tx:method name="*find*" read-only="true"/>
            <tx:method name="*get*" read-only="true"/>
            <tx:method name="*search*" read-only="true"/>
            <tx:method name="*insert*" propagation="REQUIRED"/>
            <tx:method name="*save*" propagation="REQUIRED"/>
            <tx:method name="*add*" propagation="REQUIRED"/>
            <tx:method name="*delete*" propagation="REQUIRED"/>
            <tx:method name="*remove*" propagation="REQUIRED"/>
            <tx:method name="*clear*" propagation="REQUIRED"/>
            <tx:method name="*update*" propagation="REQUIRED"/>
            <tx:method name="*modify*" propagation="REQUIRED"/>
            <tx:method name="*change*" propagation="REQUIRED"/>
            <tx:method name="*set*" propagation="REQUIRED"/>
            <tx:method name="*" propagation="SUPPORTS"/>
        </tx:attributes>
    </tx:advice>

<!--    完成切面和切入点的织入-->
    <aop:config>
        <aop:pointcut id="mypointcut" expression="execution(* com.zcl.service.*.*(..))"/>
        <aop:advisor advice-ref="myadvice" pointcut-ref="mypointcut"></aop:advisor>
    </aop:config>
</beans>

2.3 springmvc.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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!--    设置包扫描器-->
    <context:component-scan base-package="com.zcl.controller"/>

<!--    设置视图解析器 /admin/  main  .jsp-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

<!--    设置文件上传核心组件-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    </bean>

<!--    设置注解驱动-->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

2.4 前端控制器:web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--字符编码过滤器-->
    <filter>
        <filter-name>encode</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encode</filter-name>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>
    <!--注册springmvc框架-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--    拦截配置:拦截以.action 结尾的请求-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--            <url-pattern>*.action</url-pattern>-->
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
    <!--spring框架注册-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext_*.xml</param-value>
    </context-param>
    <!--    自动跳转到登录界面-->
    <welcome-file-list>
        <welcome-file>/WEB-INF/pages/admin/login.jsp</welcome-file>
    </welcome-file-list>
</web-app>

2.5 工具类

FileNameUtil.java

package com.zcl.utils;

import java.util.UUID;

public class FileNameUtil {
	//根据UUID生成文件名
	public static String getUUIDFileName() {
		UUID uuid = UUID.randomUUID();
		return uuid.toString().replace("-", "");
	}
	//从请求头中提取文件名和类型
	public static String getRealFileName(String context) {
		// Content-Disposition: form-data; name="myfile"; filename="a_left.jpg"
		int index = context.lastIndexOf("=");
		String filename = context.substring(index + 2, context.length() - 1);
		return filename;
	}
	//根据给定的文件名和后缀截取文件名
	public static String getFileType(String fileName){
		//9527s.jpg
		int index = fileName.lastIndexOf(".");
		return fileName.substring(index);
	}
}

MD5Util.java

package com.zcl.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Util {
    /**
     * 1.MD5(message-digest algorithm 5)信息摘要算法,
     *   它的长度一般是32位的16进制数字符串(如81dc9bdb52d04dc20036dbd8313ed055)
     * 2.由于系统密码明文存储容易被黑客盗取
     * 3.应用:注册时,将密码进行md5加密,存到数据库中,防止可以看到数据库数据的人恶意篡改。
     *       登录时,将密码进行md5加密,与存储在数据库中加密过的密码进行比对
     * 4.md5不可逆,即没有对应的算法,从产生的md5值逆向得到原始数据。
     *   但是可以使用暴力破解,这里的破解并非把摘要还原成原始数据,如暴力枚举法。
     *
     */
    public final static String getMD5(String str){
        try {
            MessageDigest md = MessageDigest.getInstance("SHA");//创建具有指定算法名称的摘要
            md.update(str.getBytes());                    //使用指定的字节数组更新摘要
            byte mdBytes[] = md.digest();                 //进行哈希计算并返回一个字节数组

            String hash = "";
            for(int i= 0;i<mdBytes.length;i++){           //循环字节数组
                int temp;
                if(mdBytes[i]<0)                          //如果有小于0的字节,则转换为正数
                    temp =256+mdBytes[i];
                else
                    temp=mdBytes[i];
                if(temp<16)
                    hash+= "0";
                hash+=Integer.toString(temp,16);         //将字节转换为16进制后,转换为字符串
            }
            return hash;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
}

3 登录注册模块设计

3.1 登录login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css" />
		<link rel="stylesheet" href="${pageContext.request.contextPath}/css/login.css" />
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.js"></script>
		<title></title>
		
	</head>

	<body>
		<div id="login">
			<div id="top">
				<img src="${pageContext.request.contextPath}/images/cloud.jpg" /><span>LOGIN</span>
			</div>
			<div id="bottom">
				<form  action="${pageContext.request.contextPath}/admin/login.action" method="post">
					<table border="0px" id="table">
						<tr>
							<td class="td1">用户名:</td>
							<td><input type="text" value="admin" placeholder="Username" class="td2" name="name"></td>
						</tr>
						<tr>
							<td></td>
							<td><span id="nameerr"></span></td>
						</tr>
						<tr>
							<td class="td1">密码:</td>
							<td><input type="password"  value="123456" placeholder="Password" class="td2" name="pwd"></td>
						</tr>
						<tr>
							<td></td>
							<td><span id="pwderr"></span></td>
						</tr>
						<tr>
							<td></td>
							<td><input type="submit" value="登录" class="td3">
								<a href="${pageContext.request.contextPath}/regist.jsp"><input type="button" value="注册" class="td3	"></a>
							</td>
						</tr>
					</table>
				</form>
				${errmsg}
			</div>

		</div>
	</body>

</html>

3.2 service层

adminService.java

    //完成登录
    Admin login(String name,String pwd);

adminServiceImpl.java

 public Admin login(String name, String pwd) {
        //根据用户名查询
        //创建封装条件
        AdminExample adminExample = new AdminExample();
        //添加用户名a_name条件
        adminExample.createCriteria().andANameEqualTo(name);
        List<Admin> adminList = adminMapper.selectByExample(adminExample);
        if (adminList.size() > 0) {
            Admin admin = adminList.get(0);
            //进行密码比对,数据密码是用md5加密的
            String miPwd= MD5Util.getMD5(pwd);
            if(miPwd.equals(admin.getaPass())){
                return admin;
            }
        }
        return null;
    }

3.3 controller

adminAction.java


    @RequestMapping("/login.action")
    public String login(String name, String pwd, HttpServletRequest request){
        Admin admin=adminService.login(name,pwd);
        System.out.println(admin);
        if(admin!=null){
            //登录成功
            request.setAttribute("admin",admin);
            return "admin/main";
        }else{
            //登录失败
            request.setAttribute("errmsg","用户名或密码错误");
            return "admin/login";
        }
    }

4 商品模块设计

4.1 商品分页展示

4.1.1 分页查询类–PageInfo

在这里插入图片描述

这里面有三个属性:
pageNum:当前页码
pageSize:页面显示记录数
total:总记录

4.1.2 service层

ProductInfoService.java

    //分页功能实现
    PageInfo splitPage(int pageNum,int pageSize);

ProductInfoServiceImpl.java

    @Override
    public PageInfo splitPage(int pageNum, int pageSize) {
        //分页插件PageHelper工具类进行实现
        PageHelper.startPage(pageNum,pageSize);
        //进行PageInfo的数据封装
        //进行有条件的查询操作,创建ProductInfoExample对象
        ProductInfoExample example = new ProductInfoExample();
        //设置排序,按照id降序
        example.setOrderByClause("p_id desc");
        List<ProductInfo>list=productInfoMapper.selectByExample(example);
        PageInfo<ProductInfo> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }

4.1.3 controller层

    //分页显示商品
    @RequestMapping("/splitPage.action")
    public String viewGoodsByPage(HttpServletRequest request) {
        PageInfo info = null;
            //根据条件进行查询
            //得到第一页是数据
            info = productInfoService.splitPage(1, PAGE_SIZE);
        request.setAttribute("info", info);
        return "product/product";
    }

4.2 图片上传功能

4.2.1 ajaxfileupload.js 文件


jQuery.extend({

    createUploadIframe: function(id, uri)
	{
			//create frame
            var frameId = 'jUploadFrame' + id;
            
            if(window.ActiveXObject) {
                var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
                if(typeof uri== 'boolean'){
                    io.src = 'javascript:false';
                }
                else if(typeof uri== 'string'){
                    io.src = uri;
                }
            }
            else {
                var io = document.createElement('iframe');
                io.id = frameId;
                io.name = frameId;
            }
            io.style.position = 'absolute';
            io.style.top = '-1000px';
            io.style.left = '-1000px';

            document.body.appendChild(io);

            return io			
    },
    createUploadForm: function(id, fileElementId)
	{
		//create form	
		var formId = 'jUploadForm' + id;
		var fileId = 'jUploadFile' + id;
		var form = $('<form  action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');	
		var oldElement = $('#' + fileElementId);
		var newElement = $(oldElement).clone();
		$(oldElement).attr('id', fileId);
		$(oldElement).before(newElement);
		$(oldElement).appendTo(form);
		//set attributes
		$(form).css('position', 'absolute');
		$(form).css('top', '-1200px');
		$(form).css('left', '-1200px');
		$(form).appendTo('body');		
		return form;
    },

    ajaxFileUpload: function(s) {
        // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout		
        s = jQuery.extend({}, jQuery.ajaxSettings, s);
        var id = s.fileElementId;        
		var form = jQuery.createUploadForm(id, s.fileElementId);
		var io = jQuery.createUploadIframe(id, s.secureuri);
		var frameId = 'jUploadFrame' + id;
		var formId = 'jUploadForm' + id;		
        // Watch for a new set of requests
        if ( s.global && ! jQuery.active++ )
		{
			jQuery.event.trigger( "ajaxStart" );
		}            
        var requestDone = false;
        // Create the request object
        var xml = {}   
        if ( s.global )
            jQuery.event.trigger("ajaxSend", [xml, s]);
        // Wait for a response to come back
        var uploadCallback = function(isTimeout)
		{			
			var io = document.getElementById(frameId);
            try 
			{				
				if(io.contentWindow)
				{
					 xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
                	 xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
					 
				}else if(io.contentDocument)
				{
					 xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;
                	xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;
				}						
            }catch(e)
			{
				jQuery.handleError(s, xml, null, e);
			}
            if ( xml || isTimeout == "timeout") 
			{				
                requestDone = true;
                var status;
                try {
                    status = isTimeout != "timeout" ? "success" : "error";
                    // Make sure that the request was successful or notmodified
                    if ( status != "error" )
					{
                        // process the data (runs the xml through httpData regardless of callback)
                        var data = jQuery.uploadHttpData( xml, s.dataType );    
                        // If a local callback was specified, fire it and pass it the data
                        if ( s.success )
                            s.success( data, status );
    
                        // Fire the global callback
                        if( s.global )
                            jQuery.event.trigger( "ajaxSuccess", [xml, s] );
                    } else
                        jQuery.handleError(s, xml, status);
                } catch(e) 
				{
                    status = "error";
                    jQuery.handleError(s, xml, status, e);
                }

                // The request was completed
                if( s.global )
                    jQuery.event.trigger( "ajaxComplete", [xml, s] );

                // Handle the global AJAX counter
                if ( s.global && ! --jQuery.active )
                    jQuery.event.trigger( "ajaxStop" );

                // Process result
                if ( s.complete )
                    s.complete(xml, status);

                jQuery(io).unbind()

                setTimeout(function()
									{	try 
										{
											$(io).remove();
											$(form).remove();	
											
										} catch(e) 
										{
											jQuery.handleError(s, xml, null, e);
										}									

									}, 100)

                xml = null

            }
        }
        // Timeout checker
        if ( s.timeout > 0 ) 
		{
            setTimeout(function(){
                // Check to see if the request is still happening
                if( !requestDone ) uploadCallback( "timeout" );
            }, s.timeout);
        }
        try 
		{
           // var io = $('#' + frameId);
			var form = $('#' + formId);
			$(form).attr('action', s.url);
			$(form).attr('method', 'POST');
			$(form).attr('target', frameId);
            if(form.encoding)
			{
                form.encoding = 'multipart/form-data';				
            }
            else
			{				
                form.enctype = 'multipart/form-data';
            }			
            $(form).submit();

        } catch(e) 
		{			
            jQuery.handleError(s, xml, null, e);
        }
        if(window.attachEvent){
            document.getElementById(frameId).attachEvent('onload', uploadCallback);
        }
        else{
            document.getElementById(frameId).addEventListener('load', uploadCallback, false);
        } 		
        return {abort: function () {}};	

    },

    uploadHttpData: function( r, type ) {
        var data = !type;
        data = type == "xml" || data ? r.responseXML : r.responseText;
        // If the type is "script", eval it in global context
        if ( type == "script" )
            jQuery.globalEval( data );
        // Get the JavaScript object, if JSON is used.
        if ( type == "json" )
            eval( "data = " + data );
        // evaluate scripts within html
        if ( type == "html" )
            jQuery("<div>").html(data).evalScripts();
			//alert($('param', data).each(function(){alert($(this).attr('value'));}));
        return data;
    }
})


4.2.2 前端请求(jQuery引用ajaxfileupload.js)

 <script type="text/javascript">
        function fileChange(){
			$.ajaxFileUpload({
				url:"${pageContext.request.contextPath}/prod/ajaxImg.action",
				secureuri: false,//是否遵循安全协议
				fileElementId: 'pimage',
				dataType:"json",
				success:function(res){
					//创建一个图片标签
					var imgObj=$("<img>");
					//图片在服务器中的相对位置
					imgObj.attr("src","/mimissm/image_big/"+res.imgurl);
					imgObj.attr("width","100px");
					imgObj.attr("height","100px");
					//将图片追加到imgDiv
					$("#imgDiv").append(imgObj);
				},
				error: function (e)//服务器响应失败处理函数
				{
					alert(e.message);
				}

			})
        }
    </script>

4.2.3 springMVC

<!--    设置文件上传核心组件-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    </bean>

4.2.4 controller

    //异步ajax文件上传
    @ResponseBody
    @RequestMapping("/ajaxImg.action")
    public Object ajaxImg(MultipartFile pimage, HttpServletRequest request) {
        //提取生成文件名UUID+上传图片后缀
        saveFileName = FileNameUtil.getUUIDFileName() + FileNameUtil.getFileType(pimage.getOriginalFilename());
        //得到项目中图片存储的路径
        String path = request.getServletContext().getRealPath("/image_big");
        //转存
        try {
            pimage.transferTo(new File(path + File.separator + saveFileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
        //返回客户端JSON对象,封装图片路径
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("imgurl", saveFileName);
        return jsonObject.toString();
    }

4.2 商品新增

4.2.1 service

ProductInfoService.java

    //添加功能
    int save(ProductInfo info);

ProductInfoServiceImpl.java

    //添加功能
    @Override
    public int save(ProductInfo info) {
        return productInfoMapper.insert(info);
    }

4.2.2 controller

    @RequestMapping("/save.action")
    public String save(ProductInfo info, HttpServletRequest request) {
        info.setpDate(new Date());
        info.setpImage(saveFileName);
        //info有表单提交上来的五个数据,有异步Ajax上来的图片名称数据,还有上架时间数据
        int num = -1;
        try {
            num = productInfoService.save(info);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (num > 0) {
            //增加成功
            request.setAttribute("msg", "增加成功");
        } else {
            //增加失败
            request.setAttribute("msg", "增加失败");
        }
        //清空saveFileName
        saveFileName = "";
        //增加成功后应该重新访问数据库,跳转到分页查询的action
        return "forward:/prod/splitPage.action";
    }

4.3 商品更新

4.3.1 商品的回显

4.3.1.1 service

ProductInfo.java

    //按主键id查询
    ProductInfo getById(int pid);

ProductInfoImpl.java

    @Override
    public ProductInfo getById(int pid) {
        return productInfoMapper.selectByPrimaryKey(pid);
    }

4.3.1.2 controller

    @RequestMapping("/one.action")
    public String one(int pid, ProductInfoVo vo, Model model, HttpSession session) {
        ProductInfo info = productInfoService.getById(pid);
        model.addAttribute("prod", info);
        //将多条件及页码放到session中
        session.setAttribute("prodvo", vo);
        return "product/updateProduct";
    }

4.3.2 商品的更新

4.3.2.1 service

ProductInfo.java

    //更新商品
    int update(ProductInfo info);

ProductInfoImpl.java

    @Override
    public int update(ProductInfo info) {
        return productInfoMapper.updateByPrimaryKey(info);
    }

4.3.2.2 controller


    @RequestMapping("/update.action")
    public String update(ProductInfo info, HttpServletRequest request) {
        //图片上传处理
        if (!saveFileName.equals("")) {
            info.setpImage(saveFileName);
        }
        //完成更新操作
        int num = -1;
        try {
            num = productInfoService.update(info);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (num > 0) {
            //更新成功
            request.setAttribute("msg", "更新成功");
        } else {
            //更新失败
            request.setAttribute("msg", "更新失败");
        }
        //更新savaFileName
        saveFileName = "";
        return "forward:/prod/splitPage.action";
    }

4.4 商品删除

4.4.1 service

ProductInfo.java

    //单个商品删除
    int delete(int pid);

ProductInfoImpl.java

    @Override
    public int delete(int pid) {
        return productInfoMapper.deleteByPrimaryKey(pid);
    }

4.4.2 controller

    @RequestMapping("/delete.action")
    public String delete(int pid, HttpServletRequest request) {
        int num = -1;
        try {
            num = productInfoService.delete(pid);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (num > 0) {
            //删除成功
            request.setAttribute("msg", "删除成功");
        } else {
            //删除失败
            request.setAttribute("msg", "删除失败");
        }
        //跳转到分页
        return "forward:/prod/deleteAjaxSplit.action";
    }

4.5 批量删除

4.5.1 dao

ProductInfoMapper.java

    int deleteBath(String []ids);

ProductInfoMapper.xml

    <!--  批量删除-->
    <delete id="deleteBath">
        delete from product_info where p_id in
        <foreach collection="array" item="pid" separator="," open="(" close=")">
            #{pid}
        </foreach>

    </delete>

4.5.2 service

ProductInfo.java

    //批量删除
    int deleteBatch(String[] ids);

ProductInfoImpl.java

    @Override
    public int deleteBatch(String[] ids) {
        return productInfoMapper.deleteBath(ids);
    }

4.5.3 controller

    //批量删除商品
    @RequestMapping("/deleteBatch.action")
    public String deleteBatch(String pids, HttpServletRequest request) {
        //将上传上来的字符串截开,形成商品id的字符数组
        String[] ps = pids.split(",");
        int num = productInfoService.deleteBatch(ps);
        try {
            if (num > 0) {
                request.setAttribute("msg", "批量删除成功!");
            } else {
                request.setAttribute("msg", "批量删除失败!");
            }
        } catch (Exception e) {
            request.setAttribute("msg", "商品不可删除!");
        }
        return "forward:/prod/deleteAjaxSplit.action";
    }

4.6 多条件查询

4.6.1 封装条件查询类:ProductInfoVo.java

package com.zcl.pojo.vo;

/**
 * @author ZCL
 * @Description
 * @date 2022/12/14 15:00
 */

public class ProductInfoVo {
    //商品名称
    private String pname;
    //商品类型
    private Integer typeid;
    //最低价格
    private Integer lprice;
    //最高价格
    private Integer hprice;
    //设置页码
    private Integer page=1;

    public ProductInfoVo(String pname, Integer typeid, Integer lprice, Integer hprice, Integer page) {
        this.pname = pname;
        this.typeid = typeid;
        this.lprice = lprice;
        this.hprice = hprice;
        this.page = page;
    }

    public ProductInfoVo() {
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public Integer getTypeid() {
        return typeid;
    }

    public void setTypeid(Integer typeid) {
        this.typeid = typeid;
    }

    public Integer getLprice() {
        return lprice;
    }

    public void setLprice(Integer lprice) {
        this.lprice = lprice;
    }

    public Integer getHprice() {
        return hprice;
    }

    public void setHprice(Integer hprice) {
        this.hprice = hprice;
    }

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    @Override
    public String toString() {
        return "ProductInfoVo{" +
                "pname='" + pname + '\'' +
                ", typeid=" + typeid +
                ", lprice=" + lprice +
                ", hprice=" + hprice +
                ", page=" + page +
                '}';
    }
}

4.6.2 dao

ProductInfoMapper.java

    //多条件查询
    List<ProductInfo> selectCondition(ProductInfoVo vo);

ProductInfoMapper.xml

    <!--  多条件查询-->
    <select id="selectCondition" resultMap="BaseResultMap" parameterType="com.zcl.pojo.vo.ProductInfoVo">
        select
        <include refid="Base_Column_List"></include>
        from product_info
        <where>
            <if test="pname !=null and pname != '' ">
                and p_name like '%${pname}%'
            </if>
            <if test="typeid !=null and typeid != '' ">
                and type_id like '%${typeid}%'
            </if>
            <if test="(lprice!=null and lprice!='') and  (hprice==null or hprice=='')">
                and p_price &gt;= #{lprice}
            </if>
            <if test="(lprice==null or lprice=='') and  (hprice!=null and hprice!='')">
                and p_price &lt;= #{hprice}
            </if>
            <if test="(lprice!=null and lprice!='') and  (hprice!=null and hprice!='')">
                and p_price between #{lprice} and #{hprice}
            </if>
        </where>
    </select>

4.6.3 service

ProductInfo.java

    //多条件查询
    List<ProductInfo> selectCondition(ProductInfoVo vo);

ProductInfoImpl.java

    @Override
    public List<ProductInfo> selectCondition(ProductInfoVo vo) {
        return productInfoMapper.selectCondition(vo);
    }

4.6.4 controller

    @ResponseBody
    @RequestMapping("/condition.action")
    public void searchCondition(ProductInfoVo vo, HttpSession session) {
        List<ProductInfo> list = productInfoService.selectCondition(vo);
        session.setAttribute("list", list);
    }

4.7 模块优化

4.7.1 多条件分页查询

ProductInfoService.java

    //多条件查询分页
    PageInfo splitPageVo(ProductInfoVo vo,int pageSize);

ProductInfoServiceImpl.java

    @Override
    public PageInfo splitPageVo(ProductInfoVo vo, int pageSize) {
        //设置PageHelper
        PageHelper.startPage(vo.getPage(),pageSize);
        List<ProductInfo> list = productInfoMapper.selectCondition(vo);
        return new PageInfo<>(list);
    }

4.7.2 分页查询优化

    //分页显示商品
    @RequestMapping("/splitPage.action")
    public String viewGoodsByPage(HttpServletRequest request) {
        PageInfo info = null;
        Object vo = request.getSession().getAttribute("prodvo");
        if (vo != null) {
            //根据条件进行查询
            info = productInfoService.splitPageVo((ProductInfoVo) vo, PAGE_SIZE);
            request.getSession().removeAttribute("prodvo");
        } else {
            //得到第一页是数据
            info = productInfoService.splitPage(1, PAGE_SIZE);
        }
        request.setAttribute("info", info);
        return "product/product";
    }

4.7.3 删除优化

    @RequestMapping("/delete.action")
    public String delete(int pid,ProductInfoVo vo, HttpServletRequest request) {
        int num = -1;
        try {
            num = productInfoService.delete(pid);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (num > 0) {
            //删除成功
            request.setAttribute("msg", "删除成功");
            request.getSession().setAttribute("deleteProdvo",vo);
        } else {
            //删除失败
            request.setAttribute("msg", "删除失败");
        }
        //跳转到分页
        return "forward:/prod/deleteAjaxSplit.action";
    }

    @ResponseBody
    @RequestMapping(value = "/deleteAjaxSplit.action", produces = "text/html;charset=UTF-8")
    public Object deleteAjaxSplit(HttpServletRequest request) {
        PageInfo info=null;
        Object vo=request.getSession().getAttribute("deleteProdvo");
        if (vo!=null){
            info=productInfoService.splitPageVo((ProductInfoVo) vo,PAGE_SIZE);
        }else{
            //显示第一页数据
            info = productInfoService.splitPage(1, PAGE_SIZE);
        }
        request.getSession().setAttribute("info", info);
        return request.getAttribute("msg");
    }

4.7.4 更新优化

    @RequestMapping("/one.action")
    public String one(int pid, ProductInfoVo vo, Model model, HttpSession session) {
        ProductInfo info = productInfoService.getById(pid);
        model.addAttribute("prod", info);
        //将多条件及页码放到session中
        session.setAttribute("prodvo", vo);
        return "product/updateProduct";
    }

    @RequestMapping("/update.action")
    public String update(ProductInfo info, HttpServletRequest request) {
        //图片上传处理
        if (!saveFileName.equals("")) {
            info.setpImage(saveFileName);
        }
        //完成更新操作
        int num = -1;
        try {
            num = productInfoService.update(info);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (num > 0) {
            //更新成功
            request.setAttribute("msg", "更新成功");
        } else {
            //更新失败
            request.setAttribute("msg", "更新失败");
        }
        //更新savaFileName
        saveFileName = "";
        return "forward:/prod/splitPage.action";
    }

4.7.5 翻页优化

    //ajax翻页处理
    @ResponseBody
    @RequestMapping("/ajaxSplit.action")
    public void ajaxSplit(ProductInfoVo vo, HttpSession session) {
        PageInfo info = productInfoService.splitPageVo(vo, PAGE_SIZE);
        session.setAttribute("info", info);
    }

4.8 前端页面开发

main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
		 pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css" />
		<link rel="stylesheet" href="${pageContext.request.contextPath}/css/index.css" />
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.js"></script>
		<title></title>
		<%--<link href="${pageContext.request.contextPath}/css/main.css" rel="stylesheet" >--%>
		<style type="text/css">
		</style>
	</head>

	<body>
		<!--整体部分-->
		<div id="all">
			<!--上部分-->
			<div id="top">
				<div id="top1">
					<span>商品管理系统</span>
				</div>
				<div id="top2"></div>
				<div id="top3">
					<span>欢迎您,${admin.aName}</span>
				</div>
			</div>
			<!--下部分-->
			<div id="bottom">
				<!--下部分左边-->
				<div id="bleft">
					<div id="ltop">
						<div id="lts">
							<img src="${pageContext.request.contextPath}/images/logo.jpg" /><br />
							<p style="text-align: center;">随机访客</p>
						</div>
					</div>
					<div id="lbottom">
						<ul>
							<a href="${pageContext.request.contextPath}/prod/splitPage.action" target="myright" >
								<li class="two"><span class="glyphicon glyphicon-book" style="color: white;"></span>&nbsp;&nbsp;&nbsp;&nbsp;商品管理&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="glyphicon glyphicon-play" style="color: white;"></span> </li>
							</a>
							<a href="${pageContext.request.contextPath}/WEB-INF/pages/admin/err.jsp" target="myright">
								<li class="one"><span class="glyphicon glyphicon-sort" style="color: white;"></span>&nbsp;&nbsp;&nbsp;&nbsp;订单管理&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="glyphicon glyphicon-play" style="color: white;"></span> </li>
							</a>
							<a href="${pageContext.request.contextPath}/WEB-INF/pages/admin/err.jsp" target="myright">
								<li class="one"><span class="glyphicon glyphicon-user" style="color: white;"></span>&nbsp;&nbsp;&nbsp;&nbsp;用户管理&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="glyphicon glyphicon-play" style="color: white;"></span> </li>
							</a>
							<a href="${pageContext.request.contextPath}/WEB-INF/pages/admin/err.jsp" target="myright">
								<li class="one"><span class="glyphicon glyphicon-bullhorn" style="color: white"></span>&nbsp;&nbsp;&nbsp;&nbsp;通知公告&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="glyphicon glyphicon-play" style="color: white;"></span> </li>
							</a>
						</ul>
					</div>
				</div>
				<!--下部分右边-->
				<div id="bright">
					<iframe frameborder="0" scrolling="yes" name="myright" width="1235px" height="700px" ></iframe>
				</div>
			</div>
		</div>
	</body>

</html>

product.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@page import="java.util.*" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">

    <script type="text/javascript">
        if ("${msg}" != "") {
            alert("${msg}");
        }
    </script>

    <c:remove var="msg"></c:remove>

    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css"/>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/bright.css"/>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/addBook.css"/>
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.js"></script>
    <title></title>
</head>
<script type="text/javascript">
    //全选复选框功能实现
    function allClick() {
        //获得当前点击后全选按钮的状态
        var flag = $("#all").prop("checked");
        //将此状态赋值给下面五个复选框
        $("input[name='ck']").each(function () {
            this.checked = flag;
        });
    }

    //单个复选框点击改变全选复选框功能实现
    function ckClick() {
        //得到下面五个复选框的个数
        var fiveLength = $("input[name='ck']").length;
        //得到下面五个复选框被选中的个数
        var checkedLength = $("input[name='ck']:checked").length;

        //进行对比,改变全选复选框的状态
        if (fiveLength == checkedLength) {
            $("#all").prop("checked", true);
        } else {
            $("#all").prop("checked", false);
        }
    }
</script>
<body>
<div id="brall">
    <div id="nav">
        <p>商品管理>商品列表</p>
    </div>
    <div id="condition" style="text-align: center">
        <form id="myform">
            商品名称:<input name="pname" id="pname">&nbsp;&nbsp;&nbsp;
            商品类型:<select name="typeid" id="typeid">
            <option value="0">请选择</option>
            <c:forEach items="${typeList}" var="pt">
                <option value="${pt.typeId}">${pt.typeName}</option>
            </c:forEach>
        </select>&nbsp;&nbsp;&nbsp;
            价格:<input name="lprice" id="lprice">-<input name="hprice" id="hprice">
            <input type="button" value="查询" onclick="condition()">
        </form>
    </div>
    <br>
    <div id="table">

        <c:choose>
            <c:when test="${info.list.size()!=0}">

                <div id="top">
                    <input type="checkbox" id="all" onclick="allClick()" style="margin-left: 50px">&nbsp;&nbsp;全选
                    <a onclick="toAdd(${info.pageNum})">

                        <input type="button" class="btn btn-warning" id="btn1" value="新增商品">
                    </a>
                    <input type="button" class="btn btn-warning" id="btn1" value="批量删除" onclick="deleteBatch()">
                </div>
                <!--显示分页后的商品-->
                <div id="middle">
                    <table class="table table-bordered table-striped">
                        <tr>
                            <th></th>
                            <th>商品名</th>
                            <th>商品介绍</th>
                            <th>定价(元)</th>
                            <th>商品图片</th>
                            <th>商品数量</th>
                            <th>操作</th>
                        </tr>
                        <c:forEach items="${info.list}" var="p">
                            .
                            <tr>
                                <td valign="center" align="center">
                                    <input type="checkbox" name="ck" id="ck" value="${p.pId}" onclick="ckClick()"></td>
                                <td>${p.pName}</td>
                                <td>${p.pContent}</td>
                                <td>${p.pPrice}</td>
                                <td>
                                    <c:if test="${p.pImage!='' and p.pImage!=null}">
                                        <img width="55px" height="45px"
                                             src="${pageContext.request.contextPath}/image_big/${p.pImage}">
                                    </c:if>
                                </td>

                                <td>${p.pNumber}</td>
                                    <%--<td><a href="${pageContext.request.contextPath}/admin/product?flag=delete&pid=${p.pId}" onclick="return confirm('确定删除吗?')">删除</a>--%>
                                    <%--&nbsp;&nbsp;&nbsp;<a href="${pageContext.request.contextPath}/admin/product?flag=one&pid=${p.pId}">修改</a></td>--%>
                                <td>
                                    <button type="button" class="btn btn-info "
                                            onclick="one(${p.pId},${info.pageNum})">编辑
                                    </button>
                                    <button type="button" class="btn btn-warning" id="mydel"
                                            onclick="del(${p.pId},${info.pageNum})">删除
                                    </button>
                                </td>
                            </tr>
                        </c:forEach>
                    </table>
                    <!--分页栏-->
                    <div id="bottom">
                        <div>
                            <nav aria-label="..." style="text-align:center;">
                                <ul class="pagination">
                                    <li>
                                            <%--                                        <a href="${pageContext.request.contextPath}/prod/split.action?page=${info.prePage}" aria-label="Previous">--%>
                                        <a href="javascript:ajaxsplit(${info.prePage})" aria-label="Previous">

                                            <span aria-hidden="true">«</span></a>
                                    </li>
                                    <c:forEach begin="1" end="${info.pages}" var="i">
                                        <c:if test="${info.pageNum==i}">
                                            <li>
                                                    <%--                                                <a href="${pageContext.request.contextPath}/prod/split.action?page=${i}" style="background-color: grey">${i}</a>--%>
                                                <a href="javascript:ajaxsplit(${i})"
                                                   style="background-color: grey">${i}</a>
                                            </li>
                                        </c:if>
                                        <c:if test="${info.pageNum!=i}">
                                            <li>
                                                    <%--                                                <a href="${pageContext.request.contextPath}/prod/split.action?page=${i}">${i}</a>--%>
                                                <a href="javascript:ajaxsplit(${i})">${i}</a>
                                            </li>
                                        </c:if>
                                    </c:forEach>
                                    <li>
                                            <%--  <a href="${pageContext.request.contextPath}/prod/split.action?page=1" aria-label="Next">--%>
                                        <a href="javascript:ajaxsplit(${info.nextPage})" aria-label="Next">
                                            <span aria-hidden="true">»</span></a>
                                    </li>
                                    <li style=" margin-left:150px;color: #0e90d2;height: 35px; line-height: 35px;">总共&nbsp;&nbsp;&nbsp;<font
                                            style="color:orange;">${info.pages}</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                                        <c:if test="${info.pageNum!=0}">
                                            当前&nbsp;&nbsp;&nbsp;<font
                                            style="color:orange;">${info.pageNum}</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                                        </c:if>
                                        <c:if test="${info.pageNum==0}">
                                            当前&nbsp;&nbsp;&nbsp;<font
                                            style="color:orange;">1</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                                        </c:if>
                                    </li>
                                </ul>
                            </nav>
                        </div>
                    </div>
                </div>
            </c:when>
            <c:otherwise>
                <div>
                    <h2 style="width:1200px; text-align: center;color: orangered;margin-top: 100px">暂时没有符合条件的商品!</h2>
                </div>
            </c:otherwise>
        </c:choose>
    </div>
</div>
</body>

<script type="text/javascript">
    function toAdd(page) {
        //取出查询条件
        var pname = $("#pname").val();
        var typeid = $("#typeid").val();
        var lprice = $("#lprice").val();
        var hprice = $("#hprice").val();
        //向服务器提交请求,传递商品id
        var str = "?page=" + page + "&pname=" + pname + "&typeid=" + typeid + "&lprice=" + lprice + "&hprice=" + hprice;
        location.href = "${pageContext.request.contextPath}/prod/toAdd.action" + str;
    }
    function mysubmit() {
        $("#myform").submit();
    }

    //批量删除
    function deleteBatch() {
        //得到所有选中复选框的对象,根据其长度判断是否有选中商品
        var cks = $("input[name='ck']:checked");  //1,4,5
        //如果有选中的商品,获取其value的值,进行字符串拼接
        if (cks.length == 0) {
            alert("请选择将要删除的商品");
        } else {
            var str = "";
            var id = "";
            if (confirm("你确定要删除" + cks.length + "条商品")) {
                // alert("可以进行删除!")
                //进行提交商品id的字符串的拼接
                $.each(cks, function () {
                    pid = $(this).val(); //每一个被选中商品的id
                    //进行非空判断,避免出错
                    if (pid != null) {
                        str += pid + ",";
                    }
                });
                //发送ajax请求,进行批量删除的提交
                $.ajax({
                    url: "${pageContext.request.contextPath}/prod/deleteBatch.action",
                    data: {"pids": str},
                    type: "post",
                    dataType: "text",
                    success: function (msg) {
                        alert(msg);//批量删除提示信息
                        //将页面上显示商品数据的容器重新加载
                        $("#table").load("http://localhost:8080/mimissm/prod/toProduct.action #table")
                    }
                })
            }
        }

    }

    //单个删除
    function del(pid, page) {
        //弹框提示
        if (confirm("你确定删除吗?")) {
            //取出查询条件
            var pname = $("#pname").val();
            var typeid = $("#typeid").val();
            var lprice = $("#lprice").val();
            var hprice = $("#hprice").val();
            //ajax请求
            $.ajax({
                url: "${pageContext.request.contextPath}/prod/delete.action",
                data: {"pid": pid, "page": page, "pname": pname, "typeid": typeid, "lprice": lprice, "hprice": hprice},
                type: "post",
                dataType: "text",
                success: function (msg) {
                    alert(msg);
                    $("#table").load("http://localhost:8080/mimissm/prod/toProduct.action #table")
                }
            })
        }
    }

    function one(pid, page) {
        //取出查询条件
        var pname = $("#pname").val();
        var typeid = $("#typeid").val();
        var lprice = $("#lprice").val();
        var hprice = $("#hprice").val();
        //向服务器提交请求,传递商品id
        var str = "?pid=" + pid + "&page=" + page + "&pname=" + pname + "&typeid=" + typeid + "&lprice=" + lprice + "&hprice=" + hprice;
        location.href = "${pageContext.request.contextPath}/prod/one.action" + str;
    }
</script>
<!--分页的AJAX实现-->
<script type="text/javascript">
    function ajaxsplit(page) {
        //取出查询条件
        var pname = $("#pname").val();
        var typeid = $("#typeid").val();
        var lprice = $("#lprice").val();
        var hprice = $("#hprice").val();
        //向服务发出ajax请求,请示page页中的所有数据,在当前页面上局部刷新显示
        $.ajax({
            url: "${pageContext.request.contextPath}/prod/ajaxSplit.action",
            data: {"page": page, "pname": pname, "typeid": typeid, "lprice": lprice, "hprice": hprice},
            type: "post",
            success: function () {
                //重新加载显示分页数据
                $("#table").load("http://localhost:8080/mimissm/prod/toProduct.action #table")
            }
        });

    }

    function condition() {
        //取出查询条件
        var pname = $("#pname").val();
        var typeid = $("#typeid").val();
        var lprice = $("#lprice").val();
        var hprice = $("#hprice").val();
        $.ajax({
            type: "post",
            url: "${pageContext.request.contextPath}/prod/ajaxSplit.action",
            data: {"pname": pname, "typeid": typeid, "lprice": lprice, "hprice": hprice},
            success: function () {
                //重新加载显示分页数据
                $("#table").load("http://localhost:8080/mimissm/prod/toProduct.action #table")
            }
        })
    }
</script>

</html>

addProduct.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css" />
		<link rel="stylesheet" href="${pageContext.request.contextPath}/css/addBook.css" />
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.js"></script>
        <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery.js"></script>
        <script type="text/javascript" src="${pageContext.request.contextPath }/js/ajaxfileupload.js"></script>
	</head>
    <script type="text/javascript">
        function fileChange(){
			$.ajaxFileUpload({
				url:"${pageContext.request.contextPath}/prod/ajaxImg.action",
				secureuri: false,//是否遵循安全协议
				fileElementId: 'pimage',
				dataType:"json",
				success:function(res){
					//创建一个图片标签
					var imgObj=$("<img>");
					imgObj.attr("src","/mimissm/image_big/"+res.imgurl);
					imgObj.attr("width","100px");
					imgObj.attr("height","100px");
					//将图片追加到imgDiv
					$("#imgDiv").append(imgObj);
				},
				error: function (e)//服务器响应失败处理函数
				{
					alert(e.message);
				}

			})
        }
    </script>
	<body>
	<!--取出上一个页面上带来的page的值-->

		<div id="addAll">
			<div id="nav">
				<p>商品管理>新增商品</p>
			</div>

			<div id="table">
				<form  id="myform" action="${pageContext.request.contextPath}/prod/save.action">
					<table>
						<tr>
							<td class="one">商品名称</td>
							<td><input type="text" name="pName" class="two"></td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span id="pnameerr"></span></td>
						</tr>
						<tr>
							<td class="one">商品介绍</td>
							<td><input type="text" name="pContent" class="two"></td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span id="pcontenterr"></span></td>
						</tr>
						<tr>
							<td class="one">定价</td>
							<td><input type="number" name="pPrice" class="two"></td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span id="priceerr"></span></td>
						</tr>
						
						<tr>
							<td class="three">图片介绍</td>
                            <td> <br><div id="imgDiv" style="display:block; width: 40px; height: 50px;"></div><br><br><br><br>
                            <input type="file" id="pimage" name="pimage" onchange="fileChange()" >
                                <span id="imgName" ></span><br>

                            </td>
						</tr>
						<tr class="three">
							<td class="four"></td>
							<td><span></span></td>
						</tr>
						
						<tr>
							<td class="one">总数量</td>
							<td><input type="number" name="pNumber" class="two"></td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span id="numerr"></span></td>
						</tr>
						
						
						<tr>
							<td class="one">类别</td>
							<td>
								<select name="typeId" >
									<c:forEach items="${typeList}" var="type">
										<option value="${type.typeId}">${type.typeName}</option>
									</c:forEach>
								</select>
							</td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span></span></td>
						</tr>

						<tr>
							<td>
								<input type="submit" value="提交" class="btn btn-success">
							</td>
							<td>
								<input type="reset" value="取消" class="btn btn-default" onclick="myclose()">
								<script type="text/javascript">
									function myclose() {
										location.href = "${pageContext.request.contextPath}/prod/splitPage.action";
									}
								</script>
							</td>
						</tr>
					</table>
				</form>
			</div>
		</div>

	</body>

</html>

update.jsp

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

	<head>
		<meta charset="UTF-8">
		<title></title>
		<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.css" />
		<link rel="stylesheet" href="${pageContext.request.contextPath}/css/addBook.css" />
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
		<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.js"></script>
		<script type="text/javascript" src="${pageContext.request.contextPath }/js/ajaxfileupload.js"></script>
	</head>

	<body>
		<div id="addAll">
			<div id="nav">
				<p>商品管理>更新商品</p>
			</div>
			<script type="text/javascript">
				function fileChange(){//注意:此处不能使用jQuery中的change事件,因此仅触发一次,因此使用标签的:onchange属性
					$.ajaxFileUpload({
						url: '${pageContext.request.contextPath}/prod/ajaxImg.action',//用于文件上传的服务器端请求地址
						secureuri: false,//一般设置为false
						fileElementId: 'pimage',//文件上传控件的id属性  <input type="file" id="pimage" name="pimage" />
						dataType: 'json',//返回值类型 一般设置为json
						success: function(obj) //服务器成功响应处理函数
						{

							$("#imgDiv").empty();  //清空原有数据
							//创建img 标签对象
							var imgObj = $("<img>");
							//给img标签对象追加属性
							imgObj.attr("src","/mimissm/image_big/"+obj.imgurl);
							imgObj.attr("width","100px");
							imgObj.attr("height","100px");
							//将图片img标签追加到imgDiv末尾
							$("#imgDiv").append(imgObj);
							//将图片的名称(从服务端返回的JSON中取得)赋值给文件本框
							//$("#imgName").html(data.imgName);
						},
						error: function (e)//服务器响应失败处理函数
						{
							alert(e.message);
						}
					});
				}
			</script>
<script type="text/javascript">
	function myclose() {
		location.href = "${pageContext.request.contextPath}/prod/splitPage.action";
	}
</script>
			<div id="table">
				<form action="${pageContext.request.contextPath}/prod/update.action" enctype="multipart/form-data" method="post" id="myform">
					<input type="hidden" value="${prod.pId}" name="pId">
					<input type="hidden" value="${prod.pImage}" name="pImage">

					<table>
						<tr>
							<td class="one">商品名称</td>
							<td><input type="text" name="pName" class="two" value="${prod.pName}"></td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span id="pnameerr"></span></td>
						</tr>
						<tr>
							<td class="one">商品介绍</td>
							<td><input type="text" name="pContent" class="two" value="${prod.pContent}"></td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span id="pcontenterr"></span></td>
						</tr>
						<tr>
							<td class="one">定价</td>
							<td><input type="number" name="pPrice" class="two" value="${prod.pPrice}"></td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span id="priceerr"></span></td>
						</tr>
						
						<tr>
							<td class="one">图片介绍</td>
							<td> <br><div id="imgDiv" style="display:block; width: 40px; height: 50px;"><img src="/mimissm/image_big/${prod.pImage}" width="100px" height="100px" ></div><br><br><br><br>
								<input type="file" id="pimage" name="pimage" onchange="fileChange()">
								<span id="imgName"></span><br>

							</td>
						</tr>
						<tr class="three">
							<td class="four"></td>
							<td><span></span></td>
						</tr>
						
						<tr>
							<td class="one">总数量</td>
							<td><input type="number" name="pNumber" class="two"  value="${prod.pNumber}"></td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span id="numerr"></span></td>
						</tr>
						
						
						<tr>
							<td class="one">类别</td>
							<td>
								<select name="typeId">
									<c:forEach items="${typeList}" var="type">
										<option value="${type.typeId}"
												<c:if test="${type.typeId==prod.typeId}">
													selected="selected"
												</c:if>
										>${type.typeName}</option>

									</c:forEach>
								</select>
							</td>
						</tr>
						<!--错误提示-->
						<tr class="three">
							<td class="four"></td>
							<td><span></span></td>
						</tr>

						<tr>
							<td>
								<input type="submit" value="提交" class="btn btn-success">
							</td>
							<td>
								<input type="reset" value="取消" class="btn btn-default" onclick="myclose()">
							</td>
						</tr>
					</table>
				</form>
			</div>
		</div>

	</body>

</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/93679.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

滑动窗口的最大值【滑动窗口问题】

文章目录题目解题思路代码展示题目 给定一个长度为 n 的数组 num 和滑动窗口的大小 size &#xff0c;窗口从最左边滑动到最右边&#xff0c;每次向右边滑动一个位置&#xff0c;找出所有滑动窗口里数值的最大值。 窗口大于数组长度或窗口长度为0的时候&#xff0c;返回空 数…

硬件需知知识 -- 基本元件(电阻)

一、电阻 1.1 贴片电阻 1.1.1 贴片电阻的封装大小是和功率时相关的。 封装大小功率(W)0201120\frac{1}{20}201​0402116\frac{1}{16}161​0603110\frac{1}{10}101​080518\frac{1}{8}81​12060.2518120.5或1201012\frac{1}{2}21​25121或者21.1.2 贴片电阻读数 贴片电阻的读数…

Spring Security 竟然可以同时存在多个过滤器链?

目录Spring Security 中的过滤器多个过滤器链多个过滤器链配置例子http.authorizeRequests() 开头是什么意思&#xff1f;引用Spring Security 中的过滤器 Spring Security 中认证、授权功能的实现机制是通过过滤器来实现的。Spring Security 中一共提供了 32 个过滤器&#x…

Nacos集群版本安装(三)

一、前言 注&#xff1a;我这里的nacos集群安装环境使用的是本地MacOs系统&#xff0c;使用的是同一个IP不同端口&#xff0c;这里就不再讲解具体的目录结构之内的了&#xff0c;下面我们开始演示具体的配置和安装。了解nacos单机版本安装 二、nacos集群安装部署&#xff1a; …

Redis常见面试题(二)

目录 1、Redis和Memcached有什么区别? 2、Redis支持哪些数据类型? 3、Redis支持JSON数据类型吗?为什么? 4、Redis模块系统有什么用? 5、Redis支持对象映射模型吗? 6、Redis默认支持多少个数据库?怎么修改? 7、Redis SET命令可以代替SETNX吗? 8、Redis单个实例最…

【浅学Java】索引的分类、创建、删除以及新特性

索引的创建和设计原则1. 索引的分类1.1 普通索引1.2 唯一性索引1.3 主键索引1.4 单列索引1.5 多列&#xff08;联合&#xff0c;组合&#xff09;索引1.6 全文索引2. 索引的创建2.1 创建表时创建索引1. 隐式创建2. 显式创建3. 全文检索2.2 创建表后创建索引1. alter table 的方…

基于java(ssm)家教管理平台(java毕业设计)

基于java&#xff08;ssm&#xff09;家教管理平台 家教管理&#xff0c;是基于java变成语言&#xff0c;mysql数据库&#xff0c;ssm框架和idea工具开发&#xff0c;本系统分为用户&#xff0c;管理员&#xff0c;教师三个角色&#xff0c;其中用户可以注册&#xff0c;登陆&…

网络工程师之海明校验

海明校验&#xff08;又称汉明码&#xff09; 基本思想 将有效信息按某种规律分成若干组&#xff0c;每组安排一个校验位&#xff0c;做奇偶测试&#xff0c;就能提供多位检错信息&#xff0c;以指出最大可能是哪位出错&#xff0c;从而将其纠正。 特点 它不仅具有检测错误的…

深入浅出网络编程TCP,UDP,Socket,Http网络编程面试题

目录 什么是网络编程 网络编程中的主要问题 计算机网络体系结构 TCP / UDP Socket HTTP 什么是网络编程 网络编程中的主要问题 计算机网络体系结构 OSI参考模型 OSI&#xff08;Open System Interconnect&#xff09;&#xff0c;即开放式系统互联。一般都叫OSI参考模型&…

Geoserver提示HTTP ERROR 503 Service Unaviaiable以及Context initialization failed

场景 GeoServer简介、下载、配置启动、发布shapefile全流程(图文实践)&#xff1a; GeoServer简介、下载、配置启动、发布shapefile全流程(图文实践)_霸道流氓气质的博客-CSDN博客_geoserver简介 geoserver版本为2.19.2&#xff0c;在windows10系统中正常启动并运行后&#…

教程篇 | 史上最简单也最全新手Revit教程

Hi&#xff0c;朋友们&#xff0c;我是建模助手。 近期发现&#xff0c;后台留言的画风日渐扭曲&#xff0c;很多用户的私信内容不仅跟有求必应无关&#xff0c;甚至跟建模助手也无关&#xff0c;而是关于Revit的问题。&#xff08;这就很离谱了&#xff09; 但后来小编也算是…

MySQL数据库入门到精通,从mysql安装到mysql高级、mysql优化全囊括

1、存储引擎 1.1、MySQL体系结构 连接层&#xff1a;最上层是一些客户端和链接服务&#xff0c;主要完成一些类似于连接处理、授权认证以及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。服务层&#xff1a;第二层架构主要完成大多数的核心服务功…

Qt6 qtmqtt编译及演示示例(附带动态库)

前言 随着物联网的不断发展&#xff0c;如今很多项目都需要接入&#xff0c;而两年前也是因为项目需要&#xff0c;了解了一些关于mqtt的用法&#xff0c;并将其过程记录成几篇博客&#xff0c;近一年多时间陆陆续续有好多人私信咨询关于mqtt相关的问题&#xff0c;其中又有很…

ReentrantLock源码分析AQS原理

目录 (一)AQS简介 (二)AQS原理剖析 (三)源码思想-加锁&#xff1a; (1)构造方法 (2)公平锁lock方法(核心) 3、acquire获取资源方法(核心) (一)AQS简介 AQS是AbstractQueuedSynchronizer的简称,是一种实现阻塞锁和依赖FIFO队列的同步器框架。其依赖于一个原子变量state,子…

Unity Text Mesh Pro 浮动文字-学习

TextMeshPro&#xff08;TMP&#xff09;是unity的一套UI文字方案&#xff0c;支持对顶点、颜色进行编辑&#xff0c;自定义强&#xff0c;可扩展等优点。 对于英文数字即字符只需制作ASCII的文件即可&#xff0c;但是对于中文&#xff0c;如果我们的文字需要动态生成且不可控…

k8s教程(19)-pod之批处理调度

文章目录01 引言02 批处理调度2.1 任务模式分类2.1.1 按实现方式分类2.1.2 按批处理并行分类2.1 案例2.1.1 Job Template Expansion案例2.1.2 Queue with Pod Per Work Item案例2.1.3 Queue with Variable Pod Count案例03 文末01 引言 声明&#xff1a;本文为《Kubernetes权威…

思维方式之系统思维

这世界上的所有事物&#xff0c;都被规律作用着&#xff0c;以一种叫作“系统”的方式存在着。 我们身处时代这个大系统之中&#xff0c;如果没有一种全局的系统观&#xff0c;很容易就会和机遇失之交臂。凡事要顺势而为&#xff0c;用“个位”的管理对抗“千位”的时代&#…

精华推荐 |【Redis技术探索】「底层架构原理」深入透析主从架构的底层原理分析实现机制

&#x1f4d5;技术箴言 当心中有更高的山峰去攀登&#xff0c;就不会在意脚下的泥沼。 &#x1f4d5;前提概要 Redis高可用的方案包括&#xff1a;持久化、主从复制&#xff08;及读写分离&#xff09;、哨兵和集群&#xff08;Cluster&#xff09;。 &#x1f4d5;&#x1f…

音视频面试涨知识(四)

视频格式播放体验流量占用情况DASH统计直播推流端到播放端延时。支持和视频帧绑定的内容交互。比如&#xff0c;直播答题在播放端的弹窗等。小HLS对视频进行切片&#xff0c;按切片播放&#xff0c;缓存小起播快&#xff1b;拖动时间轴到任意时间播放时&#xff0c;可以快速定位…

dubbo2和dubbo3 入门简介

稳定版本:2.5.3 目前已恢复更新Apache Dubbo 是一款微服务框架,为大规模微服务实践提供高性能 RPC通信、流量治理、可观测性等解决方案, 涵盖 Java、Golang 等多种语言 SDK 实现。3.0 版本的正式发布,标志着 Apache Dubbo 正式进入云原生时代。3.0 在通信协议、服务发现、部…