java springmvc 项目tomcat配置虚拟路径使文件与程序分离

场景:当程序中需要上传很多静态文件时,不适合将存放上传文件的文件夹放在项目里面,因为每次打包部署时会将文件夹覆盖,使服务器的静态文件丢失。有人会每次部署时备份文件,但当文件夹很大时,备份一次很费劲。

所以最好将文件与程序分离,将上传的文件夹放到服务器固定的位置,程序中需要访问文件统一去这个路径下访问。

1. 1.1tomcat配置虚拟路径

可以参考这篇文章:https://blog.csdn.net/chengp919/article/details/76552006

基本操作就是打开 tomcat/conf/server.xml文件,在host中添加 一个context标签

<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">

     <!-- 这里添加以下语句-->
     <Context path="/attachments/" docBase="E:\工作项目\attachments"></Context>

</Host>

path为访问路径,docBase为真实物理路径,意思是当访问path中的路径时,tomcat会自动找docBase中的路径。

这种适合war包在tomcat中运行的生产环境

另外说一下,有时候部署程序时也用这种方法虚拟路径

比如 <Context path="" docBase="E:\工作项目\zhxZone\target\zhuhuixin" reloadable="false" caseSensitive="false" debug="0"/>

这样配置tomcat启动后会将docBase中的程序直接启动,不需要将程序放到webapp文件夹里。

但我自己开发时,使用的是idea 启动tomcat,配置tomcat中的server就不起作用了

1.2 idea中配置tomcat虚拟路径

参考文章:https://blog.csdn.net/cheney550995353/article/details/70185282

在deployment中添加并选择你需要的真实物理路径,application context配上访问路径就可以了。

我使用配置路径成功访问了虚拟路径中的文件

2.调用config.properties中配置的保存根路径

因为程序部署时有时候会换服务器或者静态文件夹的路径,所以在程序中上传根路径不能写死,最好配置在config.properties中,方便调用修改。

具体步骤可以参考这篇文章:https://blog.csdn.net/chinadim/article/details/40621671

2.1、在spring.xml中加入context相关引用

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd">

2.2引入jdbc配置文件         

<context:property-placeholder location="classpath:config.properties" ignore-unresolvable="true" file-encoding="UTF-8"/>

 2.3、jdbc.properties的配置如下

basePath=E:\\工作项目

注意路径的“\”会被当做转义字符消失,要写双反斜杠

2.4、创建一个ConfigProperties类引用config.properties配置

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
 
 
@Configuration 
public class ConfigProperties{	
	
	@Value("${basePath}")
	public  String basePath; //这里变量不能定义成static
	 
}

2.5、在controller中调用 

首先在controller顶部声明

@Autowired
private ConfigProperties configProperties;

@Value("${basePath}")
private String basePath; //直接在Controller引用

这样在方法中就可以随时使用basePath配置了。 

但是实际使用时可能会出现一些问题。

如果使用报错 如果报错:IllegalArgumentException: Could not resolve placeholder in string value "${XXXXXX}"

参考文献:https://blog.csdn.net/aichidemao2017/article/details/76067526

如果你在config中的配置有中文,那读取的值可能会成为乱码。

可以在这句话中添加file-encoding="UTF-8"

<context:property-placeholder location="classpath:config.properties" ignore-unresolvable="true" file-encoding="UTF-8"/>

参考文献:https://blog.csdn.net/j3oker/article/details/53839210

3.实际运用

注意:在访问静态资源时这个配置虚拟路径可以根据访问路径寻找真实路径,但是上传文件是不能使用虚拟路径,必须写真实的物理路径

@Controller
@RequestMapping(value = "webmana", produces = "text/plain;charset=UTF-8")
public class AttachmentController extends BaseController{
    @Resource
    private AttachmentService attachmentService;

    @Autowired
    private ConfigProperties configProperties;

    @Value("${basePath}")
    private String basePath; //直接在Controller引用


    // 上传图片
    @RequestMapping(value = "uploadImg", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String uploadImg(
            @RequestParam(value = "file") MultipartFile[] files,  //这样接收文件
            String classId,
            HttpServletRequest request
    ) {
        try {
            Map<String,Object> params=new HashMap<String, Object>();
            String path="/attachments/images/";
            int userId=((TSystemUser)request.getSession().getAttribute("USER")).getUserId();
            params.put("classId",classId);
            params.put("attachmentType","IMAGE");
            params.put("userId",userId);
            for (MultipartFile file : files) {    //循环保存文件
                Map<String,String> name=uploadFile(path,file, request);
                params.put("attachmentUrl",path+name.get("saveName"));
                params.put("attachmentName",name.get("fileName"));
                params.put("attachmentThumbnail","");
                attachmentService.saveFile(params);
               // attachmentService.saveImg(path);
            }
            // 返回前台
            return JSON.toJSONString("success");

        } catch (Exception e) {
            e.printStackTrace();
            return JSON.toJSONString("fail");
        }

    }

	//上传文件
    public Map<String,String> uploadFile(String path,MultipartFile file, HttpServletRequest request) throws IOException {
        Map<String,String> result=new HashMap<String,String>();
        String fileName = file.getOriginalFilename();
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();
        String saveName=String.valueOf((new Date()).getTime()).substring(8)+(int)((Math.random()*999+1))+'.'+fileType;
		//需要真实路径,加basePath
        File tempFile = new File(basePath+path, String.valueOf(saveName));
        if (!tempFile.getParentFile().exists()) {    //创建文件夹
            tempFile.getParentFile().mkdir();
        }
        if (!tempFile.exists()) {
            tempFile.createNewFile();
        }
        file.transferTo(tempFile);
        result.put("fileName",fileName);
        result.put("saveName",saveName);
        return result;
    }


    //删除文件
    @RequestMapping(value = "deleteItem", produces = "application/json;charset=utf-8")
    @ResponseBody
    public String deleteItem(
            String ids,HttpServletRequest request
    ) {
        Map<String,Object> ret=new HashMap<String, Object>();
        try {
            String[] arr=ids.split(",");
            for(String id:arr ){
                int id1=isIntegerRight(id);
                String url=attachmentService.getAttachmentById(id1).get(0).get("attachment_url");
                String name=attachmentService.getAttachmentById(id1).get(0).get("attachment_name");
                //删除文件也需要文件真实路径
                File file = new File(basePath+url);
                // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
                if (file.exists() && file.isFile()) {
                    if (file.delete()) {
                        System.out.println("删除单个文件"+name+"成功!");
                    } else {
                        System.out.println("删除单个文件 "+name+"失败!");
                        ret.put("success",false);
                        ret.put("msg","删除失败");
                        return JSON.toJSONString(ret);
                    }
                } else {
                    System.out.println("删除单个文件失败:"+name+"不存在!");
                    ret.put("success",false);
                    ret.put("msg","删除文件不存在");
                    return JSON.toJSONString(ret);
                }
            }
            attachmentService.deleteItem(ids);
            ret.put("success",true);
            ret.put("msg","删除成功");

        } catch (Exception e) {
            e.printStackTrace();
            ret.put("success",false);
            ret.put("msg","删除失败");

        }
        return JSON.toJSONString(ret);

    }

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆趣编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值