SSM整合2(把数据库中的商品信息显示到页面上并进行简单的增删改查、文件上传、Oscache页面缓存的使用、FreeMarker的使用、SpringMVC拦截器的使用)

SSM整合2

1. 显示商品信息(简单的增删改查)

  • 在前一天SSM整合的基础上,搬砖
  1. 在ItemsController中写一个list方法,用于将数据库中的商品信息显示到页面上
    在这里插入图片描述
	@RequestMapping("list")
    public String list(Model model){
    
    
        //1.查数据
        List<Items> itemsList = itemsService.findAll();
        //2.存数据
        model.addAttribute("itemsList",itemsList);
        return "/items/itemsList";
    }
  1. 在itemsList.jsp中取出(从数据库中取出)保存到作用域中的数据,显示到页面上
    在这里插入图片描述
<%--
  Created by IntelliJ IDEA.
  User: shuyy
  Date: 2020/10/10
  Time: 19:51
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>商品列表</title>
</head>
<body>
<table border="1">
    <caption>商品列表</caption>
    <tr align="center">
        <td>名称</td>
        <td>价格</td>
        <td>描述</td>
        <td>图片</td>
        <td>创建时间</td>
        <td colspan="2">操作</td>
    </tr>
<c:forEach items="${itemsList}" var="items">
    <tr>
        <td>${items.name}</td>
        <td>${items.price}</td>
        <td>${items.detail}</td>
        <td>${items.pic}</td>
        <td>${items.createtime}</td>
        <td><a href="${pageContext.request.contextPath}/items/delete.do?id=${items.id}">删除</a></td>
        &nbsp;<td><a href="${pageContext.request.contextPath}/items/edit.do?id=${items.id}">修改</a></td>
    </tr>
</c:forEach>
</table>
</body>
</html>

  1. 效果
    在这里插入图片描述

2. 删除商品

  • 写一个删除方法delete
    在这里插入图片描述
  • 根据传回来的id,删除数据库中的数据,删除完后返回到商品信息显示页面
	@RequestMapping("delete")
    public String delete(Integer id){
    
    
        //根据id删除
        itemsService.deleteById(id);
        //转发到同一个方法的list.do
        return "forward:list.do";
    }
  • 上面的写法点击删除会直接删除掉信息,不是很友好,下面添加一下提示
    在这里插入图片描述
<a href="javascript:if(window.confirm('是否删除?')){window.location.href='${pageContext.request.contextPath}/items/delete.do?id=${items.id}'}">删除</a>
  • 效果
    在这里插入图片描述
    在这里插入图片描述

3. 显示修改商品信息页面

  • 写一个edit方法,点击修改后,进入修改信息页面
    在这里插入图片描述
	@RequestMapping("edit")
    public String edit(Integer id,Model model){
    
    
        System.out.println("id:"+id);
        //根据id查找商品
        Items items = itemsService.findById(id);
        if (items != null){
    
    
          model.addAttribute("items",items);
        }
        return "/items/itemsEdit";
    }
  • 商品信息详情页面,itemsEdit.jsp
    在这里插入图片描述
<%--
  Created by IntelliJ IDEA.
  User: shuyy
  Date: 2020/10/10
  Time: 19:51
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>编辑商品</title>
</head>
<body>
编辑商品<br>
<form action="${pageContext.request.contextPath}/items/update.do" method="post">
<table border="1">
    <tr>
        <td>名称</td>
        <td><input type="text" name="name" value="${items.name}">
            <input type="hidden" name="id" value="${items.id}"></td>
    </tr>
    <tr>
        <td>价格</td>
        <td><input type="text" name="price" value="${items.price}"></td>
    </tr>
    <tr>
        <td>描述</td>
        <td><textarea cols="20" rows="5" name="detail">${items.detail}</textarea></td>
    </tr>
    <tr>
        <td>图片</td>
        <td>
            <img src="${items.pic}">
            <input type="file">
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <input type="submit" value="更新">
        </td>
    </tr>
</table>
</form>
</body>
</html>

  • 点击修改,效果
    在这里插入图片描述

4. 更新商品信息

  • 写一个更新方法update
    在这里插入图片描述
  • 发现这样写,直接点击更新会报错,因为没有设置时间
    在这里插入图片描述
  • 更新操作中并没有涉及时间
    在这里插入图片描述
  • 所以需要配置一下更新方法(还发现出现了中文乱码问题)
    在这里插入图片描述
	@RequestMapping("update")
    public String update(Items items){
    
    
        System.out.println(items);
        //时间不能为空,所以要设置一下
        items.setCreatetime(new Date());
        itemsService.saveOrUpdate(items);
        //转发到同一个方法的list.do
        return "forward:list.do";
    }
  • 在web.xml中配置编码过滤器解决乱码问题
    在这里插入图片描述
<!-- 配置编码过滤器  -->
    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  • 测试更新效果
    在这里插入图片描述
  • 发现描述没有变化
    在这里插入图片描述
  • 这是由于sql语句所致,查看一下逆向工程生成的sql
    在这里插入图片描述
  • 我们使用的方法没有为我们设置描述
    在这里插入图片描述
  • 需要换种方法
    在这里插入图片描述
    在这里插入图片描述
  • 测试效果
    在这里插入图片描述
  • 成功
    在这里插入图片描述
  • 后台数据也不中文乱码了
    在这里插入图片描述

5. 文件上传(商品图片设置)

在这里插入图片描述

  1. 导入以下jar包(在spring依赖包中的org.apache.commons包下)
    在这里插入图片描述
  2. 在SpringMVC中设置文件上传大小
    在这里插入图片描述
	<!--文件上传,限制文件上传大小
    注意:一定要配置id,id的名字是固定的:multipartResolver
    -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--单位为字节-->
        <property name="maxUploadSize" value="10240000"></property>
    </bean>
  1. JSP编写(导入js,使用ajax来提交带文件的表单)
    在这里插入图片描述
  • 设置一个隐藏的图片,用于在修改的时候显示
    在这里插入图片描述
<%--
  Created by IntelliJ IDEA.
  User: shuyy
  Date: 2020/10/10
  Time: 19:51
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>编辑商品</title>
    <script src="${pageContext.request.contextPath}/js/jquery.js"></script>
    <script src="${pageContext.request.contextPath}/js/jquery.form.js"></script>
    <script>
        function submitImage() {
     
     
            /*这里不使用enctype,使用ajax来提交*/
            alert("提交图片到后台");

            var url = '${pageContext.request.contextPath}/upload/itemsPic.do';
            //封装请求数据
            var options = {
     
     
                type:'post',
                dataType:'json',
                //追加数据
                data:{
     
     
                    /*fileName:'itemsPic1'*/
                    username:'shu'
                },
                url:url,
                success:function (respData) {
     
     
                    console.log(respData.imgUrl);
                    //将json字符串转成json对象
                    //var jsonObj = $.parseJSON(respData);
                    $('#pic').attr('src',respData.imgUrl)
                    $('#hiddenPic').val(respData.imgUrl)//设置隐藏字段
                }
            }
            //提交表单(实现有文件的提交表单)
            $('#itemsForm').ajaxSubmit(options)
        }
    </script>
</head>
<body>
编辑商品<br>
<form id="itemsForm" action="${pageContext.request.contextPath}/items/update.do" method="post" >
<table border="1">
    <tr>
        <td>名称</td>
        <td><input type="text" name="name" value="${items.name}">
            <input type="hidden" name="id" value="${items.id}"></td>
    </tr>
    <tr>
        <td>价格</td>
        <td><input type="text" name="price" value="${items.price}"></td>
    </tr>
    <tr>
        <td>描述</td>
        <td><textarea cols="20" rows="5" name="detail">${items.detail}</textarea></td>
    </tr>
    <tr>
        <td>图片</td>
        <td>
            <img id="pic" src="${items.pic}" width="80px" height="80px">
            <input type="file" name="itemsPic1" onchange="submitImage();">
            <input type="hidden" name="pic" id="hiddenPic" value="${items.pic}">
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <input type="submit" value="更新">
        </td>
    </tr>
</table>
</form>
</body>
</html>

  1. 后台编写
    在这里插入图片描述
  • 可以使用replace把uuid中的-去除
    在这里插入图片描述
package com.it.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.UUID;

/**
 * @ClassName UploadController
 * @Author shuyy
 * @Date 2020/10/11 14:02
 **/
@Controller
@RequestMapping("upload")
public class UploadController {
    
    

    @RequestMapping("itemsPic")
    public void itemsPic(HttpServletRequest request,PrintWriter printWriter) throws IOException {
    
    

        MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
        //1.获取图片
        MultipartFile multiFile = multiRequest.getFile("itemsPic1");

        //2.设置图片保存的文件夹路径
        String uploadFolder = request.getServletContext().getRealPath("/upload");
        System.out.println("uploadFolder:"+uploadFolder);
        File uploadFolderFile = new File(uploadFolder);
        if (!uploadFolderFile.exists()){
    
    
            uploadFolderFile.mkdirs();
        }
        //格式化文件名(也可以使用日期加上随机数来生成图片名)
        /*SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String saveName = sdf.format(new Date());
        Random rd = new Random();
        for(int i=0;i<3;i++){
            saveName += rd.nextInt(10);//添加三个随机数
        }*/

        //3.把图片放进上面设置好的路径中
        //获取图片后缀
        String suffix = multiFile.getOriginalFilename().split("\\.")[1];
        //随机生成图片名(使用uuid,图片名会比较长)
        String fileName = UUID.randomUUID().toString()+"."+suffix;
        //图片的全路径
        String totalPath = uploadFolder+"\\"+fileName;
        System.out.println("totalPath:"+totalPath);
        //将图片拷贝到指定位置
        FileCopyUtils.copy(multiFile.getInputStream(),new FileOutputStream(new File(totalPath)));

        //4.返回一个相对路径 相对路径和全路径
        String imgURL = "http://localhost:8080/ssm_war_exploded/upload/" + fileName;
        String respJson = "{\"imgUrl\":\"" + imgURL+"\"}";

        printWriter.write(respJson);
    }
}

  • 在itemsList.jsp里设置一下图片显示
    在这里插入图片描述
  1. 效果
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 也可以使用日期加三个随机数生成图片名,这样的名字短一点
    在这里插入图片描述

6. Oscache页面缓存整合ssm项目

cache.memory=false
cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
cache.path=D:\\test
  • 在src下配置log4j的配置文件log4j.properties,打印一些日志和加载信息
    在这里插入图片描述
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
  • 在web.xml中配置页面缓存
    在这里插入图片描述
  • 刷新缓存时间3600秒,作用域application都能访问到,/items/*下的所有页面都缓存,也可以设置为/items/list.do只缓存商品列表即可
	<!--配置页面缓存-->
    <filter>
        <filter-name>oscache</filter-name>	<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>
        <init-param>
            <param-name>time</param-name>
            <param-value>3600</param-value>
        </init-param>
        <init-param>
            <param-name>scope</param-name>
            <param-value>application</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>oscache</filter-name>
        <url-pattern>/items/*</url-pattern>
    </filter-mapping>

在这里插入图片描述

7. SpringMVC整合freemarker

  • FreeMarker是一个模板引擎,一个基于模板生成文本输出(HTML网页,电子邮件,配置文件,源代码等)的通用工具,使用纯Java编写
  • FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序
  • 虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据
  • freemarker官网:https://freemarker.apache.org/.
  • 模板引擎框架还有thymeleaf:https://www.thymeleaf.org.
  1. 导入jar包(freemarker的jar在spring依赖包下)
    在这里插入图片描述
  2. 在SpringMVC中配置freemarker
    在这里插入图片描述
	<!--配置freemarker -->
    <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/WEB-INF/views" />
        <property name="defaultEncoding" value="UTF-8"></property>
    </bean>
    <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="contentType" value="text/html;charset=utf-8"/>
        <property name="suffix" value=".ftl" />
    </bean>
  1. 写一个hello.ftl模板体验一下(先创建个hello.html再重命名为hello.ftl)
    在这里插入图片描述
  2. 在itemsController中写一个简单的方法,测试一下(数据通过模板引擎生成)
    在这里插入图片描述
  3. 将itemsList.jsp改成itemsList.ftl
    在这里插入图片描述
  • 注意项目名的赋值
    在这里插入图片描述
  • 日期还可以配置成${item.createtime?string(“yyyy-MM-dd HH:mm:ss zzzz”)}
    在这里插入图片描述
<#--<%--
  Created by IntelliJ IDEA.
  User: shuyy
  Date: 2020/10/10
  Time: 19:51
  To change this template use File | Settings | File Templates.
--%>-->
<#--<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>--><#--无需标签-->
<#assign projectName = "ssm" />
<html>
<head>
    <title>商品列表</title>
</head>
<body>
<table border="1">
    <caption>商品列表by freemarker</caption>
    <tr align="center">
        <td>名称</td>
        <td>价格</td>
        <td>描述</td>
        <td>图片</td>
        <td>创建时间</td>
        <td colspan="2">操作</td>
    </tr>
<#--<c:forEach items="${itemsList}" var="items">-->
    <#list itemsList as items><#--遍历-->
    <tr>
        <td>${items.name}</td>
        <td>${items.price}</td>
        <td>${items.detail}</td>
        <td><img src="${items.pic}" width="80px" height="80px"></td>
        <td>${items.createtime?datetime}</td>
        <td><a href="javascript:if(window.confirm('是否删除?')){
        window.location.href='${projectName}/items/delete.do?id=${items.id}'
        }">删除</a></td>
        &nbsp;<td><a href="${projectName}/items/edit.do?id=${items.id}">修改</a></td>
    </tr>
    </#list>
<#--</c:forEach>-->
</table>
</body>
</html>
<#--<a href="${pageContext.request.contextPath}/items/delete.do?id=${items.id}">删除</a>-->

  1. 效果
    在这里插入图片描述
  • 由于编辑页面没有修改点击会报错
    在这里插入图片描述

8. 配置SpringMVC的登录拦截器

  • Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理
  1. 在WEB-INF下的views中写一个简单的登录页面login.jsp
    在这里插入图片描述
<form action="${pageContext.request.contextPath}/login.do" method="post">
<table border="1">
    <tr>
        <td>用户名</td>
        <td><input type="text" name="username"></td>
    </tr>
    <tr>
        <td>密码</td>
        <td><input type="text" name="password"></td>
    </tr>
    <tr>
        <td><input type="submit" value="登录"></td>
    </tr>
</table>
</form>
  1. 写一个登录控制器LoginController
    在这里插入图片描述
@Controller
public class LoginController {
    
    

    @RequestMapping("login")
    public String login(HttpServletRequest request,String username,String password){
    
    
        //这里原本要查询数据库,现在就先不查询了
        if ("shu".equals(username) && "123".equals(password)){
    
    
            //登录成功把user保存到session中
            request.getSession().setAttribute("user",username);
            //登录成功,直接返回商品列表吧,也可以设置返回其它页面
            return "forward:items/list.do";
        }
        //登录失败,返回login登录页面
        return "login";
    }
}
  • 这里返回页面没有写斜杠的原因是,在SpringMVC中配置拼接时加了斜杠
    在这里插入图片描述
  1. 写一个登录拦截器,放行一些方法和一些逻辑配置
    在这里插入图片描述
package com.it.web.controller.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @ClassName LoginInterceptor
 * @Author shuyy
 * @Date 2020/10/12 
 **/
public class LoginInterceptor implements HandlerInterceptor {
    
    

    //controller前,调用此方法
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
    
    

        System.out.println("预处理...");
        //在此处可以自己设置页面拦截(登录、注册等操作页面无需拦截)

        //路径中包含login.do是登录页面,放行
        if (request.getRequestURI().indexOf("login.do") >= 0){
    
    
            return true;
        }
        //如果用户已经登录,当然也放行(所以之前在session中存储user,除了表示已经登录,还有其它很多使用)
        if (request.getSession().getAttribute("user") != null){
    
    
            return true;
        }
        //用户没有登录而要访问已有的页面,就让它跳转到登录页面(如果用户访问没有的页面会报404错误,也无需拦截了)
        //转发到登录页面
        request.getRequestDispatcher("/WEB-INF/views/login.jsp").forward(request,response);
        return false;
    }

    //controller执行后,但未返回视图返回前,调用此方法
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    
    
        System.out.println("未返回视图前,后处理...");
    }

    //controller执行后,且视图返回后,调用此方法
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    
    
        System.out.println("返回视图前,后处理...");
    }
}

  1. 在SpringMVC配置文件中配置登录拦截器
    在这里插入图片描述
	<!--配置拦截器-->
    <mvc:interceptors>
        <!--配置登录拦截器-->
        <mvc:interceptor>
            <!--/**要2个*,表示拦截所有请求-->
            <mvc:mapping path="/**"/>
            <bean class="com.it.web.controller.interceptor.LoginInterceptor"></bean>
            <!--这里还可以配置排除,也可以之前手动配置排除一些不拦截-->
            <!--<mvc:exclude-mapping path=""/>-->
        </mvc:interceptor>
        <!--配置其它拦截器,拦截器会顺序执行-->
        <!--<mvc:interceptor>
            <mvc:mapping path=""/>
            <bean class=""></bean>
        </mvc:interceptor>-->
    </mvc:interceptors>
  1. 设置首页为登录页面login.jsp(intellij idea启动javaweb项目后,默认打开的是index.jsp页面,在index.jsp页面中转发到login.jsp中即可)
    在这里插入图片描述
<%--两种方法用其一即可--%>
  <%--<%
    request.getRequestDispatcher("WEB-INF/views/login.jsp").forward(request,response);
  %>--%>
  <%--转发到登录页面--%>
  <jsp:forward page="WEB-INF/views/login.jsp"></jsp:forward>
  1. 效果
    在这里插入图片描述
    在这里插入图片描述
  • 由于已经登录,session中有值,同一个浏览器直接访问items/list.do,能访问到
    在这里插入图片描述
  • 但是换一个浏览器直接访问items/list.do是访问不到的(因为sessionId不同,数据无法共享),会转发到登录页面
    在这里插入图片描述
  • 如果访问的路径,项目中不存在,会直接报错,拦截器不会去拦截(可以考虑自己写404页面)
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43414199/article/details/109005637