【Java框架】SpringMVC(三)——异常处理,拦截器,文件上传,SSM整合

目录

  • 异常处理
    • 解释
    • 局部异常处理
    • 全局异常
  • 拦截器
    • 拦截器介绍
    • 作用:
    • 拦截器和过滤器之间的区别
    • 拦截器执行流程
    • 代码实现
    • 补充
  • 文件上传
    • 依赖
    • 配置MultipartResolver
    • 编写文件上传表单页
    • API
      • MultipartFile
      • File.separator
      • 必须对上传文件进行重命名
      • 代码示例
    • SpringMVC文件上传流程
    • 多文件上传
  • 静态资源加载
    • 1.将静态资源统一放在一个路径下
    • 2.配置静态资源加载
  • SSM整合

异常处理

  • HandlerExceptionResolver
    • resolveException()
  • 局部异常处理
    • 仅能处理指定Controller中的异常
    • @ExceptionHandler

解释

  • Spring MVC 通过HandlerExceptionResolver 处理程序的异常,包括Handler 映射、数据绑定以及目标方法执行时发生的异常。
  • 主要处理Handler 中用@ExceptionHandler 注解定义的方法。
  • ExceptionHandlerMethodResolver 内部若找不到@ExceptionHandler 注解的话, 会找@ControllerAdvice 类的@ExceptionHandler 注解方法, 这样就相当于一个全局异常处理器。

局部异常处理

package cn.smbms.controller;

import cn.smbms.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * @author: zjl
 * @datetime: 2024/4/18
 * @desc:
 */
@RestController
public class HelloController {
    @GetMapping(value = "/index")
    public String index(){
        System.out.println(5/0);//模拟异常
        return "index";
    }

    /**
     * 这里处理ArithmeticException.class,NullPointerException.class类型的异常
     * Exception ex: 生成的异常对象,会传递给ex, 通过ex可以得到相关的异常信息,这里程序员可以加入自己的业务逻辑
     * 这里采用ServletAPI入参,HttpServletRequest、HttpServletResponse、HttpSession...都可以直接用
     */
    @ExceptionHandler({ArithmeticException.class,NullPointerException.class})
    public String localException(Exception ex, HttpServletRequest request){
        System.out.println("局部异常信息是-" + ex.getMessage());
        //如何将异常的信息带到下一个页面.
        request.setAttribute("errorInfo", ex.getMessage());
        return "error";
    }
}

全局异常

  • 对所有异常进行统一处理
  • 配置SimpleMappingExceptionResolver
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <!--<prop key="java.lang.NullPointerException">null.jsp</prop>
                <prop key="java.lang.ClassNotFoundException">class.jsp</prop>
                <prop key="java.sql.SQLException">sql.jsp</prop>
                <prop key="java.io.IOException">io.jsp</prop>-->
                <prop key="java.lang.RuntimeException">error</prop>
            </props>
        </property>
    </bean>

拦截器

在这里插入图片描述

  1. 浏览器发送一个请求会先到Tomcat的web服务器
  2. Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源
  3. 如果是静态资源,会直接到Tomcat的项目部署目录下去直接访问
  4. 如果是动态资源,就需要交给项目的后台代码进行处理
  5. 在找到具体的方法之前,我们可以去配置过滤器(可以配置多个),按照顺序进行执行
  6. 然后进入到到中央处理器(SpringMVC中的内容),SpringMVC会根据配置的规则进行拦截
  7. 如果满足规则,则进行处理,找到其对应的controller类中的方法进行执行,完成后返回结果
  8. 如果不满足规则,则不进行处理

这个时候,如果我们需要在每个Controller方法执行的前后添加业务,具体该如何来实现?——拦截器

拦截器介绍

拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行

作用:

  • 在指定的方法调用前后执行预先设定的代码
  • 阻止原始方法的执行
  • 总结:拦截器就是用来做增强

拦截器和过滤器之间的区别

  • 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
  • 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
    在这里插入图片描述

拦截器执行流程

在这里插入图片描述

代码实现

自定义拦截器类

package cn.smbms.interceptor;

import cn.smbms.tools.Constants;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

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

/**
 * @author: zjl
 * @datetime: 2024/4/12
 * @desc:
 */
public class SysInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Object obj = request.getSession().getAttribute(Constants.USER_SESSION);
        if(obj == null){
            //未登录,重定向到401.jsp
            response.sendRedirect(request.getContextPath() + "/401.jsp");
            return false;
        }
        return true;
    }
}

配置拦截规则

    <!-- 配置拦截器interceptors -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/><!-- 配置拦截规则 -->
            <mvc:exclude-mapping path="/login.do"/><!-- 配置不拦截规则 -->
            <mvc:exclude-mapping path="/logout"/><!-- 配置不拦截规则 -->
            <bean class="cn.smbms.interceptor.SysInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

补充

  • 当配置多个拦截器时,形成拦截器链
  • 拦截器链的运行顺序参照拦截器添加顺序为准
  • 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
  • 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作
    在这里插入图片描述

preHandle:与配置顺序相同,必定运行

postHandle:与配置顺序相反,可能不运行

afterCompletion:与配置顺序相反,可能不运行。

文件上传

  • MultipartResolver接口
    • 用于处理上传请求,将上传请求包装成可以直接获取文件的数据,方便操作
  • 两个实现类
    • StandardServletMultipartResolver
      • 使用了Servlet3.0标准的上传方式
    • CommonsMultipartResolver
      • 使用了Apache的commons-fileupload来完成具体的上传操作

依赖

	<!-- 文件上传 -->
	<dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.8.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.6</version>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>

配置MultipartResolver

    <!-- 配置MultipartResolver,用于上传文件,使用spring的CommonsMultipartResolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="5000000"/><!-- 上传文件大小上限,单位为字节-- >
        <property name="defaultEncoding" value="UTF-8"/><!-- 请求的编码格式,默认为ISO-8859-1,此处设置为UTF-8 -->
    </bean>

编写文件上传表单页

  • method=“POST”
  • enctype=“multipart/form-data”
    • 指定表单内容类型,支持文件上传
  • <input type=“file” name=“a_idPicPath”/>
    • 用来上传文件的file组件

API

MultipartFile

  • Spring MVC会将上传文件绑定到MultipartFile对象中,并通过该对象完成文件的上传操作

File.separator

  • Windows、Linux自适应路径分隔符
  • 低入侵性的代码实现

必须对上传文件进行重命名

原因

  • 原文件名存在中文 乱码问题
  • 原文件名与服务器上已有文件重名 覆盖问题

重新定义上传文件名(保证不重名)

  • 当前系统时间+随机数+“_Personal.jpg”

文件上传成功后,须更新数据库字段(idPicPath),记录上传文件的存储路径

代码示例

	//文件上传
	@RequestMapping(value="/useraddsave.html",method=RequestMethod.POST)
	public String addUserSave(User user,HttpSession session,HttpServletRequest request,
							 @RequestParam(value ="a_idPicPath", required = false) MultipartFile attach){
		String idPicPath = null;
		//判断文件是否为空
		if(!attach.isEmpty()){
			String path = request.getSession().getServletContext().getRealPath("statics"+File.separator+"uploadfiles"); 
			logger.info("uploadFile path ============== > "+path);
			String oldFileName = attach.getOriginalFilename();//原文件名
			logger.info("uploadFile oldFileName ============== > "+oldFileName);
			String prefix=FilenameUtils.getExtension(oldFileName);//原文件后缀     
	        logger.debug("uploadFile prefix============> " + prefix);
			int filesize = 500000;
			logger.debug("uploadFile size============> " + attach.getSize());
	        if(attach.getSize() >  filesize){//上传大小不得超过 500k
            	request.setAttribute("uploadFileError", " * 上传大小不得超过 500k");
	        	return "useradd";
            }else if(prefix.equalsIgnoreCase("jpg") || prefix.equalsIgnoreCase("png") 
            		|| prefix.equalsIgnoreCase("jpeg") || prefix.equalsIgnoreCase("pneg")){//上传图片格式不正确
            	String fileName = System.currentTimeMillis()+RandomUtils.nextInt(1000000)+"_Personal.jpg";  
                logger.debug("new fileName======== " + attach.getName());
                File targetFile = new File(path, fileName);  
                if(!targetFile.exists()){  
                    targetFile.mkdirs();  
                }  
                //保存  
                try {  
                	attach.transferTo(targetFile);  
                } catch (Exception e) {  
                    e.printStackTrace();  
                    request.setAttribute("uploadFileError", " * 上传失败!");
                    return "useradd";
                }  
                idPicPath = path+File.separator+fileName;
            }else{
            	request.setAttribute("uploadFileError", " * 上传图片格式不正确");
            	return "useradd";
            }
		}
		user.setCreatedBy(((User)session.getAttribute(Constants.USER_SESSION)).getId());
		user.setCreationDate(new Date());
		user.setIdPicPath(idPicPath);
		if(userService.add(user)){
			return "redirect:/user/userlist.html";
		}
		return "useradd";
	}

省略service、mapper、sql代码

SpringMVC文件上传流程

在这里插入图片描述

多文件上传

<label for="a_idPicPath">证件照:</label>
<input type="file" name="attachs" id="a_idPicPath"/>
<label for="a_workPicPath">工作证照片:</label>
<input type="file" name="attachs" id="a_workPicPath"/>
  • 控制器-处理方法addUserSave()
    • 修改入参MultipartFile为数组
      • MultipartFile[] attachs
  • MultipartFile[] 数组内存放文件对象顺序
    • 按照form表单的file标签的顺序进行存储
  • 分别更新字段:idPicPath、workPicPath
  • 若入参对象MultipartFile为数组时,该参数前面必须要加上@RequestParam注解,否则会报错
@RequestParam(value="a_idPicPath",required=false) 		    							MultipartFile idPicFile,
@RequestParam(value="a_workPicPath",required=false)
                                            MultipartFile workPicFile)

静态资源加载

1.将静态资源统一放在一个路径下

在这里插入图片描述

2.配置静态资源加载

    <mvc:resources location="/statics/" mapping="/statics/**"></mvc:resources>

SSM整合

  • 1.使用IDEA创建SSM的Maven工程
  • 2.在main目录中创建出来java和resources目录
  • 3.修改pom.xml
    • 3.1导入SSM使用的依赖
    • 3.2导入resources配置
    • 3.3对maven工程重新构建(reload project)
  • 4.创建package目录结构,基本目录命名规则:com.项目名简称
    实体类:entity或pojo
    请求层:controller
    业务层:service
    数据访问层:mapper
    工具类包:utils或tools
    配置类包:config
    过滤器包:filter
    拦截器包:interceptor
  1. 导入SSM使用的配置文件,放在resources目录下
  • 5.1spring配置文件:applicationContext.xml【修改扫描的包路径】
  • 5.2springMvc配置文件:springm-servlet.xml【修改扫描的包路径,去掉没用的配置】
  • 5.3创建mybatis目录,导入mybatis配置文件:mybatis-config.xml【修改实体类别名的包名】
  • 5.4在mybatis目录下创建mapper目录
  • 5.5将写SQL的mapper.xml导入进来,修改为对应实体类的mapper.xml【修改namespace的路径】
  • 5.6数据库配置文件:database.properties【修改数据库连接信息】
  • 5.7日志配置文件:log4j.properties
  • 5.8web.xml配置文件:修改启动页“welcome-file”、引入spring、springmvc、过滤器的配置
  • 5.9注意:修改配置文件中的自定义配置(包名、路径名等)
  • 6.编写java代码
    pojo——controller——service——mapper——mapper.xml
  • 7.编写前端页面
    • 将前端页面统一放在一个目录下(jsp),以便配置视图解析器,在请求层可以直接使用逻辑视图名。
  • 8.编写/导入静态资源
    • 图片、音频、视频、样式、js、插件等等
    • 注意:将静态资源统一放在webapp/statics下
    • 若没有statics目录需要手动创建。
  • 9.在springm-servlet.xml中配置静态资源访问,否则无法使用静态资源
  • 10.在编写完请求层、业务逻辑层、以及SQL后,可以进行功能测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/572326.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

你知道吗?PCBA产品上市前还需要进行老化测试?

在PCBA加工过程中&#xff0c;电子工程师可能发现明明PCBA板出货时各项功能指标正常&#xff0c;但使用一段时间&#xff0c;就莫名其妙出现各种不良问题&#xff0c;最后返场维修&#xff0c;那么这是为什么&#xff1f; 首先&#xff0c;这些原因&#xff0c;十有八九可能是P…

谷歌开发者账号关联被封?解封申诉指南来了!

相信大部分在谷歌上架应用的开发者&#xff0c;已经被谷歌封号封麻了。且不少开发者普遍认为&#xff0c;一旦开发者账号被封禁&#xff0c;想要成功申诉回来的难度极大。 特别是那些因为涉及“高风险”滥用模式行为关联被封的账号&#xff0c;更是不可能申诉成功。但事实上&am…

再谈C语言——理解指针(五)(完结篇)

数组名的理解 在上⼀个章节我们在使⽤指针访问数组的内容时&#xff0c;有这样的代码&#xff1a; int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0]; 这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址&#xff0c;但是其实数组名本来就是地址&#xf…

【产品经理修炼之道】- 将用户需求转化为研发需求

每当接到一个用户需求&#xff0c;产品经理头疼的事情之一&#xff0c;可能就是如何把用户需求转化成研发需求。怎么理解二者的区别&#xff0c;并成功地将需求转化呢&#xff1f;这篇文章里&#xff0c;作者做了分享与总结&#xff0c;一起来看一下。 产品经理与研发人员的博弈…

【图像分割】光流生成标签(matlab)

文章目录 1. 框架2. opticalFlow_label3. 光流 1. 框架 2. opticalFlow_label close all; clear; clc; % 使用光流进行标签的生成 %% 视频帧的读取 npy_data readNPY(train.npy);%% 提取标签的坐标 first_label squeeze(npy_data(2,1,:,:)); h fspecial("gaussian&quo…

C语言自定义类型【结构体】

结构体的概念 结构是一些值的集合&#xff0c;这些值被称为成员变量。结构的每个成员可以是不同类型的变量。 1.结构体的声明 1.1普通声明 我们假设要创建一本书的类型&#xff0c;那我们需要书名&#xff0c;作者&#xff0c;价格&#xff0c;书的ID 代码如下&#xff1a;…

第十五届蓝桥杯省赛第二场C/C++B组A题【进制】题解(AC)

解题思路 按照题意进行模拟&#xff0c;计算 x x x 的 b b b 进制过程中&#xff0c;若出现余数大于 9 9 9&#xff0c;则说明 x x x 的 b b b 进制一定要用字母进行表示。 #include <iostream> #include <cstring> #include <algorithm> #include &l…

vue3推荐算法

Vue 3 推荐算法主要指的是在 Vue 3 框架中实现的或者适用于 Vue 3 的算法库或组件库。Vue 3 由于其优秀的设计和性能&#xff0c;被广泛应用于构建各种类型的应用程序&#xff0c;包括需要复杂算法支持的项目。以下是一些在 Vue 3 中可能会用到的推荐算法资源&#xff1a; Vue-…

啊? 又要洗数据啦!! 还是两个key决定一个表! 二维Map学习,基于guava的HashBasedTable

一个洗数据的需求&#xff0c;表设计的外建不能判断某一个数据源&#xff0c;还要根据tyoe来进行判断才可以。 那此时呆逼的查发能实现但不够优雅&#xff0c;于是乎想到了二维数组&#xff0c;查了下资料有相关的实现给大家分享下&#xff01;&#xff01; 背景 表设计如下&a…

美易官方:AI热潮“熄火”了?Meta Q1财报较差

近期&#xff0c;随着Meta&#xff08;前Facebook&#xff09;发布了其2023年第一季度的财报&#xff0c;一场科技股的震荡在美股市场上演。曾经风光无限的AI热潮似乎出现了“熄火”的迹象&#xff0c;引发了市场的广泛关注和讨论。 Cresset Wealth Advisors首席投资官Jack Abl…

libVLC 专栏介绍

本专栏主要界面libVLC的使用&#xff0c;详细介绍了相关用法&#xff0c;使用Qt作为显示界面&#xff0c;不仅可以了解Qt的使用&#xff0c;QSS的美化&#xff0c;更能够熟悉libVLC核心接口的使用&#xff0c;最后打造一款属于自己的精美播放器。 每一节都有单独的源码供查看。…

CSS @media 媒体查询全解:打造极致跨平台页面的动态户体体验

随着互联网设备的多样化和用户浏览习惯的变化&#xff0c;现代网页设计越来越注重提供跨平台、跨设备的无缝用户体验。CSS媒体查询media在此背景下扮演着至关重要的角色&#xff0c;它赋予网页设计者精准控制网页样式的能力&#xff0c;使之能随设备环境变化而动态调整&#xf…

内存管理下及模板初阶

嗨喽&#xff0c;今天阿鑫给大家带来内存管理下以及模板初阶的博客&#xff0c;下面让我们开始今天的学习吧&#xff01; 内存管理下及模板初阶 new和delete的实现原理定位new表达式(placement-new)常见面试题泛型编程函数模板类模板 1. new和delete的实现原理 1.1 内置类型…

短链接推荐:一个可以监测用户行为的“营销神器”

客户对我的推广有兴趣吗&#xff1f;他喜欢我的产品吗&#xff1f;他打开了我的营销信息吗&#xff1f;这三个问题相信每一位推广者都遇到过。接下来&#xff0c;就将给大家介绍一位大聪明——它能帮你监测每一位用户的行为&#xff0c;让你分分秒秒掌握用户的心理&#xff01;…

consul服务注册与发现、服务配置与刷新

为什么要用服务注册&#xff1f;为什么要用consul不用eureka&#xff1f; 举个栗子&#xff1a; 微服务当中存在多个服务模块&#xff0c;每个服务模块的ip端口在每套环境是不一致的&#xff0c;开发切换环境部署时&#xff0c;如果漏了一个配置忘记改动&#xff0c;将是一个很…

黑龙江—等保测评三级安全设计思路

需求分析 6.1、 系统现状 6.2、 现有措施 目前&#xff0c;信息系统已经采取了下述的安全措施&#xff1a; 1、在物理层面上&#xff0c; 2、在网络层面上&#xff0c; 3、在系统层面上&#xff0c; 4、在应用层面上&#xff0c; 5、在管理层面上&#xff0c; 6.…

数码摄影色彩构成,数码相机色彩管理

一、资料描述 本套摄影色彩资料&#xff0c;大小58.54M&#xff0c;共有6个文件。 二、资料目录 《抽象彩色摄影集》.阿瑟.pdf 《色彩构成》.pdf 《色彩学》.星云.扫描版.pdf 《摄影色彩构成》.pdf 《数码相机色彩管理》.pdf 数码摄影进阶之4《色彩篇》.pdf 三、资料下…

【PCL】教程narf_feature_extraction 如何从深度图像中提取 NARF 特征

如何从范围图像中提取 NARF 特征  本教程演示如何从深度图像中在 NARF 关键点位置提取 NARF 描述符。该可执行文件使我们能够从磁盘加载点云&#xff08;或创建它&#xff0c;如果没有提供&#xff09;&#xff0c;在其上提取兴趣点&#xff0c;然后在这些位置计算描述符。然…

spring @value @configurationProperties比较

今天项目中需要使用数组的方式 来加载一批 配置 yml: xxxx: - xxxxx - xsssss javaBean Value("${xxxxx.xxxxx}") private List<String> xxxs; 启动时候报错&#xff0c;无法加载&#xff0c;TM试验了1个小时&#xff0c;我一开始想到是格式的问题&#x…

Android 10.0 Launcher3替换桌面app图标后大小和其他app图标不一样的问题解决方案

1.前言 在10.0的系统ROM产品定制化开发中,在关于launcher3的产品定制化开发中,在有些时候需要对一些第三方的app图标做 替换或者是做一些动态图标的替换,发现在替换以后图标大小和其他app的图标大小不一样,所以就需要看是具体哪里 对app的图标做了缩放功能,接下来就需要去…