创建Maven项目后没有webapp目录所以我们要添加web模块,
这里通过手动添加web模块,这种通过手动添加web模块方式创建的web项目是非常纯净的,没有任何附加的代码,开发中推荐。也可以使用maven的模板(在创建Maven时选择模板)创建web项目
<properties>
<junit.version>4.12junit.version>
<spring.version>5.2.5.RELEASEspring.version>
<mybatis.version>3.5.1mybatis.version>
<mybatis.spring.version>1.3.1mybatis.spring.version>
<mybatis.paginator.version>1.2.15mybatis.paginator.version>
<mysql.version>8.0.22mysql.version>
<slf4j.version>1.6.4slf4j.version>
<druid.version>1.1.12druid.version>
<pagehelper.version>5.1.2pagehelper.version>
<jstl.version>1.2jstl.version>
<servlet-api.version>3.0.1servlet-api.version>
<jsp-api.version>2.0jsp-api.version>
<jackson.version>2.9.6jackson.version>
properties>
在
中添加依赖
spring 所需要的依赖
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jmsartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>${spring.version}version>
dependency>
Mybatis相关依赖
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>${mybatis.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>${mybatis.spring.version}version>
dependency>
<dependency>
<groupId>com.github.miemiedevgroupId>
<artifactId>mybatis-paginatorartifactId>
<version>${mybatis.paginator.version}version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>${pagehelper.version}version>
dependency>
数据库相关的依赖
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>${druid.version}version>
dependency>
单元测试依赖
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
<scope>testscope>
dependency>
JSP相关依赖
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>${jstl.version}version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.0.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jsp-apiartifactId>
<scope>providedscope>
<version>${jsp-api.version}version>
dependency>
ackson Json处理工具包
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>${jackson.version}version>
dependency>
文件异步上传
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.4version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.3.1version>
dependency>
dependencies>
在
中添加插件
jdk 编译版本
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<source>1.8source>
<target>1.8target>
<encoding>UTF-8encoding>
configuration>
plugin>
在
中添加
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mimissm?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
jdbc.username=root
jdbc.password=root
mybatis大部分功能被spring接管,在这里分页pagehelper无法被spring接管,所以配置分页即可
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
configuration>
对spring配置文件按照分层进行拆分
其中实体类pojo和mapper文件夹未创建,后面通过mybatis逆向工程生成
<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">
<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>
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="typeAliasesPackage" value="com.yanyu.pojo">property>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.yanyu.mapper"/>
bean>
beans>
<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">
<context:component-scan base-package="com.yanyu.service"/>
<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="*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.yanyu.service.*.*(..))"/>
<aop:advisor advice-ref="myadvice" pointcut-ref="mypointcut"/>
aop:config>
beans>
springmvc.xml
<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.yanyu.controller"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/admin/">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>
注:字符编码过滤器需放在web.xml顶端
<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>encodefilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceRequestEncodingparam-name>
<param-value>tureparam-value>
init-param>
<init-param>
<param-name>forceResponseEncodingparam-name>
<param-value>tureparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodefilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
web-app>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.actionurl-pattern>
servlet-mapping>
spring配置文件若在WEB-INF目录下,会自动加载,在其他位置要手动加载
加载多个文件时有两个方法
1. 逗号隔开 :classpath:applicationContext_dao.xml,classpath:applicationContext_service.xml
2. 使用通配符 :classpath:applicationContext_*.xml (代表以 applicationContext_ 为前缀以.xml为后缀的文件)
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext_*.xmlparam-value>
context-param>
逆向工程简称MBG,是一个专门为MyBatis框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件,接口,以及bean类。支持基本的增删改查,以及QBC风格的条件查询。但是表连接、存储过程等这些复杂sqI的定义需要我们手工编写
在generatorConfig.xml中配置Mapper生成的详细信息,如下图:
注意修改内容主要以下几点:
修改数据库连接的信息
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mimissm?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true"
userId="root"
password="root">
jdbcConnection>
指定数据库表 (生成那些数据库表对应的文件) – admin,product_info,product_type
<table schema="" tableName="admin">table>
<table schema="" tableName="product_info">table>
<table schema="" tableName="product_type">table>
生成PO类的位置 – com.yanyu.pojo
<javaModelGenerator targetPackage="com.yanyu.pojo"
targetProject=".\src">
<property name="enableSubPackages" value="false" />
<property name="trimStrings" value="true" />
javaModelGenerator>
mapper映射文件生成的位置 – com.yanyu.mapper
<sqlMapGenerator targetPackage="com.yanyu.mapper"
targetProject=".\src">
<property name="enableSubPackages" value="false" />
sqlMapGenerator>
mapper接口生成的位置
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.yanyu.mapper"
targetProject=".\src">
<property name="enableSubPackages" value="false" />
javaClientGenerator>
运行前删除src下同名目录,防止文件重叠
参考:https://blog.csdn.net/qq_44058265/article/details/120460879
MD5Util工具类
package com.yanyu.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
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;
}
}
测试
@Test
public void testMD5(){
String md5 = MD5Util.getMD5("000000");
System.out.println(md5); //c984aed014aec7623a54f0591da07a85fd4b762d
}
AdminService
package com.yanyu.service;
import com.yanyu.pojo.Admin;
public interface AdminService {
Admin login(String name,String pwd);
}
通过数据访问层对象AdminMapper,查找数据,成功返回用户数据,失败返回null
AdminServiceImpl
package com.yanyu.service.impl;
import ...
@Service
public class AdminServiceImpl implements AdminService {
//数据访问层对象,spring自动创建注入
@Autowired
AdminMapper adminMapper;
@Override
public Admin login(String name, String pwd) {
//根据用户名在数据库查找用户
//使用AdminExample对象来封装条件
AdminExample example = new AdminExample();
/* select * from admin where a_name = 'admin' */
//添加用户名a_name = 'admin'条件
example.createCriteria().andANameEqualTo(name);
//执行查询
List<Admin> adminList = adminMapper.selectByExample(example);
if(adminList.size()>0){
Admin admin = adminList.get(0);
//进行密码对比判断 - 密码是密文
String md5 = MD5Util.getMD5(pwd);
/* System.out.println(admin.getaPass()+" "+md5);*/
if(md5.equals(admin.getaPass())){
return admin;
}
}
return null;
}
}
调用业务逻辑层对象AdminServiceImpl,获取登录信息,登陆成功,跳转到main.jsp页面,登陆失败,跳转到login.jsp页面
AdminAtion
package com.yanyu.controller;
import ...
@Controller
@RequestMapping("/admin")
public class AdminAction {
//业务逻辑层对象
@Autowired
AdminService adminService;
//实现登陆的判断,进行相应跳转、
@RequestMapping("/login")
public String login(String name, String pwd, HttpServletRequest request){
Admin admin = adminService.login(name,pwd);
if(admin!=null){
//登陆成功,跳转到main.jsp页面(视图解析器)
request.setAttribute("admin",admin); // 存储用户信息
return "main";
}else {
//登陆失败,跳转到login.jsp页面(视图解析器)
request.setAttribute("errmsg","用户名或密码不正确!"); //返回失败信息
return "login";
}
}
}
ProductInfoService
package com.yanyu.service;
import ...
public interface ProductInfoService {
//显示所有商品、
List<ProductInfo> getAll();
}
ProductInfoServiceImpl
package com.yanyu.service.impl;
import ...
@Service
public class ProductInfoServiceImpl implements ProductInfoService {
//数据访问层对象
@Autowired
ProductInfoMapper productInfoMapper;
@Override
public List<ProductInfo> getAll() {
//没有条件,查询所有
return productInfoMapper.selectByExample(new ProductInfoExample());
}
}
package com.yanyu.controller;
import ...
@Controller
@RequestMapping("/prod")
public class ProductInfoAction {
//业务逻辑层对象
@Autowired
ProductInfoService productInfoService;
//显示所有商品
@RequestMapping("/getAll")
public String getAll(HttpServletRequest request){
List<ProductInfo> list = productInfoService.getAll();
//传递数据
request.setAttribute("list",list);
//跳转页面
return "product";
}
}
PageInfo由分页插件pagehelper提供(PageInfo页面数据类,包含当前页,页大小,当前页大小,当前页数据…),pageNum当前页,pageSize页的大小
//分页功能,PageInfo由分页插件pagehelper提供,pageNum当前页,pageSize页的大小
PageInfo splitPage(int pageNum,int pageSize);
@Override
public PageInfo splitPage(int pageNum, int pageSize) {
//分页插件使用PageHelper工具类完成分页设置(),放在取数据集合之前
PageHelper.startPage(pageNum,pageSize);
//条件查询 - 主键降序 select* from product_info order by p_id desc
ProductInfoExample example =new ProductInfoExample();
//添加条件order by p_id desc
example.setOrderByClause("p_id desc");
//查询数据,分页设置PageHelper要放在取数据集合之前
List<ProductInfo> list = productInfoMapper.selectByExample(example);
//将数据封装进PageInfo中,PageInfo自动对list进行分页
PageInfo<ProductInfo> pageInfo = new PageInfo<>(list);
return pageInfo;
}
显示初始页数据(第一页的5条数据)到前台 , 翻页由ajax异步来完成
设置每页显示记录数常量PAGE_SIZE,方便修改
//每页显示记录数
public static final int PAGE_SIZE = 5 ;
//显示初始页数据(第一页的5条数据)
@RequestMapping("/split")
public String split(HttpServletRequest request){
//得到第一页数据
PageInfo info = productInfoService.splitPage(1,PAGE_SIZE);
request.setAttribute("info",info);
return "product";
}
前台接收初始页数据,通过ajax翻页,ajax传到界面控制层 – ProductInfoAtion中进行分页
<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"> 全选
<a href="${pageContext.request.contextPath}/admin/addproduct.jsp">
<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><img width="55px" height="45px"
src="${pageContext.request.contextPath}/image_big/${p.pImage}">td>
<td>${p.pNumber}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})">删除
button>
td>
tr>
c:forEach>
table>
<div id="bottom">
<div>
<nav aria-label="..." style="text-align:center;">
<ul class="pagination">
<li>
<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="javascript:ajaxsplit(${i})"
style="background-color: grey">${i}a>
li>
c:if>
<c:if test="${info.pageNum!=i}">
<li>
<a href="javascript:ajaxsplit(${i})">${i}a>
li>
c:if>
c:forEach>
<li>
<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;">总共 <font style="color:orange;">${info.pages}font> 页
<c:if test="${info.pageNum!=0}">
当前 <font style="color:orange;">${info.pageNum}font> 页
c:if>
<c:if test="${info.pageNum==0}"> 当前 <font style="color:orange;">1font> 页
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>
<script type="text/javascript">
function ajaxsplit(page) {
//异步ajax分页请求
$.ajax({
url:"${pageContext.request.contextPath}/prod/ajaxSplit.action",
data:{"page":page},
type:"post",
success:function () {
//重新加载分页显示的组件table
//location.href---->http://localhost:8080/admin/login.action
$("#table").load("http://localhost:8080/admin/product.jsp #table");
}
})
};
script>
//ajax分页处理
//解析ajax请求,返回客户端
@ResponseBody
@RequestMapping("/ajaxSplit")
public void ajaxSplit(int page, HttpSession session){
//取得当前页page的数据
PageInfo info = productInfoService.splitPage(page,PAGE_SIZE);
System.out.println(info.getList());
session.setAttribute("info",info);
}
package com.yanyu.service;
package ...
public interface ProductTypeService {
List<ProductType> getAll();
}
package com.yanyu.service.impl;
import ...
@Service("ProductTypeServiceImpl")
public class ProductTypeServiceImpl implements ProductTypeService {
//数据访问层对象
@Autowired
ProductTypeMapper productTypeMapper;
@Override
public List<ProductType> getAll() {
return productTypeMapper.selectByExample(new ProductTypeExample());
}
}
spring容器的注册是通过监听器,与该对象是同一个监听器,无法确定谁先创建,所以无法使用spring的自动装配,需手动从Spring容器取出ProductTypeServiceImpl对象
package com.yanyu.listener;
import ...
@WebListener
public class ProductTypeListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
//手动从Spring容器取出ProductTypeServiceImpl对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_*.xml");
ProductTypeService productTypeService = (ProductTypeService) context.getBean("ProductTypeServiceImpl");
List<ProductType> typeList = productTypeService.getAll();
//放入全局作用域中
sce.getServletContext().setAttribute("typeList",typeList);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
<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>
<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>
<!-- 引入ajaxfileupload.js-->
<script type="text/javascript" src="${pageContext.request.contextPath }/js/ajaxfileupload.js"></script>
<script type="text/javascript">
function fileChange(){//注意:此处不能使用jQuery中的change事件,因此仅触发一次,因此使用标签的:onchange属性
$.ajaxFileUpload({
url: '/prod/ajaxImg.action',//用于文件上传的服务器端请求地址
secureuri: false,//是否需要安全协议一般设置为false
fileElementId: 'pimage',//文件上传控件的id属性
dataType: 'json',//返回值类型 一般设置为json
success: function(obj) //服务器成功响应处理函数
{
$("#imgDiv").empty(); //清空原有数据
//创建img 标签对象
var imgObj = $("");
//给img标签对象追加属性
imgObj.attr("src","/image_big/"+obj.imgurl);
imgObj.attr("width","100px");
imgObj.attr("height","100px");
//将图片img标签追加到imgDiv末尾
$("#imgDiv").append(imgObj);
},
error: function (e)//服务器响应失败处理函数
{
alert(e.message);
}
});
}
</script>
//异步Ajax文件上传处理
@ResponseBody
@RequestMapping("/ajaxImg")
//pimage与前台上传的name值一样
public Object ajaxImg(MultipartFile pimage,HttpServletRequest request){
//生成文件名和后缀,通过FileNameUtil工具类将前台上传的文件名通过UUID重新生成,防止重复
String uuidFileName = FileNameUtil.getUUIDFileName()+FileNameUtil.getFileType(pimage.getOriginalFilename());
//存取路径 -- 完整的项目本地路径
String path = request.getServletContext().getRealPath("/image_big");
//存储 File.separator -> \
try {
pimage.transferTo(new File(path+File.separator+uuidFileName));
} catch (IOException e) {
e.printStackTrace();
}
//返回josn对象,包含图片路径,
String s = "{\"imgurl\":\""+uuidFileName+"\"}";
return s;
}
package com.yanyu.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);
}
}
//新增商品
int save(ProductInfo info);
@Override
public int save(ProductInfo info) {
return productInfoMapper.insert(info);
}
@RequestMapping("/save")
public String save(ProductInfo info,HttpServletRequest request){
//文件由ajaxImg方法上传,将uuidFileName设置为全局变量,在此传递给数据库
info.setpImage(uuidFileName);
//前端提交的数据不包含时间,由后端添加
info.setpDate(new Date());
//num受影响行数
int num=0;
try {
num = productInfoService.save(info);
} catch (Exception e) {
e.printStackTrace();
}
if(num>0){
request.setAttribute("msg","增加成功!");
}else{
request.setAttribute("msg","增加失败!");
}
//转发到所有商品初始页
return "forward:/prod/split.action";
}
//按主键id查询商品
ProductInfo getById(int pid);
@Override
public ProductInfo getById(int pid) {
return productInfoMapper.selectByPrimaryKey(pid);
}
@RequestMapping("one")
public String one(int pid, Model model){
ProductInfo byId = productInfoService.getById(pid);
model.addAttribute("prod",byId);
//更新时可以修改图片,防止数据冲突,清除uuidFileName
uuidFileName="";
return "update";
}
function one(pid) {
location.href = "${pageContext.request.contextPath}/prod/one.action?pid=" + pid;
}
....
<button type="button" class="btn btn-info " onclick="one(${p.pId})">编辑 </button>
//取消时返回初始页
<script type="text/javascript">
function myclose(ispage) { window.location="${pageContext.request.contextPath}/admin/product/split.action";
//window.close();
}
script>
<div id="table">
<form action="${pageContext.request.contextPath}/prod/update.action" enctype="multipart/form-data" method="post" id="myform">
//修改根据id,所以要提交,但不修改用隐藏域
<input type="hidden" value="${prod.pId}" name="pId">
//用于判断是否重新上传图片
<input type="hidden" value="${prod.pImage}" name="pImage">
...
商品名称
商品介绍
定价
...
//显示图片和异步上传
<tr>
<td class="one">图片介绍td>
<td> <br><div id="imgDiv" style="display:block; width: 40px; height: 50px;"><img src="/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>
...
总数量
...
//取出全局中的数据,与修改商品的类别id对比,selected="selected"表示选中
<tr>
<td class="one">类别td>
<td>
<select name="typeId">
<c:forEach items="${typeList}" var="type">
<option value="${type.typeId}"
if test="${type.typeId==prod.typeId}">
selected="selected"
c:if>
>${type.typeName}option>
c:forEach>
select>
td>
tr>
<td>
<input type="submit" value="提交" class="btn btn-success">
td>
<td>
<input type="reset" value="取消" class="btn btn-default" onclick="myclose(1)">
td>
tr>
table>
form>
div>
//更新商品
int update(ProductInfo info);
@Override
public int update(ProductInfo info) {
return productInfoMapper.updateByPrimaryKey(info);
}
@RequestMapping("/update")
public String update(ProductInfo info,HttpServletRequest request){
//判断是否有重新上传的图片,若有则修改图片地址,没有不变
if(!uuidFileName.equals("")) {
info.setpImage(uuidFileName);
}
//num受影响行数
int num=0;
try {
num = productInfoService.update(info);
} catch (Exception e) {
e.printStackTrace();
}
if(num>0){
request.setAttribute("msg","更新成功!");
}else{
request.setAttribute("msg","更新失败!");
}
//转发到所有商品初始页
return "forward:/prod/split.action";
}
//批量删除
function deleteBatch() {
//取得所有被选中删除商品的pid
var cks=$("input[name=ck]:checked");
//判断是否有选中的商品
if(cks.length==0){
// 没有选中的商品
alert("请选择将要删除的商品!");
}else{
var str="";
var id="";
// 有选中的商品,则取出每个选中商品的ID,拼接提交的ID的数据
if(confirm("您确定删除"+cks.length+"条商品吗?")){
//拼接ID
$.each(cks,function () {
id=$(this).val(); //22 33
//非空判断,防止出错
if(id!=null)
str += id+","; //22,33,44
});
//发送ajax请求
$.ajax({
url:"${pageContext.request.contextPath}/prod/deleteBatch.action",
data:{"ids":str},
type:"post",
dataType: "text",
success:function (msg) {
alert(msg);
$("#table").load("http://localhost:8080/admin/product.jsp #table");
}
});
}
}
}
<delete id="deleteBatch">
delete from product_info where p_id in
/* 采用foreach来拼接多个数据
* collection="array" 数组类型
* separator="," 每个数值之间的间隔符
* open="(" 开始的字符
* close=")" 结束的字符
*/
<foreach collection="array" item="pid" separator="," open="(" close=")">
#{pid}
foreach>
delete>
@Override
public int deleteBatch(String[] ids) {
return productInfoMapper.deleteBatch(ids);
}
//ajax异步批量删除
@ResponseBody
@RequestMapping(value = "/deleteBatch",produces = "text/html;charset=UTF-8")
public Object delete(String ids,HttpSession session){
//将上传的id拼接字符串拆分为字符数组
String[] pids = ids.split(",");
//num受影响行数
int num=0;
try {
num = productInfoService.deleteBatch(pids);
} catch (Exception e) {
e.printStackTrace();
}
//重新分页
PageInfo info = productInfoService.splitPage(1,PAGE_SIZE);
session.setAttribute("info",info);
if(num>0){
return "批量删除成功!";
}else{
return "批量删除失败!";
}
}