SSM项目-商城后台管理系统

news2024/11/29 0:36:41

SSM项目-商城后台管理系统

  • 开发说明
    • 开发环境
    • 项目界面演示
    • 项目功能
    • 具体的技术指标
  • 开发过程
    • 1、搭建SSM框架
      • 1.1、建库建表
      • 1.2、新建Maven工程
      • 1.3、配置pom.xml
      • 1.4、目录结构
      • 1.5、jdbc.properties
      • 1.6、mybatis-config.xml
      • 1.7 两个Spring的配置文件
        • applicationContext_dao.xml
        • applicationContext_service.xml
      • 1.8、SpringMVC.xml
      • 1.9、web.xml
      • 1.10、log4j.xml
      • 1.11、index.jsp
      • 1.12、mybatis逆向工程生成pojo和mapper
    • 2、实现登录功能
      • 2.1、编写业务层代码
      • 2.2、编写控制层代码
      • 2.3、登录页
    • 3、显示全部商品
      • 3.1、编写业务层代码
      • 3.2、编写控制层代码
      • 3.3、商品管理页
    • 4、分页显示商品
      • 4.1、编写业务层代码
      • 4.2、编写控制层代码
      • 4.3、商品分页显示
    • 5、新增(上架)商品
      • 5.1、获取商品类别
      • 5.2、Ajax上传图片并回显
      • 5.3、新增商品
      • 5.4、新增(上架)商品页面展示
    • 6、更新商品
      • 6.1、回显并更新商品
      • 6.2、页面展示
    • 7、删除商品
      • 7.1、单个删除
      • 7.2、批量删除
      • 7.3、页面展示
    • 8、查询商品
      • 8.0、编写多条件查询语句
      • 8.1、编写业务层代码
      • 8.2、编写控制层代码
      • 8.3、页面展示
    • 9、项目托管
      • Gitee
      • GitHub
    • 10、项目所需前端页面资料

申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计39077字,阅读大概需要10分钟
更多学习内容, 欢迎关注我的个人公众号:不懂开发的程序猿

开发说明

开发环境

工具版本
后台框架Sprig5 + SpringMVC + Mybatis
服务器Tomcat 8.5.73
数据库MySQL 8.0.28
Build ToolsMaven 3.8.5
前端jQuery + Bootstrap + JavaScript
开发工具IDEA 2022.3

项目界面演示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

项目功能

1、介绍项目实现功能,使用到的技术点,使用到的框架,演示最终效果。

2、创建数据库和表,添加idea可视化。

3、完成SSM框架的搭建。

4、添加字符编码过滤器,实现中文编码解析。

5、使用数据库连接池技术,使用mybatis框架完成底层实体类的创建和数据访问层的实现。

6、实现登录功能。

7、实现登录成功后全部商品分页显示。

8、实现Ajax的翻页功能。

9、添加监听器,实现获取全部商品类型功能。

10、实现商品增加功能。

11、实现Ajax商品删除功能。

12、实现Ajax商品批量删除功能。

13、实现商品修改的回显功能。

14、实现商品修改功能。

15、实现按商品名称条件查询并分页功能,翻页使用Ajax技术。

16、实现按商品类型查询并分页功能,翻页使用Ajax技术。

17、实现按商品价格查询并分页功能,翻页使用Ajax技术。

18、实现按商品名称、商品类型、商品价格多条件查询并分页,翻页使用Ajax技术。

19、实现退出功能。

具体的技术指标

  1. 熟悉Spring框架的使用
  2. 熟悉SpringMVC框架的使用;
  3. 熟悉MyBatis框架的使用
  4. 掌握JSP的标签库的使用
  5. 掌握EL表达式的使用
  6. 掌握AJAX异步刷新技术的使用
  7. 掌握文件上传实现
  8. 掌握异步AJAX分页实现
  9. 熟悉企业日常的接口开发流程
  10. 熟悉企业的项目进度控制规范
  11. 建立起软件开发的基本思想和积累开发中常见的设计思路
  12. 巩固SSM框架以及JavaEE的相关知识点,增强对各个知识点的进一步认识

开发过程

1、搭建SSM框架

1.1、建库建表

DROP DATABASE IF EXISTS xiaomissm;
CREATE DATABASE xiaomissm DEFAULT CHARSET utf8;

/*打开DB*/
USE xiaomissm;
DROP TABLE IF EXISTS `orderdetail`;
DROP TABLE IF EXISTS `xmorder`;
DROP TABLE IF EXISTS `carshop`;
DROP TABLE IF EXISTS `address`;
DROP TABLE IF EXISTS `users`;
DROP TABLE IF EXISTS product_info;
DROP TABLE IF EXISTS product_type;
DROP TABLE IF EXISTS admin;


#DROP TABLE xiaomi_admin;
#################################管理员表
CREATE TABLE admin(
a_id INT AUTO_INCREMENT PRIMARY KEY,
a_name VARCHAR(20),
a_pass VARCHAR(20)
);
INSERT INTO admin(a_id,a_name,a_pass) VALUES(1,'admin','admin');

##########################商品类型表
CREATE TABLE product_type
(
type_id INT AUTO_INCREMENT PRIMARY KEY,
type_name VARCHAR(20)
);

####################添加数据
INSERT INTO product_type(type_name) VALUES('手机');
INSERT INTO product_type(type_name) VALUES('电脑');
INSERT INTO product_type(type_name) VALUES('电视');


#############################商品表
CREATE TABLE product_info
(
p_id INT AUTO_INCREMENT PRIMARY KEY,
p_name VARCHAR(20),
p_content VARCHAR(200), ##############33商品规格/简介
p_price INT, ###############价格
p_image VARCHAR(200), #############图片
p_number INT, ########数量
type_id INT,
p_date DATE,
FOREIGN KEY(type_id) REFERENCES product_type(type_id)
);
##添加
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米Note2','双曲面 黑色 6GB内存 64GB闪存',2899,'xmNote2.jpg',500,1,'2018-01-04');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('红米Note5A','5.5英寸 粉色 2GB内存 16GB闪存',699,'hmNote5A.jpg',500,1,'2018-01-05');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('红米Note4X','5.5英寸 绿色 4GB内存 64GB闪存',1299,'hmNote4X.jpg',500,1,'2018-01-06');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('红米4','5英寸 金色 3GB内存 32GB闪存',999,'hm4.jpg',500,1,'2018-01-07');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('红米4X','5英寸 黑色 3GB内存 32GB闪存',899,'hm4X.jpg',500,1,'2018-01-08');

INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米平板3','7.9英寸 金色 4GB内存 64GB闪存',1499,'xmPad3.jpg',500,2,'2018-01-09');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米Air12','12.5英寸 银色 4GB内存 128GB闪存',3599,'xmAir12.jpg',500,2,'2018-01-18');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米Air13','13.3英寸 银色 8GB内存 256GB闪存',4999,'xmAir13.jpg',500,2,'2018-01-17');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米Pro','15.6英寸 灰色 16GB内存 256GB闪存',6999,'xmPro.jpg',500,2,'2018-01-16');

INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米电视4','49英寸 原装LG屏 3840×2160 真4K',3299,'xmTV4-49.jpg',500,3,'2018-01-15');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米电视4','55英寸 原装三星屏 3840×2160 真4K',3999,'xmTV4-55.jpg',500,3,'2018-01-13');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米电视4','65英寸 原装三星屏 3840×2160 真4K',8999,'xmTV4-65.jpg',500,3,'2018-01-22');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米电视4A','43英寸 FHD全高清屏 1920*1080',1999,'xmTV4A-43.jpg',500,3,'2018-01-11');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米电视4A','49英寸 FHD全高清屏 1920*1080',2299,'xmTV4A-49.jpg',500,3,'2018-01-21');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米MIX2','全陶瓷 黑色 8GB内存 128GB闪存',4699,'xmMIX2.jpg',500,1,'2018-04-01');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米Note3','全网通 蓝色 6GB内存 64GB闪存',2499,'xmNote3.jpg',500,1,'2018-03-01');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米6','玻璃金属 白色 6GB内存 128GB闪存',2899,'xm6.jpg',500,1,'2018-02-01');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米MAX2','全金属 金色 4GB内存 64GB闪存',1599,'xmMAX2.jpg',500,1,'2018-01-02');
INSERT INTO product_info(p_name,p_content,p_price,p_image,p_number,type_id,p_date) VALUES('小米5X','全金属 金色 4GB内存 64GB闪存',1499,'xm5X.jpg',500,1,'2018-01-03');

1.2、新建Maven工程

在这里插入图片描述

1.3、配置pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jerry</groupId>
    <artifactId>missm</artifactId>
    <version>1.0</version>
    <packaging>war</packaging>

    <!-- 集中定义依赖版本号 -->
    <properties>
        <junit.version>4.12</junit.version>
        <spring.version>5.2.5.RELEASE</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.27</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>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>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</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>

1.4、目录结构

在这里插入图片描述

1.5、jdbc.properties

在这里插入图片描述

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

1.6、mybatis-config.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="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <plugins>
        <!--配置分页插件-->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
</configuration>

1.7 两个Spring的配置文件

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
       https://www.springframework.org/schema/context/spring-context.xsd">

    <!--    读取jdbc.properties属性文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

    <!--    创建数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--    创建SqlSessionFactoryBean-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--        配置数据源-->
        <property name="dataSource" ref="dataSource"></property>
        <!--        配置mybatis核心配置文件-->
        <property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
        <!--        配置实体类-->
        <property name="typeAliasesPackage" value="com.jerry.pojo"></property>
    </bean>
    <!--    创建mapper文件的扫描器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.jerry.mapper"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>
</beans>

applicationContext_service.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: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">
    <!--    设置业务逻辑层的包扫描器,目的是在指定的路径下,使用@Service注解的类,Spring负责创建对象,并添加依赖-->
    <context:component-scan base-package="com.jerry.service"></context:component-scan>

    <!--    设置事务管理器-->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--    添加事务的切面-->
    <tx:advice id="transactionInterceptor" transaction-manager="dataSourceTransactionManager">
        <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="interceptor" expression="execution(* com.jerry..service.*.*(..))"/>
        <!--绑定-->
        <aop:advisor advice-ref="transactionInterceptor" pointcut-ref="interceptor"/>
    </aop:config>
</beans>

1.8、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.jerry.controller"></context:component-scan>

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

    <!-- 开启MVC的注解驱动 -->
    <mvc:annotation-driven/>

    <!--    配置文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
</beans>

1.9、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">

    <!--    字符编码过滤器必须写在第一个,其他的框架配置写在下面-->
    <!-- 配置Spring的字符编码过滤器 -->
    <filter>
        <filter-name>CharacterEncodingFilter</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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</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>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <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>/admin/login.jsp</welcome-file>
    </welcome-file-list>
</web-app>

1.10、log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <param name="Encoding" value="UTF-8"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS}%m (%F:%L) \n"/>
        </layout>
    </appender>
    <logger name="java.sql">
        <level value="debug"/>
    </logger>
    <logger name="org.apache.ibatis">
        <level value="info"/>
    </logger>
    <root>
        <level value="debug"/>
        <appender-ref ref="STDOUT"/>
    </root>
</log4j:configuration>

1.11、index.jsp

<%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2023/2/12
  Time: 11:37
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

</body>
</html>

1.12、mybatis逆向工程生成pojo和mapper

MyBatisGeneratorTools自动生成mapper接口和pojo实体类

2、实现登录功能

2.1、编写业务层代码

AdminService

在这里插入图片描述

AdminServiceImpl

package com.jerry.service.impl;

import com.jerry.mapper.AdminMapper;
import com.jerry.pojo.Admin;
import com.jerry.pojo.AdminExample;
import com.jerry.service.AdminService;
import com.jerry.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * ClassName: AdminServiceImpl
 * Package: com.jerry.service.impl
 * Description:
 *
 * @Author jerry_jy
 * @Create 2023-02-12 18:54
 * @Version 1.0
 */

@Service
public class AdminServiceImpl implements AdminService {

    //在业务逻辑层中,一定有数据访问层的对象
    @Autowired
    AdminMapper adminMapper;

    @Override
    public Admin login(String name, String pwd) {

        //根据传入的用户或到数据库中查询相应用户对象
        //如果有条件,则一定要创建AdminExample的对象,用来封装条件
        AdminExample example = new AdminExample();

        //添加用户名a_name条件
        example.createCriteria().andANameEqualTo(name);

        List<Admin> list = adminMapper.selectByExample(example);
        if (list.size()>0){
            Admin admin = list.get(0);
            //如果查询到用户,再进行密码的密文比对,注意密码是密文的
            /**
             * admin.getApass ==> d033e22ae348aeb5660fc2140aec35850c4da997
             * pwd ==> admin
             * 在进行密码的密文对比时,将用户从前端页面输入的密码pwd进行md5加密,再与数据库中的查到的对象密码进行比对
             */
//            String md5 = MD5Util.getMD5(pwd);
//            if (md5==admin.getaPass()){
//                return admin;
//            }
            return admin;
        }else {
            // 没查到,就返回null
            return null;
        }


    }
}

2.2、编写控制层代码

AdminAction

package com.jerry.controller;

import com.jerry.pojo.Admin;
import com.jerry.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

/**
 * ClassName: AdminAction
 * Package: com.jerry.controller
 * Description:
 *
 * @Author jerry_jy
 * @Create 2023-02-12 19:13
 * @Version 1.0
 */

@Controller
@RequestMapping("/admin")
public class AdminAction {
    //切记:在所有的界面层,一定有业务逻辑层的对象
    @Autowired
    AdminService adminService;

    //实现登录判断,并进行相应的跳转
    @RequestMapping("/login.action")
    public String login(String name, String pwd, HttpServletRequest request) {

        Admin admin = adminService.login(name, pwd);
        if (admin != null) {
            //登录成功
//            request.setAttribute("admin", admin);
            request.getSession().setAttribute("admin", admin);
            return "main";

        } else {
            //登录失败
            request.setAttribute("errmsg", "用户名或密码不正确!");
            return "login";
        }

    }

}

2.3、登录页

http://localhost:8080/admin/login.jsp

在这里插入图片描述

登录成功页==>商品后台管理页

在这里插入图片描述

3、显示全部商品

3.1、编写业务层代码

ProductInfoService

public interface ProductInfoService {
    //显示全部商品不分页
    List<ProductInfo> getAllProduct();
}

ProductInfoServiceImpl

public class ProductInfoServiceImpl implements ProductInfoService {

   @Autowired
    ProductInfoMapper productInfoMapper;

    @Override
    public List<ProductInfo> getAllProduct() {

        return productInfoMapper.selectByExample(new ProductInfoExample());

    }
}

3.2、编写控制层代码

ProductInfoAction

@Controller
@RequestMapping("/prod")
public class ProductInfoAction {
    @Autowired
    ProductInfoService productInfoService;

    //显示全部商品不分页
    @RequestMapping("/getAll")
    private String getAllProduct(HttpServletRequest request){
        List<ProductInfo> list = productInfoService.getAllProduct();
        request.setAttribute("list", list);
        return "product";
    }

}

3.3、商品管理页

在这里插入图片描述

4、分页显示商品

4.1、编写业务层代码

ProductInfoService

public interface ProductInfoService {
    //显示全部商品不分页
    List<ProductInfo> getAllProduct();

    //商品分页显示
    //使用mybits提供的插件,返回值是PageInfo,形参传入(当前页,每页显示条数)
    PageInfo splitPage(int pageNum, int pageSize);
}

ProductInfoServiceImpl

@Service
public class ProductInfoServiceImpl implements ProductInfoService {

   @Autowired
    ProductInfoMapper productInfoMapper;

    @Override
    public List<ProductInfo> getAllProduct() {

        return productInfoMapper.selectByExample(new ProductInfoExample());

    }

    @Override
    public PageInfo splitPage(int pageNum, int pageSize) {

        //分页插件pageHelper工具类完成分页设置
        //SELECT * FROM product_info LIMIT 10,5;
        PageHelper.startPage(pageNum, pageSize);

        //进行PageInfo的数据封装,然后返回一个pageinfo对象就行了
        //1、进行条件查询,必须创建ProductInfoExample对象
        ProductInfoExample example = new ProductInfoExample();
        //2、设置排序,按主键降序排序
        //SELECT * FROM product_info ORDER BY p_id DESC;
        example.setOrderByClause("p_id desc");
        //3、排完序后,取集合。切记:一定在取集合前,设置PageHelper.startPage(pageNum, pageSize);
        List<ProductInfo> list = productInfoMapper.selectByExample(example);
        //4、将倒序排的集合,封装为PageInfo
        PageInfo<ProductInfo> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }
}

4.2、编写控制层代码

@Controller
@RequestMapping("/prod")
public class ProductInfoAction {
    //每页显示的记录数
    public static final int PAGE_SIZE = 5;
    @Autowired
    ProductInfoService productInfoService;

    //显示全部商品不分页
    @RequestMapping("/getAll")
    private String getAllProduct(HttpServletRequest request) {
        List<ProductInfo> list = productInfoService.getAllProduct();
        request.setAttribute("list", list);
        return "product";
    }

    //显示第一页的5条记录
    @RequestMapping("/split")
    private String split(HttpServletRequest request) {

        //得到第一页的数据
        PageInfo info = productInfoService.splitPage(1, PAGE_SIZE);
        request.setAttribute("info", info);
        return "product";
    }

    //Ajax分页的翻页处理
    @ResponseBody
    @RequestMapping("/ajaxSplit")
    private void ajaxSplit(int page, HttpSession session) {
        //取得当前page参数的页面数据
        PageInfo info = productInfoService.splitPage(page, PAGE_SIZE);

        session.setAttribute("info", info);
    }
}

4.3、商品分页显示

在这里插入图片描述

5、新增(上架)商品

5.1、获取商品类别

ProductTypeListener

package com.jerry.listener;

import com.jerry.pojo.ProductType;
import com.jerry.service.ProductTypeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.util.List;

/**
 * ClassName: ProductTypeListener
 * Package: com.jerry.listener
 * Description:
 *
 * @Author jerry_jy
 * @Create 2023-02-13 16:47
 * @Version 1.0
 */

@WebListener
public class ProductTypeListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

        //Spring注册监听器也是通过ContextLoaderListener,因此我们要手动管理ProductTypeListener
        //如果交给Spring管理就不知道哪个Listener先被创建
        //1、手动从Spring容器中取出ProductTypeServiceImpl的对象
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_*.xml");
        ProductTypeService productTypeService = (ProductTypeService) context.getBean("ProductTypeServiceImpl");
        List<ProductType> typeList = productTypeService.getAll();

        //2、放入全局作用域中,供新增页面、修改页面、前台的查询功能提供全部的商品类别集合
        servletContextEvent.getServletContext().setAttribute("typeList",typeList);

    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

5.2、Ajax上传图片并回显

ProductInfoAction

//异步Ajax文件上传处理
@ResponseBody
@RequestMapping("ajaxImg")
public Object ajaxImg(MultipartFile pimage,HttpServletRequest request){

    //1、提取、生成文件名UUID+上传图片后缀名.jpg .png
    String saveFileName = FileNameUtil.getUUIDFileName() + FileNameUtil.getFileType(pimage.getOriginalFilename());
    //2、获取图片的存取路径
    String path = request.getServletContext().getRealPath("/image_big");
    //3、转存
    try {
        pimage.transferTo(new File(path+File.separator+saveFileName));
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    //返回客户端的JSON对象, 封装图片路径,为了在页面上回显图片
    JSONObject object = new JSONObject();
    object.put("imgurl", saveFileName);

    return object.toString();
}

5.3、新增商品

业务层

ProductInfoService

//新增商品
int save(ProductInfo info);

在这里插入图片描述

ProductInfoServiceImpl

@Override
public int save(ProductInfo info) {
    return productInfoMapper.insert(info);
}

控制层

ProductInfoAction

//新增商品
@RequestMapping("/save")
public String save(ProductInfo info, HttpServletRequest request) {
    info.setpImage(saveFileName);
    info.setpDate(new Date());

    int num=-1;
    try {
        num=productInfoService.save(info);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

    if (num>0){
        request.setAttribute("msg", "增加成功");
    }else {
        request.setAttribute("msg", "增加失败");
    }

    //增加成功后应该重新访问数据库,所以跳转到分页显示的action上
    return "forward:/prod/split.action";
}

5.4、新增(上架)商品页面展示

在这里插入图片描述

在这里插入图片描述

6、更新商品

6.1、回显并更新商品

业务层

ProductInfoService

    //按主键id查询商品
    ProductInfo selectById(int pid);

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

ProductInfoServiceImpl

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

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

控制层

ProductInfoAction

//根据主键id查询商品
@RequestMapping("/one")
public String one(int pid, Model model){

    ProductInfo info = productInfoService.selectById(pid);
    model.addAttribute("prod", info);
    return "update";
}

    //更新商品
    @RequestMapping("/update")
    public String update(ProductInfo info, HttpServletRequest request) {
        //1、因为Ajax的异步图片上传,如果有上传过,则 saveFileName 里有上传过来的名称,
        //如果没有使用异步Ajax上传过图片,则saveFileName="",则实体类使用隐藏表单域提供上来的pImage原始图片的名称;
        if (!saveFileName.equals("")) {
            info.setpImage(saveFileName);
        }
        //完成更新处理
        int num = -1;
        //切记:对于增删改的操作,一定要进行try-catch的异常捕获
        try {
            num = productInfoService.update(info);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (num>0){
            //更新成功
            request.setAttribute("msg", "更新成功");
        }else {
            //更新失败
            request.setAttribute("msg", "更新失败");
        }

        //处理完更新后,saveFileName里可能有数据
        //而下一次使用这个变量作为判断的依据,就会出错,所以必须清空saveFileName
        saveFileName = "";
        //redirect会导致request请求丢失,改用forward
        return "forward:/prod/split.action";
    }

6.2、页面展示

在这里插入图片描述

在这里插入图片描述

7、删除商品

7.1、单个删除

ProductInfoService

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

ProductInfoServiceImpl

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

ProductInfoAction

//单个删除
@RequestMapping("/delete")
public String delete(int pid, HttpServletRequest request) {
    int num = -1;

    try {
        num = productInfoService.delete(pid);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    if (num > 0) {
        request.setAttribute("msg", "删除成功");
    } else {
        request.setAttribute("msg", "删除失败");
    }

    return "forward:/prod/deleteAjaxSplit.action";
}

@ResponseBody
@RequestMapping(value = "deleteAjaxSplit", produces = "text/html;charset=UTF-8")
public Object deleteAjaxSplit(HttpServletRequest request) {
    //取第一页的数据
    PageInfo info = productInfoService.splitPage(1, PAGE_SIZE);
    request.getSession().setAttribute("info", info);
    return request.getAttribute("msg");
}

7.2、批量删除

ProductInfoMapper

//批量删除商品的功能
int deleteBatch(String []ids);

ProductInfoMapper.xml

<delete id="deleteBatch">
  delete from product_info where p_id in
                           <foreach collection="array" item="pid" separator="," open="(" close=")">
                             #{pid}
                           </foreach>
</delete>

ProductInfoService

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

ProductInfoServiceImpl

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

ProductInfoAction

//批量删除商品
@RequestMapping("/deleteBatch")
public String deleteBatch(String pids, HttpServletRequest request) {
    //将上传上来的字符串截断开,形成商品id的字符数组
    String[] split = pids.split(",");
    int num = -1;
    try {
        num = productInfoService.deleteBatch(split);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    try {
        if (num > 0){
            request.setAttribute("msg", "批量删除成功");
        }else {
            request.setAttribute("msg", "批量删除失败");
        }
    } catch (Exception e) {
        request.setAttribute("msg", "商品不能删除");
    }

    return "forward:/prod/deleteAjaxSplit.action";
}

7.3、页面展示

单个删除

在这里插入图片描述

在这里插入图片描述

批量删除

在这里插入图片描述

在这里插入图片描述

8、查询商品

8.0、编写多条件查询语句

多条件的查询【条件】封装在vo对象中

package com.jerry.pojo.vo;

/**
 * ClassName: ProductInfoVo
 * Package: com.jerry.pojo.vo
 * Description:
 *
 * @Author jerry_jy
 * @Create 2023-02-14 11:49
 * @Version 1.0
 */
public class ProductInfoVo {
    //商品名称
    private String pname;

    //商品类型
    private Integer typeid;

    //最低价格
    private Integer lprice;

    //最高价格
    private Integer hprice;

    //设置页码
    private Integer page = 1;

    public ProductInfoVo() {
    }

    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 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 +
                '}';
    }
}

ProductInfoMapper

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

ProductInfoMapper.xml

 <!--
多条件查询 拼接
List<ProductInfo> selectCondition(ProductInfoVo vo);
-->
  <select id="selectCondition" parameterType="com.jerry.pojo.vo.ProductInfoVo" resultMap="BaseResultMap">
      select
      <include refid="Base_Column_List"></include>
      from product_info
    <!--拼接条件-->
      <where>
        <!--商品名称不为空,拼接商品名称模糊查询-->
          <if test="pname != null and pname != -1">
              and p_name like '%${pname}%'
          </if>
        <!--商品类型不为空,拼接商品类型查询-->
          <if test="typeid != null and type != ''">
              and type_id = #{typeid}
          </if>
        <!--如果最低价格不为空 且大于0(vo在类中实现),最高价格为空,则查询大于最低价格的所有商品-->
          <if test="(lprice != null and lprice != '') and (hprice == null or hprice == '')">
              and p_price &gt;= #{lprice}
          </if>
        <!--如果最低价格为空,最高价格不为空 且大于0,则查询小于最高价格的所有商品-->
          <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>
      order by p_id desc
  </select>

SelectConditionTest

package com.jerry;

import com.jerry.mapper.ProductInfoMapper;
import com.jerry.pojo.ProductInfo;
import com.jerry.pojo.vo.ProductInfoVo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

/**
 * ClassName: SelectConditionTest
 * Package: com.jerry
 * Description:
 *
 * @Author jerry_jy
 * @Create 2023-02-14 12:24
 * @Version 1.0
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext_dao.xml","classpath:applicationContext_service.xml"})
public class SelectConditionTest {
    @Autowired
    ProductInfoMapper productInfoMapper;

    @Test
    public void test(){
        ProductInfoVo vo = new ProductInfoVo();
        List<ProductInfo> list = productInfoMapper.selectCondition(vo);
        list.forEach(System.out::println);
    }
}

8.1、编写业务层代码

ProductInfoService

//多条件商品的查询 分页
PageInfo<ProductInfo> splitPageVo(ProductInfoVo vo, int pageSize);

ProductInfoServiceImpl

@Override
public PageInfo<ProductInfo> splitPageVo(ProductInfoVo vo, int pageSize) {
    //取出集合之前,先要取出PageHelper.startPage()属性设置
    PageHelper.startPage(vo.getPage(), pageSize);
    List<ProductInfo> list = productInfoMapper.selectCondition(vo);
    return new PageInfo<>(list);
}

8.2、编写控制层代码

package com.jerry.controller;

import com.github.pagehelper.PageInfo;
import com.jerry.pojo.ProductInfo;
import com.jerry.pojo.vo.ProductInfoVo;
import com.jerry.service.ProductInfoService;
import com.jerry.utils.FileNameUtil;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * ClassName: ProductInfoAction
 * Package: com.jerry.controller
 * Description:
 *
 * @Author jerry_jy
 * @Create 2023-02-13 11:33
 * @Version 1.0
 */

@Controller
@RequestMapping("/prod")
public class ProductInfoAction {
    //每页显示的记录数
    public static final int PAGE_SIZE = 5;

    //异步上传的文件图片的名称
    String saveFileName = "";

    @Autowired
    ProductInfoService productInfoService;

    //显示全部商品不分页
    @RequestMapping("/getAll")
    public String getAllProduct(HttpServletRequest request) {
        List<ProductInfo> list = productInfoService.getAllProduct();
        request.setAttribute("list", list);
        return "product";
    }

    //显示第一页的5条记录
    @RequestMapping("/split")
    public String split(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";
    }

    //Ajax分页的翻页处理
    @ResponseBody
    @RequestMapping("/ajaxSplit")
    public void ajaxSplit(ProductInfoVo vo, HttpSession session) {
        //取得当前page参数的页面数据
        PageInfo info = productInfoService.splitPageVo(vo, PAGE_SIZE);
        session.setAttribute("info", info);
    }

    //异步Ajax文件上传处理
    @ResponseBody
    @RequestMapping("ajaxImg")
    public Object ajaxImg(MultipartFile pimage, HttpServletRequest request) {

        //1、提取、生成文件名UUID+上传图片后缀名.jpg .png
        saveFileName = FileNameUtil.getUUIDFileName() + FileNameUtil.getFileType(pimage.getOriginalFilename());
        //2、获取图片的存取路径
        String path = request.getServletContext().getRealPath("/image_big");
        //3、转存
        try {
            pimage.transferTo(new File(path + File.separator + saveFileName));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //返回客户端的JSON对象, 封装图片路径,为了在页面上回显图片
        JSONObject object = new JSONObject();
        object.put("imgurl", saveFileName);

        return object.toString();
    }

    //新增商品
    @RequestMapping("/save")
    public String save(ProductInfo info, HttpServletRequest request) {
        info.setpImage(saveFileName);
        info.setpDate(new Date());

        int num = -1;
        try {
            num = productInfoService.save(info);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if (num > 0) {
            request.setAttribute("msg", "增加成功");
        } else {
            request.setAttribute("msg", "增加失败");
        }

        //清空saveFileName这个变量,为了下次新增或修改的异步Ajax的上传处理
        saveFileName = "";
        //增加成功后应该重新访问数据库,所以跳转到分页显示的action上
        return "forward:/prod/split.action";
    }

    //根据主键id查询商品
    @RequestMapping("/one")
    public String one(int pid, ProductInfoVo vo, Model model, HttpSession session) {

        ProductInfo info = productInfoService.selectById(pid);
        model.addAttribute("prod", info);
        //将多条件以及页码放在session中,更新处理结束后,分页时读取条件和页码
        session.setAttribute("prodVo", vo);
        return "update";
    }

    //更新商品
    @RequestMapping("/update")
    public String update(ProductInfo info, HttpServletRequest request) {
        //1、因为Ajax的异步图片上传,如果有上传过,则 saveFileName 里有上传过来的名称,
        //如果没有使用异步Ajax上传过图片,则saveFileName="",则实体类使用隐藏表单域提供上来的pImage原始图片的名称;
        if (!saveFileName.equals("")) {
            info.setpImage(saveFileName);
        }
        //完成更新处理
        int num = -1;
        //切记:对于增删改的操作,一定要进行try-catch的异常捕获
        try {
            num = productInfoService.update(info);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (num > 0) {
            //更新成功
            request.setAttribute("msg", "更新成功");
        } else {
            //更新失败
            request.setAttribute("msg", "更新失败");
        }

        //处理完更新后,saveFileName里可能有数据
        //而下一次使用这个变量作为判断的依据,就会出错,所以必须清空saveFileName
        saveFileName = "";
        //redirect会导致request请求丢失,改用forward
        return "forward:/prod/split.action";
    }

    //单个删除
    @RequestMapping("/delete")
    public String delete(int pid, ProductInfoVo vo, HttpServletRequest request) {
        int num = -1;

        try {
            num = productInfoService.delete(pid);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (num > 0) {
            request.setAttribute("msg", "删除成功");
            request.getSession().setAttribute("deleteProductVo", vo);
        } else {
            request.setAttribute("msg", "删除失败");
        }

        return "forward:/prod/deleteAjaxSplit.action";
    }

    @ResponseBody
    @RequestMapping(value = "deleteAjaxSplit", produces = "text/html;charset=UTF-8")
    public Object deleteAjaxSplit(HttpServletRequest request) {
        //取第一页的数据
        PageInfo info = null;
        Object vo = request.getSession().getAttribute("deleteProductVo");
        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");
    }

    //批量删除商品
    @RequestMapping("/deleteBatch")
    public String deleteBatch(String pids, HttpServletRequest request) {
        //将上传上来的字符串截断开,形成商品id的字符数组
        String[] split = pids.split(",");
        int num = -1;
        try {
            num = productInfoService.deleteBatch(split);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try {
            if (num > 0) {
                request.setAttribute("msg", "批量删除成功");
            } else {
                request.setAttribute("msg", "批量删除失败");
            }
        } catch (Exception e) {
            request.setAttribute("msg", "商品不能删除");
        }

        return "forward:/prod/deleteAjaxSplit.action";
    }

    //多条件商品的查询
    @ResponseBody
    @RequestMapping("/condition")
    public void condition(ProductInfoVo vo, HttpSession session) {
        List<ProductInfo> list = productInfoService.selectCondition(vo);
        session.setAttribute("list", list);
    }
}

8.3、页面展示

在这里插入图片描述

9、项目托管

Gitee

https://gitee.com/jinyang-jy/xiaomissm.git

GitHub

https://github.com/Jerry-jy/missm.git

10、项目所需前端页面资料

链接:https://pan.baidu.com/s/1CGnGV4anjBHVI_tLqLYXfw?pwd=2022
提取码:2022

–end–

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

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

相关文章

数据库(三)

第三章 MySQL库表操作 3.1 SQL语句基础 3.1.1 SQL简介 SQL&#xff1a;结构化查询语言(Structured Query Language)&#xff0c;在关系型数据库上执行数据操作、数据检索以及数据维护的标准语言。使用SQL语句&#xff0c;程序员和数据库管理员可以完成如下的任务。 改变数据…

【图解数据结构与算法】数据结构与算法知识点整理 Data Structures and Algorithms

程序数据结构算法 数据结构是可以存储和组织数据的命名位置。 算法是用于解决特定问题的一组步骤。 数据结构是指&#xff1a;一种数据组织、管理和存储的格式&#xff0c;它可以帮助我们实现对数据高效的访问和修改。 数据结构 数据元素 元素之间的结构。 如果说数据结…

什么人合适学习Python

发了几天的Python基础&#xff0c;也认识了一些朋友&#xff0c;忽然有人问起&#xff0c;说为啥学Python&#xff0c;或者说啥人学习Python&#xff0c;作为一个教龄8年从Python一线讲师到Python教学主管的我和大家分享一下个人的看法&#xff0c;还是提前说一下&#xff0c;个…

winapi模拟鼠标按住左键拖动

继前文《windows下通过uiAutomation技术获取ui元素》介绍获取ui元素信息后&#xff0c;还需要对信息进行修改&#xff0c;但是 uiAutomation 技术并未提供可修改的 api&#xff0c;只能另辟他径看看了。 以 camera raw 为例&#xff0c;已知的是可将鼠标放在指定区域位置&#…

电力国家(行业)标准目录

1、3&#xff5e;63kV交流高压负荷开关 GB 3804-90 代替 GB 3804-882、电气装置安装工程35kV及以下架空电力线路施工及验收规范Code for construction and acceptance of 35kVand umder over head power levels electricequipment installation engineeringGB50173—923、带电作…

论文文献引用规范和标准(国标GBT7714)@endnote国标样式@citation交叉引用编号

文章目录论文文献引用规范和标准&#xff08;国标GBT7714&#xff09;国标GBT7714-2015endnote stylerefs简述国标GBT7714条目的组织格式&#x1f388;Noteword中的文献交叉引用超链接[编号]&#x1f388;正则高级搜索批量选中引用序号上标调整更新引用编号项段落内容对齐居中&…

python爬虫学习记录

初识爬虫 爬虫的概念 「什么是爬虫」 爬虫&#xff1a;通过编写程序&#xff0c;模拟浏览器上网&#xff0c;并抓取有价值的数据的过程 反爬虫&#xff1a;门户网站通过制定相应的策略或技术手段&#xff0c;来阻止爬虫程序对其网站数据的爬取 反反爬&#xff1a;爬虫程序…

操作系统(五)页面置换算法与分配策略

操作系统&#xff08;五&#xff09;页面置换算法与分配策略 一、页面置换算法 1、最佳置换算法&#xff08;OPT&#xff09; 每次选择淘汰的页面将是以后永不使用&#xff0c;或者在最长时间内不再被访问的页面&#xff0c;这样可以保证最低的缺页率 实际上就是从当前内存块…

【Kubernetes】【一】Kubernetes介绍

Kubernetes介绍 应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个时代&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其它技术的参与 缺点&#xff1a;不能为应用程序定…

PDF SDK for Linux 8.4.2 Crack

PDF SDK for Linux 是适用于任何 Linux 企业或云应用程序的强大解决方案&#xff0c;非常适合需要完全可定制的 PDF 查看器或后端流程的任何 Linux 开发人员。 将 Foxit PDF SDK 嵌入到基于 Linux 的应用程序中非常容易。只需打开您最喜欢的 Linux IDE&#xff0c;复制您需要的…

电容笔和Apple pencil的区别有啥?学生党电容笔推荐

普通的电容笔与 Apple Pencil最大的区别在于&#xff0c;普通的电容笔没有像苹果电容笔那样的重力压感&#xff0c;而仅仅只有一个倾斜的压敢。但平替电容笔的其他性能也很不错&#xff0c;几乎和苹果 Pencil一样&#xff0c;而且平替电容笔的售价只需200元左右。目前&#xff…

react+antd+Table里切换Switch改变状态onChange 传参

场景&#xff1a;table列表里面&#xff0c;操作用Switch切换状态。对应列改变操作在colums里面// 表格行const colums: ColumnsType<potentialType> [{title: useLocale(创建时间),dataIndex: creation_date,key: creation_date,align: center,render: (v: string, rec…

【Python安全编程】Python实现网络主机和端口扫描

文章目录前言环境准备Python实现主机扫描基于ARP协议基于ICMP协议普通版本多线程版本Python实现端口扫描扫描单个端口利用多线程扫描端口后记前言 本文主要讲几个利用Python实现网络扫描的小例子&#xff0c;可以结合多线程或多进程编程改进实例 我曾经走过多遥远的路 跨越过多…

windows环境下安装Nginx及常用操作命令

windows环境下安装Nginx及常用操作命令nginx基本概述基本用途nginx安装nginx基本概述 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器。基本用途 nginx是一个轻量级高并发服务器&#xff0c;而tomcat并不是。nginx一般被用来做反向代理&#xff0c;将请求转发到应用…

The Social-Engineer Toolkit(社会工程学工具包)互联网第一篇全模块讲解

一、工具介绍 Social-Engineer Toolkit 是一个专为社会工程设计的开源渗透测试框架&#xff0c;可以帮助或辅助你完成二维码攻击、可插拔介质攻击、鱼叉攻击和水坑攻击等。SET 本身提供了大量攻击选项&#xff0c;可让您快速进行信任型攻击&#xff0c;也是一款高度自定义工具…

Fluent Python 笔记 第 14 章 可迭代的对象、迭代器和生成器

迭代是数据处理的基石。扫描内存中放不下的数据集时&#xff0c;我们要找到一种惰性获取数据项的方式&#xff0c;即按需一次获取一个数据项。这就是迭代器模式(Iterator pattern)。本章说明 Python 语言是如何内置迭代器模式的&#xff0c;这样就避免了自己手动去实现。 在 P…

Mask-RCNN(3) : 自定义数据集读取(VOC COCO)以及pycocotools的使用

文章目录1. COCO数据读取1.1 COCO数据集目录结构1.2 pycocotools的使用1.3 COCODetection类__init__方法__getitem__方法2. VOC数据读取2.1 VOC数据集目录结构2.2 VOCInstances类__init__方法2.3 __getitem__方法参考1. COCO数据读取 1.1 COCO数据集目录结构 下载并解压COCO数…

MySQL 6:MySQL存储过程、存储函数

MySQL 5.0 版本开始支持存储过程。存储过程是一组SQL语句&#xff0c;功能强大&#xff0c;可以实现一些复杂的逻辑功能&#xff0c;类似于JAVA语言中的方法&#xff1b;存储是数据库SQL语言层面的代码封装和复用。 存储过程有输入输出参数&#xff0c;可以声明变量&#xff0…

Android Monkey

1、Monkey&#xff08;Monkey是发送伪随机用户事件的工具&#xff09;介绍&#xff1a; Monkey测试是Android平台自动化测试的一种手段&#xff0c;通过Monkey程序模拟用户触摸屏幕、滑动Trackball、按键等操作来对设备上的程序进行压力测试&#xff0c;检测程序多久的时间会发…

安灯(andon)系统是车间现场管理的必备工具

安灯&#xff08;andon&#xff09;系统应用越来越广泛&#xff0c;不单单局限于汽车行业&#xff0c;更多生产型企业意识到了提高工作效率的重要性&#xff0c;提高工作效率根本的能提高生产水平&#xff0c;提高产量&#xff0c;而且安灯&#xff08;andon&#xff09;系统不…