【springMVC】高级部分

2023-09-18 20:25:57

拦截器

1 拦截器( Interceptor)

  • 是一种动态拦截方法调用的机制
# 作用:
	1. 在指定的方法调用前后执行预先设定后的的代码
	2. 阻止原始方法的执行

# 核心原理: 
	AOP思想
# 拦截器链:
	多个拦截器按照一定的顺序,对原始被调用功能进行增强  

2 拦截器使用步骤

1 实现HandlerInterceptor接口

/**
 *  三个方法的运行顺序为    preHandle -> postHandle -> afterCompletion
 *  如果preHandle返回值为false,三个方法仅运行preHandle
 */
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("前置运行----a1");
        //返回值为false将拦截原始处理器的运行
        //如果配置多拦截器,返回值为false将终止当前拦截器后面配置的拦截器的运行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("后置运行----b1");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("完成运行----c1");
    }
}

2 配置拦截器

  <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/m8"/>
            <bean class="com.xinzhi.intercepter.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

3 拦截器配置项

<mvc:interceptors>
    <!--开启具体的拦截器的使用,可以配置多个-->
    <mvc:interceptor>
        <!--设置拦截器的拦截路径,支持*通配-->
        <!--/**         表示拦截所有映射-->
        <!--/*          表示拦截所有/开头的映射-->
        <!--/user/*     表示拦截所有/user/开头的映射-->
        <!--/user/add*  表示拦截所有/user/开头,且具体映射名称以add开头的映射-->
        <!--/user/*All  表示拦截所有/user/开头,且具体映射名称以All结尾的映射-->
        <mvc:mapping path="/*"/>
        <mvc:mapping path="/**"/>
        <mvc:mapping path="/handleRun*"/>
        <!--设置拦截排除的路径,配置/**或/*,达到快速配置的目的-->
        <mvc:exclude-mapping path="/b*"/>
        <!--指定具体的拦截器类-->
        <bean class="MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

4 拦截器的使用场景

1)日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。

2)权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;

3)性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);

5 拦截器登录案例

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        String uri = request.getRequestURI();
        if(uri.equal("/login")){
            return true;
        }
        HttpSession session = request.getSession();
        Object user = session.getAttribute("USER_SESSION");
        if(user!=null){
            return true;
        }
        request.setAttribute("msg","未登陆状态");
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
        return false;
    }

<mvc:interceptors>
    	<mvc:interceptor>
        	<mvc:mapping path="/**" />
        	<bean class="com.soft.interceptor.LoginInterceptor" />
    	</mvc:interceptor>
</mvc:interceptors>	

7 文件上传

1 导入maven依赖

commons-fileupload commons-fileupload 1.4

2 前端页面

<form action="/fileupload" method="post" enctype="multipart/form-data">
    上传LOGO: <input type="file" name="file"/><br/>
    <input type="submit" value="上传"/>
</form>

3 配置多媒体解析器

<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
package com.xinzhi.controller;

import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.UUID;

@Controller
public class FileUploadController {

    /**
     * 上传页面跳转
     * @return
     */
    @RequestMapping(value = "/upload",method = RequestMethod.GET)
    public String upload(){
        return "fileUpload";
    }

    /**
     * 下载页面跳转
     * @return
     */
    @RequestMapping(value = "/down",method = RequestMethod.GET)
    public String down(){
        return "download";
    }

    /**
     * 上传逻辑
     * @param uploadfile 上传的文件数组
     * @return
     */
    @RequestMapping(value = "/fileUpload",method = RequestMethod.POST)
    public String uploadFile(MultipartFile[] uploadfile){
        for (MultipartFile file : uploadfile) {
            //获取文件名称
            String filename = file.getOriginalFilename();
            //存在服务器上名称的修改
            filename = UUID.randomUUID()+"_"+filename;
            // 定义服务器上的存储路径
            String dirPath = "F:/file/";
            File filePath = new File(dirPath);
            // 判断路径是否存在,不存在就创建
            if(!filePath.exists()){
                filePath.mkdir();
            }
            try {
                // 文件上传的核心
                file.transferTo(new File(dirPath+filename));
            } catch (IOException e) {
                e.printStackTrace();
                return "error";
            }
        }
        return "success";
    }


    @RequestMapping("/download")
    public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,String filename) throws UnsupportedEncodingException {
        //指定文件下载地址的目录   filename -> 美女.jpg
        String dirPath = "D:/file";
        // 指定下载的文件名称
        File file = new File(dirPath + File.separator + filename);
        HttpHeaders headers = new HttpHeaders();
        // 解决不同浏览器之间乱码问题
        filename = getFilename(request, filename);
        //告诉浏览器,打开方式(附件)
        headers.setContentDispositionFormData("attachment",filename);
        //以二进制字节流的方式下载
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        try {
            return new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity<>(e.getMessage().getBytes(), HttpStatus.EXPECTATION_FAILED);
        }
    }

    /**
     * 不同浏览器的版本兼容
     * @param request
     * @param filename
     * @return
     * @throws UnsupportedEncodingException
     */
    private String getFilename(HttpServletRequest request,String filename) throws UnsupportedEncodingException {
        //判断是不是IE内核的关键字
        String[] IEBrowerKeyWords = {"MSIE","Trident","Edge"};
        String keywords = request.getHeader("User-Agent");
        for (String keyWord : IEBrowerKeyWords) {
            if(keywords.contains(keyWord)){  //判断是否为IE浏览器
                return URLEncoder.encode(filename,"UTF-8");
            }
        }
        // 其他浏览器编码格式ISO-8859-1
        return new String(filename.getBytes("UTF-8"),"ISO-8859-1");
    }
}

更多推荐

Vue的进阶使用--模板语法应用

目录前言一.Vue的基础语法1.插值1.1文本插值1.2HTML插值1.3属性插值1.4Vue演示三元条件运算2指令2.1if&&else指令(v-if/v-else-if/v-else)2.2v-for指令2.3v-on指令(动态参数)2.4知识点补充之v-if与v-show的区别3.过滤器3.1局部过滤器3.2全局

什么是领域驱动设计(DDD): 领域驱动设计和实践如何做

引言软件系统面向对象的设计思想可谓历史悠久,20世纪70年代的Smalltalk可以说是面向对象语言的经典,直到今天我们依然将这门语言视为面向对象语言的基础。随着编程语言和技术的发展,各种语言特性层出不穷,面向对象是大部分语言的一个基本特性,像C++、Java、C#这样的静态语言,Ruby、Python这样的动态语言都

关于物联网技术的水电厂电气开关柜测温系统设计应用

摘要:针对洪江水电厂电气开关柜温度无法在线监测的问题,本文提出了一种基于物联网技术的水电厂开关柜温度测量系统。该系统部署简单高效,能快速采集设备温度数据,通过4G或者WiFi无线信号将数据送入物联网云平台,实现开关柜温度远程实时监测,为开关柜状态诊断提供决策依据。此外,该系统解决了人工巡检成本高、数据及时率低、作业风险

PostgreSQL如何支持PL/Python过程语言

瀚高数据库目录环境文档用途详细信息环境系统平台:Linuxx86-64RedHatEnterpriseLinux7版本:10.4文档用途本文档主要介绍PostgreSQL如何支持PL/Python过程语言,如何创建plpython扩展。详细信息一、PostgreSQL支持python语言的前提条件1、本地必须安装pyt

Twitter优化秘籍:置顶、列表、受众增长

在Twitter上,将你的一条推送文置顶到个人数据顶部是提高可见性和吸引关注者的绝佳方式。无论你是个人用户还是企业,此功能都可以让你的重要信息常驻在众人眼前,即使你发布了新的推文。接下来,我们将分享一些优化建议,帮助你合理地使用此功能。1、置顶要点:你可以使用置顶功能来展示人们需要看到的重要信息,比如:限时促销:如果您

C/C++内存管理

文章目录1.C/C++内存分布2.C语言中动态内存管理方式:malloc/calloc/realloc/free3.C++内存管理方式new/delete3.1new/delete操作内置类型3.2new/delete操作自定义类型4.operatornew和operatordelete函数(重点)4.1底层原理5.m

探讨大型公共建筑能耗监测与信息管理系统研究及应用

安科瑞华楠摘要:文章通过阐述大型公共建筑能耗现状,突出大型公共建筑实施节能监管的必要性,并在系统总结运用技术手段实施建筑能耗监测的基础上,介绍了江苏省建筑能耗监测系统研究过程中的技术创新和应用情况。关键词:公共建筑;建筑能耗;监测;节能0前言为随着我国工业化和城市化进程的加速,高速发展的建筑业以及不断扩大的建筑规模使得

短视频视频制作矩阵剪辑系统---源码,源代码独立搭建

短视频矩阵系统源码开发源代码搭建1,短视频矩阵系统需要的技术和知识1..数据库技术:抖音SEO系统需要处理海量的数据,需要使用高效、安全的数据库技术,如MySQL、MongoDB等,进行数据存储和管理。2.分布式系统架构:抖音SEO系统需要具备高可靠性、高性能、高容错性等特点,需要使用分布式系统架构进行设计和搭建。3.

【C++】C++11——可变参数模板和emplace

可变参数模板的定义方式可变参数模板的传值计算可变参数模板参数个数参数包展开方式递归展开参数包逗号表达式展开参数包emplace插入可变参数模板是C++11新增的最强大的特性之一,它对参数高度泛化,能够让我们创建可以接受可变参数的函数模板和类模板。在C++11之前,类模板和函数模板中只能包含固定数量的模板参数,可变模板参

创龙TL6678F开发板: 实现FPGA与DSP之间 SRIO(3.125Gbps, 4x)通信

创龙TL6678F开发板官方Demo:SRIO_AD9613实现了FPGA和DSP之间的SRIO通信,SRIO的速率为5Gbps.在FPGA端,srio_gen_2模块的参考时钟为125MHz.而Demo:udp_10g_echo实现了10G以太网通信,ten_gig_eth_pcs_pma模块的参考时钟为156.25

软件测试/测试开发丨​利用ChatGPT编写测试用例

点此获取更多相关资料简介测试用例是测试人员的核心工作内容,是测试人员思想的“实现类”,其充分体现了测试的思路,可以为后续的测试行为提供指导,是测试人员了解业务的重要根据和质量之根本。如果测试用例设计得不完成,出现了遗漏,那么通常是会出现大家不想看到的后果,如漏测、线上Bug不断等。——引用自《饿了么质量体系搭建实战》一

热文推荐