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

news2025/1/12 13:17:32

目录

  • 异常处理
    • 解释
    • 局部异常处理
    • 全局异常
  • 拦截器
    • 拦截器介绍
    • 作用:
    • 拦截器和过滤器之间的区别
    • 拦截器执行流程
    • 代码实现
    • 补充
  • 文件上传
    • 依赖
    • 配置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后,可以进行功能测试

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mybatis中<if>条件判断带数字的字符串失效问题

文章目录 一、项目背景二、真实错误原因说明三、解决方案3.1针对纯数字的字符串值场景3.2针对单个字符的字符串值场景 四、参考文献 一、项目背景 MySQL数据库使用Mybatis查询拼接select语句中进行<if>条件拼接的时候&#xff0c;发现带数字的或者带单个字母的字符串失效…

Coursera: An Introduction to American Law 学习笔记 Week 03: Property Law

An Introduction to American Law 本文是 https://www.coursera.org/programs/career-training-for-nevadans-k7yhc/learn/american-law 这门课的学习笔记。 文章目录 An Introduction to American LawInstructors Week 03: Property LawKey Property Law TermsSupplemental Re…

LM324的输出VOL与IOL你注意过吗?

电路图 途中LMC6084 更改为LM324 故障现象 这个电路的输入输出表达式为 R30 两端电压等于0V 当J16 的4脚与2脚相等&#xff0c;等于5V&#xff08;或者4脚略大于2脚时&#xff09;7脚输出 约 500mV&#xff1b; 实际应该为0V左右才对.见下图 故障原因 上图运放输出低电平…

AI重塑数字安全,安恒信息行胜于言

有人曾言&#xff1a;所有行业都值得基于人工智能技术重做一遍。 深以为然。如今&#xff0c;数字安全产业面临着一次重要的重塑机遇。以大模型为代表的人工智能技术正深刻影响着数字安全市场格局、产品研发、技术方案以及运营服务。产业界已形成共识&#xff0c;即谁能抓住人…

Nginx+Lua+OpenResty(详解及使用)

一、 Nginx简介 Nginx是一个高性能的Web服务器和反向代理的软件。 Web服务器&#xff1a;就是运行我们web服务的容器&#xff0c;提供web功能&#xff0c;还有tomcat也提供类似的功能。 代理是软件架构和网络设计中&#xff0c;非常重要的一个概念。 二、Nginx的反向代理&…

WEB服务的配置与使用 Apache HTTPD

服务端&#xff1a;服务器将发送由状态代码和可选的响应正文组成的 响应 。状态代码指示请求是否成功&#xff0c;如果不成功&#xff0c;则指示存在哪种错误情况。这告诉客户端应该如何处理响应。较为流星的web服务器程序有&#xff1a; Apache HTTP Server 、 Nginx 客户端&a…

百度网盘svip白嫖永久手机2024最新教程

百度网盘&#xff08;原名百度云&#xff09;是百度推出的一项云存储服务&#xff0c;已覆盖主流PC和手机操作系统&#xff0c;包含Web版、Windows版、Mac版、Android版、iPhone版和Windows Phone版。用户将可以轻松将自己的文件上传到网盘上&#xff0c;并可跨终端随时随地查看…

爬虫抓取网站数据

Fiddler 配置fiddler工具结合浏览器插件 配置fiddler Tools--Options 抓包技巧 谷歌浏览器开启无痕浏览,使用SwitchyOmega配置好代理端口 Ctrl x 清理所有请求记录,可以删除指定不需要日志方便观察 设置按请求顺序 观察cookie,观察请求hesder cookie和row返回结果 Swit…

《QT实用小工具·四十二》圆形发光图像

1、概述 源码放在文章末尾 该项目实现了图像的发光效果&#xff0c;特别适合做头像&#xff0c;项目demo演示如下所示&#xff1a; 项目部分代码如下所示&#xff1a; import QtQuick 2.7 import QtGraphicalEffects 1.12Item {id: rootwidth: 80height: 80property int ra…

写Python需要养成的9个编程好习惯

以写Python代码为例&#xff0c;有以下9个编程好习惯。 1. 提前设计 写代码和写作文一样&#xff0c;需要有大纲&#xff0c;不然很容易变成"屎山"。 思考业务逻辑和代码流程&#xff0c;是动手前的准备工作&#xff0c;这上面可以花一半以上时间。 一些程序员洋…

【考研数学】全程跟张宇,《1000题》应该怎么搭配《660》《880》?

数一125学长来了&#xff0c;选题集和选老师经验满满&#xff0c;手把手教你避雷&#xff0c;直接不废话&#xff0c;三本题集很重要&#xff0c;筛选找重点事半功倍。 就老师而言&#xff0c;如果已经决定全程跟张宇老师了&#xff0c;那么就不要中途换老师&#xff01; 就题…

按照模板导出复杂样式的excel

导出excel通常使用的是apache poi,但是poi的api相当复杂&#xff0c;所以当导出的excel样式比较复杂时&#xff0c;写起来就比较头疼了&#xff0c;这里推荐使用easypoi, 可以很方便的根据模板来导出复杂excel 文档地址: 1.1 介绍 - Powered by MinDoc 我们要实现如图所示效果…

C++的二叉搜索树

目录 基本概念 二叉搜索树的实现 插入结点 查找结点 删除结点 删除结点左为空 删除结点右为空 基于特殊情况的优化 删除结点左右不为空 基于特殊情况的优化 完整代码 二叉搜索树的实际应用 K和KV模型 改造二叉搜索树为为KV模型 基本概念 1、二叉搜索树又称二叉…

数据结构之二叉搜索树底层实现洞若观火!

目录 题外话 正题 二叉搜索树 底层实现 二叉搜索树查找操作 查找操作思路 查找代码实现详解 二叉搜索树插入操作 插入操作思路 插入代码详解 二叉搜索树删除操作 删除操作思路 删除代码详解 小结 题外话 我的一切都是党给的,都是人民给的,都是家人们给的!! 十分感…

LeetCode:51. N 皇后

leetCode51.N皇后 题解分析 代码 class Solution { public:int n;vector<vector<string>> ans;vector<string> path;vector<bool> col, dg,udg;vector<vector<string>> solveNQueens(int _n) {n _n;col vector<bool> (n);dg …

通过matlab对比遗传算法优化前后染色体的变化情况

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 通过matlab对比遗传算法优化前后染色体的变化情况. 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 3.核心程序 ....................................…

AI视频教程下载:用ChatGPT和 MERN 堆栈构建 SAAS 项目

这是一个关于 掌握ChatGPT 开发应用的全面课程&#xff0c;它将带领你进入 AI 驱动的 SAAS 项目的沉浸式世界。该课程旨在使你具备使用动态的 MERN 堆栈和无缝的 Stripe 集成来构建强大的 SAAS 平台所需的技能。 你将探索打造智能解决方案的艺术&#xff0c;深入研究 ChatGPT 的…

第十五章数据管理成熟度评估6分

15.1 引言 能力成熟度评估&#xff08;Capability Maturity Assessment&#xff0c;CMA&#xff09; 是一种基于能力成熟度模型&#xff08;Capability MaturityModel&#xff0c;CMM&#xff09;框架的能力提升方案&#xff0c;描述了数据管理能力初始状态发展到最优化的过程…

一键部署,隐私无忧!有道QAnything,本地AI问答系统开源了,你下载了吗?

作者&#xff1a;Aitrainee | 公众号&#xff1a;AI进修生 排版太难了&#xff0c;请点击这里查看原文&#xff1a;一键部署&#xff0c;隐私无忧&#xff01;有道QAnything&#xff0c;本地AI问答系统开源了&#xff0c;你下载了吗&#xff1f; 一键部署&#xff0c;隐私无忧…

AWVS的使用

AWVS的使用 1、使用docker拉取AWVS的镜像 docker pull secfa/docker-awvs 2.使用AWVS docker run -it -d -p 13443:3443 --cap-add LINUX_IMMUTABLE secfa/docker-awvs 3.访问 4.输入账号密码 https://hub.docker.com/r/secfa/docker-awvs 找到账号密码 username:adminadmin.…