一、SpringMVC一个拦截器和文件上传下载的完整程序代码示例
本文章是一个 SpringMVC拦 截器和文件上传下载的完整程序代码示例,使用的开发工具是 IntelliJ IDEA 2024.1.6 (Ultimate Edition), 开发环境是 OpenJDK-21 java version 21.0.2。Tomcatt版本为9.0.96,整体程序目录结构如下:
本程序演示了 SpringMVC中的 interceptor 拦截器的使用,基于此拦截器实现对其它控制器如后台控制器中用户管理的操作程序示例。同时在用户管理控制器添加了基于 spring 的 CommonsMultipartResolver 类实现 文件上传和文件下载的代码程序示例。
A、xml 配置文件
1. pom.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kermit</groupId>
<artifactId>springmvc-05</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.39</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
2. web.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3. resource目录下springmvc.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.kermit.controller" />
<mvc:default-servlet-handler />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 文件上传的固定配置,不用修改-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" >
<property name="defaultEncoding" value="utf-8" />
<!-- 最大上传大小 100M-->
<property name="maxUploadSize" value="104857600" />
<property name="maxUploadSizePerFile" value="104857600" />
<property name="maxInMemorySize" value="10485760" />
<property name="uploadTempDir" value="/WEB-INF/tmp" />
</bean>
<!-- 拦截器配置,/** 匹配所有, /admin/* 匹配 admin下面的请求。-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.kermit.interceptor.AdminInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans>
B、JAVA程序文件
1. controller下的LoginController 控制器程序
package com.kermit.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
//测试拦截器,并结合 session 试验登录 退出的基本逻辑。
@RequestMapping("/login")
public String login(){
return "login";
}
@RequestMapping("/logincheck")
public String logincheck(HttpSession session){
session.setAttribute("admin", "kermit");
return "redirect:/admin/user";
}
@RequestMapping("/logout")
public String logout(HttpSession session){
session.setAttribute("admin", null);
return "redirect:/login";
}
}
2. controller下的UserController 控制器程序
package com.kermit.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
@Controller
public class UserController {
//试拦截器
@RequestMapping("/admin/user")
public String index(Model model) {
model.addAttribute("message", "Hello World");
return "admin/user";
}
//测试spring 文件上传下载
@ResponseBody
@RequestMapping("/admin/upload")
public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//处理用户上传的文件
// 需要在 spring 配置里写一个 bean配置,固定的。
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()) {
realPath.mkdirs();
}
System.out.println("realpath:"+ realPath);
file.transferTo(new File(realPath + "/" + file.getOriginalFilename()));
return "upload success.";
}
@ResponseBody
@RequestMapping("/admin/download/{filename}")
public String download(@PathVariable("filename") String filename, HttpServletRequest request, HttpServletResponse response) throws IOException {
String path = request.getServletContext().getRealPath("/upload");
if(filename == "") filename = "test.jpg";
//清空BUFFER;
response.reset();
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(filename, "UTF-8") + "\"");
File file = new File(path, filename);
InputStream inputStream = new FileInputStream(file);
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int index=0;
while((index=inputStream.read(buffer))!=-1){
outputStream.write(buffer, 0 ,index);
outputStream.flush();
}
outputStream.close();
inputStream.close();
return "download success.";
}
}
3. 拦截器 interceptor 下的 AdminInterceptor
package com.kermit.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AdminInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("------------------pre-----------------");
//登录页允许访问
if(request.getRequestURI().contains("login")){
return true;
}
//已登录用户直接放行
if(request.getSession().getAttribute("admin") != null) {
return true;
}
//其它页面如果未有 session 跳转
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
System.out.println("------------------拦截后-----------------");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("------------------清理后-----------------");
// HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
C、视图文件
1. jsp下的login.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
未登录想直接去后台:被阻止
<a href="${pageContext.request.contextPath}/admin/user" >
<input type="button" value="直接去后台" />
</a>
已输入账号密码登录:<br><br>
<a href="${pageContext.request.contextPath}/logincheck" >
<input type="button" value="跳转验证成功后进入后台" />
</a>
</body>
</html>
2. jsp下的index.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${message}
</body>
</html>
3. jsp下admin目录中的user.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>成功进入管理后台-用户页面</h1>
<br>
<h2>在此页面测试上传一个文件</h2>
<form action="${pageContext.request.contextPath}/admin/upload" method="post" enctype="multipart/form-data">
Select file to upload:
<input type="file" name="file" id="file">
<input type="submit" value="Upload File" name="submit">
</form>
<h2>使用流下载一个文件</h2>
<a href="${pageContext.request.contextPath}/admin/download/24112.jpg">点击下载</a>
<br>
清理 session 退出<br><br>
<a href="${pageContext.request.contextPath}/logout" >
<input type="button" value="退出后台" />
</a>
</body>
</html>
二、IDEA2024部署找不到此Web模块out\artifacts\等问题
1. IDEA2024部署报错 找不到此 Web 模块的 out\artifacts\问题
在使用 IDEA2024 开发项目时,多次修改了项目名称,移动了项目路径,导致出现了一些问题,完整的问题修复已经无法再完整记录。进行了各种尝试,部署都不能成功,报错。
在这个过程中我删除了工件,然后点击+号重建,期间碰到报错:IDEA 无法保存设置 源根 D:XXXX在模块XXX中重复之类的错误。最后成功的一次是删除工件之后,在新建中选择 WEB应用程序展开型时选择了【基于模块】,最后才成功启动了项目。如下图所示:
最后成功后发现浏览器上的路径也有细微差别:
http://localhost:8080/springmvc_05_war_exploded/login 成功
http://localhost:8080/springmvc_05_Web_exploded/login 失败
一个是war地址,一个是web地址。这是Web项目部署中,有两种常见的 exploded 形式:Web exploded 和 War exploded。Web exploded 都是将一个已经打包好的 Web 应用(通常是一个 WAR 文件)解压到指定的目录中。但两者有所不同,与 Web exploded的区别在于War exploded 只会将 WAR 文件中的类文件和库文件解压到指定的目录中,而不包括其他资源文件。这应该就是在出现问题的时候发现 jsp目录、web.xml文件都没有在 out 目录中显示。
2. MVN仓库网站 https://mvnrepository.com/ 总是要验证真人烦
MVN仓库网站 https://mvnrepository.com/ 总是要验证真人烦,真觉得很烦!总是显示:正在验证你是否为真人,请耐心等待!而且我不只碰到过一次,它持续在这个页面循环跳了多次,还出现过失败!我直接浏览器里访问还不是真人吗?可见他的技术也就这个鸟样!这么明显的真人请求都能验错!
3. springmvc开发时getServletContex() 方法报红
另外在使用 springmvc开发时,一段文件上传的代码里需要 HttpServletRequest request)
request.getServletContext().getRealPath getServletContex() 方法报红找不到,相关的包也已经导入,是因为导入的包: javax.servlet-api 版本过低,目前使用的是2.5版本,导入 3.1.0 或者4.0.1 最新版都能解决。