搭建SSM项目
- 1. 新建Maven工程,添加Web模板
- 2. 配置 pom.xml文件
-
- 2.1 集中定义全局变量 : 依赖版本号 (方便管理版本)
- 2.2 依赖
- 2.3 插件
- 2.4 识别配置文件
- 3. 添加配置文件
-
- 3.1 数据库连接信息jdbc.properties文件配置
- 3.2 MyBatis核心配置文件mybatis-config.xml
- 3.3 Spring配置文件
-
- 3.3.1 数据持久层 -- applicationContext_dao.xml
- 3.3.2 业务逻辑层 -- applicationContext_service.xml
- 3.4 springMVC配置文件springmvc.xml
- 4. 设置web.xml文件
-
- 4.1 添加字符编码过滤器
- 4.2 注册SpringMVC框架
- 4.3 注册Spring框架
- 5. 使用Mabatis逆向工程生成pojo和mapper
-
- 5.1 导入逆向工程
- 5.2 修改配置文件
- 5.3 运行GeneratorSqlmap,生成pojo和mapper文件
- 5.4 MyBatis逆向工程中的Mapper接口以及Example的实例函数及详解
- 6. 添加MD5加密算法(保护密码)
- 7. 实现登录功能
-
- 7.1 业务逻辑层 -- 创建AdminService接口,添加登录login
- 7.2 业务逻辑层 -- 创建AdminServiceImpl,实现AdminService接口登录login
- 7.3 界面控制层 -- 创建AdminAtion,添加login,判断是否登陆成功,并跳转相应页面
- 8. 实现查询所有商品数据
-
- 8.1 业务逻辑层 -- 创建ProductInfoService接口,添加查询所有商品功能getAll
- 8.2 业务逻辑层 -- 创建ProductInfoServiceImpl,实现getAll
- 8.3 界面控制层 -- 创建ProductInfoAtion,添加getAll,传递数据到前台
- 9. 实现分页展示 --Ajax异步 -- mybatis插件pagehelper
-
- 9.1 业务逻辑层 -- ProductInfoService接口中,添加分页功能splitPage
- 9.2 业务逻辑层 -- ProductInfoServiceImpl中,实现splitPage,完成分页
- 9.3 界面控制层 -- ProductInfoAtion中,添加splitPage,传递数据到前台product.jsp
- 9.4 product.jsp前台接收数据展示,设置分页栏
- 9.5 分页的AJAX实现
- 9.6 界面控制层 -- ProductInfoAtion中,添加ajaxSplit,对ajax进行解析完成分页
- 10 . 商品类别下拉选项实现 -- 监听器实现(自动查询并存入全局对象中)
-
- 10.1 业务逻辑层 -- 实现获取所有类别数据
-
- 创建ProductTypeService接口,定义获取所有类别数据方法getAll
- 创建ProductTypeServiceImpl实现接口的所有类别数据方法getAll
- 10.2 通过监听器自动查询并存入全局对象中
- 10.3 前端下拉框显示类别
- 11. 上传文件 --ajax异步上传并回显 -- springMVC组件
-
- 11.1 前端上传图片
-
- 文件选择
- Ajax异步提交事件 -- 采用ajaxfileupload.js文件(封装ajax异步上传的功能)
- 11.2 在ProductInfoAction中添加异步Ajax文件上传处理
-
- Ajax文件上传处理并返回含图片位置的json对象用于回显图片
- FileNameUtil工具类 -- 用于UUID文件名防止重复
- 12 . 新增商品功能
-
- 12.1 业务逻辑层 -- 实现新增商品
-
- ProductInfoService接口添加save方法
- ProductInfoServiceImpl实现类实现save
- 12.2 界面控制层 -- ProductInfoAtion中,添加save完成添加,返回初始页
- 13. 更新商品
-
- 13.1 根据主键id查询商品,用于修改数据 - getById方法
-
- 业务逻辑层 -- ProductInfoService接口添加getById方法
- 业务逻辑层 -- ProductInfoServiceImpl实现类实现getById
- 界面控制层 -- ProductInfoAtion中,添加one方法完成查询,返回修改页
- 13.3 前端点击编辑,跳转one方法根据主键id查询所要修改的数据,回显
- 13.3 更新前端页面 -- 主要代码
- 13.4 修改数据 - update方法
-
- 业务逻辑层 -- ProductInfoService接口添加update方法
- 业务逻辑层 -- ProductInfoServiceImpl实现类实现update
- 界面控制层 -- ProductInfoAtion中,添加update完成更新
- 14. ajax批量删除
-
- 14.1 前端点击触发
- 14.2 在mapper中添加操作语句(复杂操作)
- 14.3 实现删除
1. 新建Maven工程,添加Web模板 创建Maven项目后没有webapp目录所以我们要添加web模块,
文章图片
这里通过手动添加web模块,这种通过手动添加web模块方式创建的web项目是非常纯净的,没有任何附加的代码,开发中推荐。也可以使用maven的模板(在创建Maven时选择模板)创建web项目
如下图所示,添加web模块
文章图片
文章图片
2. 配置 pom.xml文件 2.1 集中定义全局变量 : 依赖版本号 (方便管理版本)
4.12
>5.2.5.RELEASE
3.5.1
1.3.1
1.2.15
8.0.22
>1.6.4
1.1.12
5.1.2
1.2
>3.0.1
2.0
2.9.6
2.2 依赖 在
...
中添加依赖spring 所需要的依赖
org.springframework
spring-context
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-webmvc
${spring.version}
org.springframework
spring-jdbc
${spring.version}
org.springframework
spring-aspects
${spring.version}
org.springframework
spring-jms
${spring.version}
org.springframework
spring-context-support
${spring.version}
org.springframework
spring-test
${spring.version}
Mybatis相关依赖
org.mybatis
mybatis
${mybatis.version}
org.mybatis
mybatis-spring
${mybatis.spring.version}
com.github.miemiedev
mybatis-paginator
${mybatis.paginator.version}
com.github.pagehelper
pagehelper
${pagehelper.version}
数据库相关的依赖
mysql
mysql-connector-java
${mysql.version}
com.alibaba
druid
${druid.version}
单元测试依赖
junit
junit
${junit.version}
>test
JSP相关依赖
jstl
jstl
${jstl.version}
javax.servlet
javax.servlet-api
3.0.1
>provided
javax.servlet
jsp-api
>provided
${jsp-api.version}
ackson Json处理工具包
com.fasterxml.jackson.core
jackson-databind
${jackson.version}
文件异步上传
commons-io
commons-io
2.4
commons-fileupload
commons-fileupload
1.3.1
2.3 插件 在
...
中添加插件jdk 编译版本
org.apache.maven.plugins
maven-compiler-plugin
>1.8
1.8
UTF-8
2.4 识别配置文件 在
...
中添加
src/main/java
**/*.properties
**/*.xml
false
src/main/resources
**/*.properties
**/*.xml
false
3. 添加配置文件 3.1 数据库连接信息jdbc.properties文件配置
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
3.2 MyBatis核心配置文件mybatis-config.xml mybatis大部分功能被spring接管,在这里分页pagehelper无法被spring接管,所以配置分页即可
3.3 Spring配置文件 对spring配置文件按照分层进行拆分
3.3.1 数据持久层 – applicationContext_dao.xml
其中实体类pojo和mapper文件夹未创建,后面通过mybatis逆向工程生成
3.3.2 业务逻辑层 – applicationContext_service.xml
3.4 springMVC配置文件springmvc.xml springmvc.xml
4. 设置web.xml文件 4.1 添加字符编码过滤器
注:字符编码过滤器需放在web.xml顶端
encode
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceRequestEncoding
ture
forceResponseEncoding
ture
encode
/*
4.2 注册SpringMVC框架
>
>springmvc
>org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
>
>springmvc
*.action
4.3 注册Spring框架
spring配置文件若在WEB-INF目录下,会自动加载,在其他位置要手动加载
加载多个文件时有两个方法
1. 逗号隔开 :classpath:applicationContext_dao.xml,classpath:applicationContext_service.xml
2. 使用通配符 :classpath:applicationContext_*.xml (代表以 applicationContext_ 为前缀以.xml为后缀的文件)
org.springframework.web.context.ContextLoaderListener
contextConfigLocationclasspath:applicationContext_*.xml
5. 使用Mabatis逆向工程生成pojo和mapper 5.1 导入逆向工程 逆向工程简称MBG,是一个专门为MyBatis框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件,接口,以及bean类。支持基本的增删改查,以及QBC风格的条件查询。但是表连接、存储过程等这些复杂sqI的定义需要我们手工编写
- 官方文档地址http://www.mybatis.org/generator/
- 官方工程地址 https://github.com/mybatis/generator/releases
文章图片
5.2 修改配置文件 在generatorConfig.xml中配置Mapper生成的详细信息,如下图:
文章图片
注意修改内容主要以下几点:
- 修改数据库连接的信息
- 指定数据库表 (生成那些数据库表对应的文件) – admin,product_info,product_type
- 生成PO类的位置 – com.yanyu.pojo
- mapper映射文件生成的位置 – com.yanyu.mapper
targetPackage="com.yanyu.mapper" targetProject=".\src">
- mapper接口生成的位置
文章图片
运行前删除src下同名目录,防止文件重叠运行程序后,在设置的目录下生成对应文件
文章图片
5.4 MyBatis逆向工程中的Mapper接口以及Example的实例函数及详解 参考:https://blog.csdn.net/qq_44058265/article/details/120460879
6. 添加MD5加密算法(保护密码)
- MD5(message-digest algorithm 5)信息摘要算法,
它的长度一般是32位的16进制数字符串(如81dc9bdb52d04dc20036dbd8313ed055) - 由于系统密码明文存储容易被黑客盗取
- 应用:注册时,将密码进行md5加密,存到数据库中,防止可以看到数据库数据的人恶意篡改。
登录时,将密码进行md5加密,与存储在数据库中加密过的密码进行比对 - md5不可逆,即没有对应的算法,从产生的md5值逆向得到原始数据。
但是可以使用暴力破解,这里的破解并非把摘要还原成原始数据,如暴力枚举法。
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
测试
@Test
public void testMD5(){
String md5 = MD5Util.getMD5("000000");
System.out.println(md5);
//c984aed014aec7623a54f0591da07a85fd4b762d
}
7. 实现登录功能 7.1 业务逻辑层 – 创建AdminService接口,添加登录login AdminService
package com.yanyu.service;
import com.yanyu.pojo.Admin;
public interface AdminService {
Admin login(String name,String pwd);
}
7.2 业务逻辑层 – 创建AdminServiceImpl,实现AdminService接口登录login 通过数据访问层对象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 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;
}
}
7.3 界面控制层 – 创建AdminAtion,添加login,判断是否登陆成功,并跳转相应页面 调用业务逻辑层对象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";
}
}}
8. 实现查询所有商品数据 8.1 业务逻辑层 – 创建ProductInfoService接口,添加查询所有商品功能getAll ProductInfoService
package com.yanyu.service;
import ...public interface ProductInfoService {
//显示所有商品、
List getAll();
}
8.2 业务逻辑层 – 创建ProductInfoServiceImpl,实现getAll ProductInfoServiceImpl
package com.yanyu.service.impl;
import ...@Service
public class ProductInfoServiceImpl implements ProductInfoService {
//数据访问层对象
@Autowired
ProductInfoMapper productInfoMapper;
@Override
public List getAll() {
//没有条件,查询所有
return productInfoMapper.selectByExample(new ProductInfoExample());
}
}
8.3 界面控制层 – 创建ProductInfoAtion,添加getAll,传递数据到前台
package com.yanyu.controller;
import ...@Controller
@RequestMapping("/prod")
public class ProductInfoAction {
//业务逻辑层对象
@Autowired
ProductInfoService productInfoService;
//显示所有商品
@RequestMapping("/getAll")
public String getAll(HttpServletRequest request){
List list = productInfoService.getAll();
//传递数据
request.setAttribute("list",list);
//跳转页面
return "product";
}
}
9. 实现分页展示 --Ajax异步 – mybatis插件pagehelper 9.1 业务逻辑层 – ProductInfoService接口中,添加分页功能splitPage PageInfo由分页插件pagehelper提供(PageInfo页面数据类,包含当前页,页大小,当前页大小,当前页数据…),pageNum当前页,pageSize页的大小
//分页功能,PageInfo由分页插件pagehelper提供,pageNum当前页,pageSize页的大小
PageInfo splitPage(int pageNum,int pageSize);
9.2 业务逻辑层 – ProductInfoServiceImpl中,实现splitPage,完成分页
@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 list = productInfoMapper.selectByExample(example);
//将数据封装进PageInfo中,PageInfo自动对list进行分页
PageInfo pageInfo = new PageInfo<>(list);
return pageInfo;
}
9.3 界面控制层 – ProductInfoAtion中,添加splitPage,传递数据到前台product.jsp 显示初始页数据(第一页的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";
}
9.4 product.jsp前台接收数据展示,设置分页栏 前台接收初始页数据,通过ajax翻页,ajax传到界面控制层 – ProductInfoAtion中进行分页
9.5 分页的AJAX实现
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");
}
})
};
9.6 界面控制层 – ProductInfoAtion中,添加ajaxSplit,对ajax进行解析完成分页
//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);
}
10 . 商品类别下拉选项实现 – 监听器实现(自动查询并存入全局对象中) 10.1 业务逻辑层 – 实现获取所有类别数据 创建ProductTypeService接口,定义获取所有类别数据方法getAll
package com.yanyu.service;
package ...public interface ProductTypeService {
List getAll();
}
创建ProductTypeServiceImpl实现接口的所有类别数据方法getAll
package com.yanyu.service.impl;
import ...@Service("ProductTypeServiceImpl")
public class ProductTypeServiceImpl implements ProductTypeService {
//数据访问层对象
@Autowired
ProductTypeMapper productTypeMapper;
@Override
public List getAll() {
return productTypeMapper.selectByExample(new ProductTypeExample());
}}
10.2 通过监听器自动查询并存入全局对象中
【ssm框架项目|ssm项目(商城管理系统)-- 完整】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 typeList = productTypeService.getAll();
//放入全局作用域中
sce.getServletContext().setAttribute("typeList",typeList);
}@Override
public void contextDestroyed(ServletContextEvent sce) {}
}
10.3 前端下拉框显示类别
类别
name="typeId">
11. 上传文件 --ajax异步上传并回显 – springMVC组件 11.1 前端上传图片 文件选择
图片介绍
id="imgName" >
Ajax异步提交事件 – 采用ajaxfileupload.js文件(封装ajax异步上传的功能)
="text/javascript" src="https://www.it610.com/article/${pageContext.request.contextPath }/js/ajaxfileupload.js">="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 = $("
文章图片
id="imgName">
...
总数量
...
//取出全局中的数据,与修改商品的类别id对比,selected="selected"表示选中
类别
name="typeId">
13.4 修改数据 - update方法 业务逻辑层 – ProductInfoService接口添加update方法
//更新商品
int update(ProductInfo info);
业务逻辑层 – ProductInfoServiceImpl实现类实现update
@Override
public int update(ProductInfo info) {
return productInfoMapper.updateByPrimaryKey(info);
}
界面控制层 – ProductInfoAtion中,添加update完成更新
@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";
}
14. ajax批量删除 14.1 前端点击触发
//批量删除
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");
}
});
}
}
}
14.2 在mapper中添加操作语句(复杂操作)
delete from product_info where p_id in
/* 采用foreach来拼接多个数据
* collection="array" 数组类型
* separator="," 每个数值之间的间隔符
* open="(" 开始的字符
* close=")" 结束的字符
*/
#{pid}
14.3 实现删除
@Override
public int deleteBatch(String[] ids) {
return productInfoMapper.deleteBatch(ids);
}
//ajax异步批量删除
@ResponseBody
@RequestMapping(value = "https://www.it610.com/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"批量删除失败!";
}}
推荐阅读
- 项目练习|ssm项目练习-电商平台后台管理系统_1
- 人工智能|数字化转型的交付物是什么()
- 安卓开发|JAVA开发环境搭建-黑马程序员(个人整理版本)
- python|用 Pandas 做 ETL,不要太快
- 大数据|为什么要做数仓分层,不做行吗()
- hive|面试官(hive表有数据,但为什么impala查询不到数据())
- github|内卷把同事逼成了“扫地僧”,把 Github 上所有面试题都整理了一遍~ 足足 24W 字
- 面试|【面试题】Java基础
- JavaWeb开发|Java中的BIO和NIO区别