SSM框架开发-进阶案例

SSM框架整合进阶案例详解

此案例的初衷,是在之前基础案例整合的基础之上,对使用SSM框架开发JavaWeb项目,所做的一个实战演练!

1、数据库设计

  • 管理员表admin

SSM框架开发-进阶案例_第1张图片

SSM框架开发-进阶案例_第2张图片

  • 商品信息表product_info

SSM框架开发-进阶案例_第3张图片

SSM框架开发-进阶案例_第4张图片

  • 商品类型表product_type

SSM框架开发-进阶案例_第5张图片

SSM框架开发-进阶案例_第6张图片

2、配置文件

注意:执行这步操作之前,初始化项目工作已经完成

2.1 导入相关依赖



    5.2.5.RELEASE
    3.5.7
    2.0.6
    1.2.15
    1.6.4
    5.1.2
    2.9.6
    3.0.1
    2.0
    8.0.21
    0.9.5.5
    1.2
    4.12
    1.18.20



    
    
        org.mybatis
        mybatis
        ${mybatis.version}
    
    
        org.mybatis
        mybatis-spring
        ${mybatis.spring.version}
    

    
    
        org.springframework
        spring-webmvc
        ${spring.version}
    
    
        org.springframework
        spring-jdbc
        ${spring.version}
    

    
    
        org.springframework
        spring-context
        ${spring.version}
    
    
        org.springframework
        spring-beans
        ${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}
    

    
        com.github.miemiedev
        mybatis-paginator
        ${mybatis.paginator.version}
    
    
        com.github.pagehelper
        pagehelper
        ${pagehelper.version}
    

    
    
        com.fasterxml.jackson.core
        jackson-databind
        ${jackson.version}
    

    
    
        commons-io
        commons-io
        2.4
    
    
        commons-fileupload
        commons-fileupload
        1.3.1
    

    
        org.json
        json
        20170516
    

    
        javax.servlet
        javax.servlet-api
        ${servlet-api.version}
    

    
        javax.servlet
        jsp-api
        ${jsp-api.version}
    
    
    
        jstl
        jstl
        ${jstl.version}
    
    
    
        mysql
        mysql-connector-java
        ${mysql.version}
    

    
    
        com.mchange
        c3p0
        ${c3p0.version}
    

    
    
        junit
        junit
        ${junit.version}
    

    
        org.projectlombok
        lombok
        ${lombok.version}
    






    
        
            src/main/resources
            
                **/*.properties
                **/*.xml
            
            false
        
        
            src/main/java
            
                **/*.properties
                **/*.xml
            
            false
        
    
    
    
        
            org.apache.maven.plugins
            maven-compiler-plugin
            
                1.8
                1.8
                UTF-8
            
        
    

接下来在该位置添加如下配置文件

SSM框架开发-进阶案例_第7张图片

2.2 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=mc123456

2.3 mybatis-config.xml





    
        
    
    
    
        
    

2.4 spring-dao.xml

 



    
    


    
    
        
        
        
        

        
        
        
        
        
        
        
        
        

    

    
    
        
        
        
        
        
        
    

    
    
        
    

2.5 spring-service.xml




    
    
    
    
        
    
    
    
        
            
            
            
            
            
            
            
            
            
            
            
            
            
            
        
    
    
    
        
        
    

2.6 spring-mvc.xml




    
    

    
    
        
        
        
        
    

    
    
        
        
        
        
        
    

    
    

2.7 applicationContext.xml




    
    
    

接下来在以下位置,修改web.xml配置文件

2.8 web.xml




    
    
        encodingFilter
        org.springframework.web.filter.CharacterEncodingFilter
        
            encoding
            UTF-8
        
        
            forceRequestEncoding
            true
        
        
            forceResponseEncoding
            true
        
    
    
        encodingFilter
        /*
    

    
    
    
        springmvc
        org.springframework.web.servlet.DispatcherServlet
        
        
            contextConfigLocation
            classpath:spring-mvc.xml
        
        
        1
    
    
    
        springmvc
        *.action
    

    
    
        org.springframework.web.context.ContextLoaderListener
    
    
        contextConfigLocation
        classpath:spring-*.xml
    

    
    
        15
    

3、jsp页面设计

3.1 登录页面

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




	
		
		
		
		
		
		
		
	

	
		
LOGIN
用户名:
密码:
${errmsg}

3.2 首页

SSM框架开发-进阶案例_第8张图片

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



	
		
		
		
		
		
		
		<%----%>
		
	
	
		
		
	

3.3 商品详情页

SSM框架开发-进阶案例_第9张图片

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




    
    
    
    
    
    
    
    
    



商品名称:    商品类型:    价格:-

  全选
<%----%>
商品名 商品介绍 定价(元) 商品图片 商品数量 操作
${p.pName} ${p.pContent} ${p.pPrice} ${p.pNumber}删除--%> <%--   修改

暂时没有符合条件的商品!

4、功能实现

参照下图,创建封装不同功能代码的包

SSM框架开发-进阶案例_第10张图片

所有功能实现的流程可参照下图:

SSM框架开发-进阶案例_第11张图片

说明:

  • 所有功能,不论简单还是复杂,代码编写流程都是一样
  • 对登录功能编写流程做详细介绍,其余增删改查等基本功能参照登录功能编写
  • 密码加密<------>MD5加密
  • 复杂条件下的数据处理
  • 异步图片上传及回显

4.1 登录功能

第一步:在jsp页面的action位置先用#代填,controller层编写完毕后,在将正确路径填入

第二步:编写controller层

访问路径中有.action,是因为在web.xml配置文件中设置了路径拦截

@Controller
@RequestMapping("/admin")
public class AdminController {
    // 切记:在所有的界面层,一定会有业务逻辑层的对象
    // 实现登录判断,并做相应跳转
    //创建业务逻辑层的对象
    @Autowired
    private AdminService adminService;

    @RequestMapping("/login")
    public String login(String name, String pwd, Model model) {
        Admin admin = adminService.login(name, pwd);
        if (admin != null) {    // 登录成功
            model.addAttribute("admin", admin);
            return "main";
        } else { // 登录失败
            model.addAttribute("errmsg", "用户名或密码不正确!");
            return "login";
        }
    }
}

第三步:编写service层接口

public interface AdminService {
    // 完成登录判断
    public Admin login(String name, String pwd);
}

第四步:编写serviceImpl接口实现类

@Service
public class AdminServiceImpl implements AdminService {

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

    @Override
    public Admin login(String name, String pwd) {
        
        // 根据传入的用户名,到DB中查询相应用户对象
        Admin admin = adminMapper.selectByUserName(name);
        if (admin != null) {
            // 如果查询到用户对象,再进行密码的比对,注意密码是密文
            /*分析:
                admin.getaPass() ==> d033e22ae348aeb5660fc2140aec35850c4da997
                pwd ==> admin
                在进行密码对比时,要将传入的pwd进行md5加密,再与数据库中查到的对象的密码进行对比
             */
            if (MD5Util.getMD5(pwd).equals(admin.getaPass())) {
                return admin;
            }
        }
        return null;
    }
}

第五步:编写mapper接口

public interface AdminMapper {
    Admin selectByUserName(String name);
}

第六步:编写mapper.xml文件




  
    
    
    
  
  
  
    a_id, a_name, a_pass
  
  
  
 

4.2 密码加密实现-----MD5加密

  • MD5(message-digest algorithm 5)信息摘要算法
  • 它的长度一般是32位的16进制数字符串(如81dc9bdb52d04dc20036dbd8313ed055)
  • 由于系统密码明文存储容易被黑客盗取
  • 应用:注册时,将密码进行md5加密,存到数据库中,防止可以看到数据库数据的人恶意篡改。
  • 登录时,将密码进行md5加密,与存储在数据库中加密过的密码进行比对
  • md5不可逆,即没有对应的算法,从产生的md5值逆向得到原始数据

在实际的开发中,编写一个加密的公共类即可

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

4.3 复杂条件下的数据处理

4.3.1 复杂条件情况说明:

  • 商品数据列表展示的时候,在获取商品列表信息时,根据商品id(有自增属性)先对商品进行降序排序,这样做可以保证第一条数据的商品id永远是最大的,方便在新增商品时,在数据回显列表中及时查看数据是否添加成功(在select语句的最后添加order by p_id desc)
  • 数据分页显示时,无论是简单条件的分页,还是复杂条件下的分页,最重要且相同的一个步骤还是将查询到的结果集放到PageInfo中(PageInfo pageInfo = new PageInfo<>(list);),让该分页插件自己实现数据结果集的分页显示(返回的是return pageInfo;)
  • 批量删除商品数据(一次删除多条数据信息)
  • 根据商品名称,商品类型,价格区间,页码等条件查询商品的结果集(依旧分页显示)

4.3.2 普通分页

只需要传入起始页码和每页要显示的数据条数

// select * from product_info limit 起始记录数=((当前页-1)*每页的条数),每页取几条
// select* from product_info limit 10,5
@Override
public PageInfo splitPage(int pageNum, int pageSize) {
    // 分页插件使用PageHelper工具类完成分页设置
    PageHelper.startPage(pageNum, pageSize);

    // 进行PageInfo的数据封装
    // 进行有条件的查询操作,必须要创建ProductInfoExample对象
    ProductInfoExample example = new ProductInfoExample();
    //设置排序,按主键降序排序
    // select * from product_info order by p_id desc
    example.setOrderByClause("p_id desc");
    // 设置完排序后,取集合,切记切记:一定在取集合之前,设置PageHelper.startPage(pageNum, pageSize);
    List list = pmapper.selectByExample(example);
    //将查到的集合封装进pageInfo
    PageInfo pageInfo = new PageInfo<>(list);
    return pageInfo;
}

4.3.3 多条件查询获得数据结果集

第一步:多这几个查询条件进行封装,将其转换成可new的对象

public class ProductInfoVo {
    //封装所有页面上的查询条件
    private String pname; // 商品名称
    private Integer typeid; // 商品类型
    private Integer lprice; // 最低价格
    private Integer hprice; // 最高价格
    private Integer page = 1; //设置页码

    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;
    }
}
**第二步:从前端jsp页面传递这几个参数**

这里使用了ajax技术,来传递参数,并将响应结果进行回显

function condition() {
    // 取出查询条件
    var pname = $("#pname").val();
    var typeid = $("#typeid").val();
    var lprice = $("#lprice").val();
    var hprice = $("#hprice").val();
    $.ajax({
    url: "${pageContext.request.contextPath}/prod/ajaxsplit.action",
    type: "post",
    data: {
    "pname": pname,
    "typeid": typeid,
    "lprice": lprice,
    "hprice": hprice
    },
    success: function () {
    // 刷新显示数据的容器
    $("#table").load("http://localhost:8080/admin/product.jsp #table");
    }
    });
}

第三步:在controller中接收参数,并根据其值进行数据查询

页面传递过来的参数自动用ProductInfoVo进行了封装(如果单独想要哪个参数,直接用get方法就可以得到)

直接调用pmapper.selectCondition(vo),该方法返回的数据集合就是多条件查询后的结果集

@Override
public List selectCondition(ProductInfoVo vo) {
    return pmapper.selectCondition(vo);
}

4.3.4 多条件查询接口selectCondition的SQL实现




    
        
        
        
        
        
        
        
        
    

    
        p_id, p_name, p_content, p_price, p_image, p_number, type_id, p_date
    
    
    

4.3.5 多条件查询后数据的分页显示

与普通分页类似,只是起始页码是从前端传递的多条件参数中得到

@Override
public PageInfo splitPageVo(ProductInfoVo vo, int pageSize) {
    //切记切记:在取集合之前,使用分页插件一定要先设置当前页和每页的个数,即PageHelper.startPage()属性
    PageHelper.startPage(vo.getPage(), pageSize);
    //取集合
    List list=pmapper.selectCondition(vo);

    return new PageInfo<>(list);
}

4.3.6 批量删除

第一步:从jsp页面传递参数,这次传递的是一个存放要删除商品id的数组

//批量删除
function deleteBatch(page) {
    // 取出查询条件
    var pname = $("#pname").val();
    var typeid = $("#typeid").val();
    var lprice = $("#lprice").val();
    var hprice = $("#hprice").val();
    //得到所有选中复选框的对象,根据其长度判断是否有选中商品
    var cks = $("input[name='ck']:checked");
    // 如果有选中的商品,则获取其value的值,进行字符串拼接
    if (cks.length == 0) {
    	alert("请选择将要删除的商品!");
    } else {
        var str = "";
        var pid = "";
        if (confirm("您确定要删除" + cks.length + "条商品吗?")) {
            //进行提交商品Id的字符串的拼接
            $.each(cks, function () {
            pid = $(this).val();  // 每一个被选中商品的id
            if (pid != null) { //进行非空判断,避免出错
            	str += pid + ",";
            }
    	});

        $.ajax({
            url: "${pageContext.request.contextPath}/prod/deleteBatch.action",
            data: {
                "pids": str,
                "page": page,
                "pname": pname,
                "typeid": typeid,
                "lprice": lprice,
                "hprice": hprice
            },
            type: "post",
            dataType: "text",
            success: function (msg) {
                alert(msg);//弹删除是否成功
                $("#table").load("http://localhost:8080/admin/product.jsp #table");
                }
            });
        }
    }
}

……

最后一步:mapper.xml中SQL语句编写实现

 



    
        
        
        
        
        
        
        
        
    

    
        p_id, p_name, p_content, p_price, p_image, p_number, type_id, p_date
    
	
    
        delete from product_info where p_id in
        
            #{pid}
        
    

4.4 异步图片上传及回显

4.4.1 再次强调,需要导入依赖



    commons-io
    commons-io
    2.4


    commons-fileupload
    commons-fileupload
    1.3.1

4.4.2 jsp页面

  • form表单的位置
  • fileChange()函数

4.4.3 在controller中做处理

// 异步Ajax文件上传处理
@ResponseBody
@RequestMapping("/ajaxImg")
public Object ajaxImg(MultipartFile pimage, HttpServletRequest request) {
    // 提取生成取文件名UUID+上传图片的后缀.jpg .png
    saveFileName = FileNameUtil.getUUIDFileName() + FileNameUtil.getFileType(pimage.getOriginalFilename());
    //得到项目中图片存储的路径
    try {
        String path = request.getServletContext().getRealPath("/image_big");
        //转存 D:\IntelliJ IDEA\IdeaProjects\MimiSSM\web\image_big\mkxmk.jpg
        pimage.transferTo(new File(path + File.separator + saveFileName));
    } catch (Exception e) {
        e.printStackTrace();
    }
    //为了在客户端显示图片,要将存储的文件名回传下去,由于是自定义的上传插件,所以此处要手工处理JSON
    //返回客户端JSON对象,封装图片的路径,为了在页面实现立即回显
    JSONObject object = new JSONObject();
    object.put("imgurl", saveFileName);
    //切记切记:JSON对象一定要toString()回到客户端
    return object.toString();
}

你可能感兴趣的:(SSM,entity,oauth,javabean,java,wap)