1、想做一个小的商城系统,里面有个商家模块,我用layui.table显示的,但是当我想把图片加进去时才发现对于相对路径和绝对路径的理解不够,进过研究终于搞出来了,不多说直接上代码。
2、首先要了解springboot内置tomcat和外置tomcat里面的虚拟路径的配置。
内置tomcat虚拟路径的配置有两种:
第一种:直接在application.properties中配置,配置方法如下:
# 默认值为/**
spring.mvc.static-path-pattern=/**
# 默认值为 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,\
classpath:/static/, classpath:/public/,file:D:/var/uploaded_files/
第二种方法:新建一个config类,我建的是StaticMvcConfigurerAdapter配置方法,该方法需要实现WebMvcConfigurerAdapter类
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class StaticMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
// 指明浏览器标签页上标题的小图标
// registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/static/images/favicon.ico");
// super.addResourceHandlers(registry);
registry.addResourceHandler("/uploaded_files/**").addResourceLocations("file:/var/uploaded_files/");
}
}
上述两种方法选一种即可
外置tomcat的配置:
https://www.cnblogs.com/hglibin/p/10392078.html
这里就不多说了
3、layui页面
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>商家信息管理</title>
<link rel="stylesheet" th:href="@{/layui/css/layui.css}">
</head>
<style>
.layui-table-cell{
display:table-cell;
vertical-align: middle;
}
</style>
<body>
<blockquote class="layui-elem-quote role_search">
<div class="layui-inline">
<div class="layui-input-inline">
<input id="keyword" type="text" value="" placeholder="请输入类别名称" class="layui-input search_input">
</div>
<a class="layui-btn search_btn" οnclick="query()"><i class="layui-icon layui-icon-search"></i></a>
</div>
<div class="layui-inline">
<a class="layui-btn layui-btn-normal newsAdd_btn" οnclick="openDialog()">
<i class="layui-icon layui-icon-add-circle-fine"></i>新增商家</a>
</div>
</blockquote>
<table class="layui-hide" id="business" lay-filter="tools"></table>
<script type="text/html" id="tools">
<a class="layui-btn layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i></a>
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del"><i class="layui-icon layui-icon-delete"></i></a>
</script>
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-xs" lay-event="find" οnclick="openProduct()">商品信息</a>
</script>
<script type="text/html" id="imgTpl">
<img src="{{ d.picture }}">
<!--<div><img src="{{d.picture}}"></div>-->
</script>
<script th:src="@{layui/layui.js}"></script>
<script th:src="@{jquery-1.11.3.js}"></script>
<script th:src="@{/biz/business_detail.js}"></script>
</body>
</html>
business_detail.js
var table;
var layer;
layui.use(['layer', 'table', 'element'], function () {
table = layui.table;
layer = layui.layer;
// 执行一个 table 实例
table.render({
elem: '#business',
height: 472,
url: 'business_list',
page: true, // 开启分页
limits: [10, 20],
limit: 10,
cols: [[ // 表头
{
fixed: 'left',
type: 'checkbox'
}, {
field: 'shopId',
title: '商家编号',
width: 160,
align: 'center'
}, {
field: 'name',
title: '商家名称',
width: 160,
align: 'center'
}, {
field: 'introduction',
title: '商家介绍',
width: 300,
align: 'center'
}, {
field: 'picture',
title: '商家图片',
templet: '<div><img src="{{d.picture}}"></div>',
width: 160,
align: 'center'
}, {
title: '详情',
width: 160,
align: 'center',
toolbar: '#barDemo'
}, {
title: '操作',
width: 160,
align: 'center',
toolbar: '#tools'
}
]]
});
这里点击上传图片之后,返回满足layui格式的json数据,然后通过回调函数把url地址赋值达到预览效果,代码如下
//html代码
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>商家信息</title>
<link rel="stylesheet" th:href="@{/layui/css/layui.css}">
</head>
<body>
<form class="layui-form" th:object="${business}" id="businessFrm" method="post" enctype="multipart/form-data">
<input type="hidden" name="shopId" id="shopId" th:value="*{shopId}"/>
<div class="layui-form-item" style="margin-top: 20px;">
<label class="layui-form-label">商家名称:</label>
<div class="layui-input-block">
<input type="text" name="name" id="name" th:value="*{name}"
style="width: 200px;" placeholder="请输入商家名称" class="layui-input" lay-verify="required">
</div>
</div>
<div class="layui-form-item" style="margin-top: 20px;">
<label class="layui-form-label">商家简介:</label>
<div class="layui-input-block">
<input type="text" name="Introduction" id="Introduction" th:value="*{introduction}"
style="width: 200px;" placeholder="请输入商家简介" class="layui-input" lay-verify="required">
</div>
</div>
<div class="layui-form-item" style="margin-top: 20px;">
<label class="layui-form-label">商家图片:</label>
<div class="layui-upload">
<button type="button" class="layui-btn" id="test1">上传图片</button>
<input type="hidden" id="img_url" name="picture"/>
<div class="layui-upload-list">
<img class="layui-upload-img" name="picture" id="picture" th:value="*{picture}">
<p id="demoText"></p>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit="" lay-filter="*">确认</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
<script th:src="@{/layui/layui.js}"></script>
<script th:src="@{/jquery-1.11.3.js}"></script>
<script th:src="@{/biz/business_view.js}"></script>
</body>
</html>
html和js两个要分开,这里我写到一起了
//business_view.js代码
layui.use(['form', 'layer','upload'], function () { var form = layui.form; var layer = layui.layer; var $ = layui.jquery ,upload = layui.upload; // 添加验证规则 form.verify({ name: function (value, item) { value = value.trim(); if (value.length < 0) { return "请输入商家名称"; } } }); var uploadInst = upload.render({ elem: '#test1' ,url: '/upload' ,before: function(obj){ files = obj.pushFile(); //将每次选择的文件追加到文件队列 //预读本地文件示例,不支持ie8 obj.preview(function(index, picture, result){//回调函数达到预览效果 $('#picture').attr('src', result); //图片链接(base64) }); } ,done: function(res){ //如果上传失败 if(res.code > 0){ return layer.msg('上传失败'); } //上传成功 layer.msg(res.msg); // alert("上传成功"+res.msg); document.getElementById("img_url").value = res.data.src; // document.getElementById("picture").value = res.data.src(); /*if(res.code==0){ $('.layui-upload-list').html('<img class="layui-upload-list" style="width:80px;height:100px" src="'+res.src+'" id="demo1"> <p id="demoText"></p>'); $('.layui-btn').css({"margin-left":"104px","width":"90px","margin-top":"6px"}); $('.layui-btn').text("重新上传"); return layer.msg(res.msg,{time:700}); }*/ } ,error: function(){ //演示失败状态,并实现重传 var demoText = $('#demoText'); demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-mini demo-reload">重试</a>'); demoText.find('.demo-reload').on('click', function(){ uploadInst.upload(); }); } }); form.on('submit(*)', function (data) { layer.alert(JSON.stringify(data.field), { title: '最终的提交信息' }) var index = layer.msg('提交中,请稍候', {icon: 16, time: false, shade: 0.8}); var context = data.field; var url = "/saveOrUpdate"; $.ajax({ type: 'POST', url: "/saveOrUpdate", data: context, dataType: "text", success: function (data) { var index = parent.layer.getFrameIndex(window.name); //获取窗口索引 parent.layer.close(index); // 关闭layer if (data == 0) { parent.layer.msg("操作成功", {icon: 6}); parent.table.reload('business', { page: { curr: 1 // 重新从第1页开始 }, where: { 'keyword': $("#keyword").val() } }); } else { parent.layer.msg("操作失败", {icon: 5}); } }, error: function () { parent.layer.msg("操作失败", {icon: 5}); } }); return false; }); });
controller层photoUpload.controller
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@Controller
public class photoUpload {
@Autowired
private BusinessDao businessDao;
@ResponseBody
@RequestMapping("/upload")
public JSONObject uploadaaa(MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws IllegalStateException, IOException{
JSONObject res = new JSONObject();
JSONObject resUrl = new JSONObject();
//String path = request.getSession().getServletContext().getRealPath("upload");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式 HH:mm:ss
String date = df.format(new Date());// new Date()为获取当前系统时间,也可使用当前时间戳
String path = "D:/var/uploaded_files/";
UUID uuid=UUID.randomUUID();
String originalFilename = file.getOriginalFilename();
// String fileName = uuid.toString() + originalFilename;
String extendName = originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());
String fileName = uuid.toString() + extendName;
File dir = new File(path+fileName);
File filepath = new File(path);
System.out.println("路径=="+filepath.getParentFile());
if(!filepath.getParentFile().exists()){
filepath.getParentFile().mkdirs();
}else{
System.out.println(filepath.getParentFile());
}
// if(!filepath.exists()) {
file.transferTo(dir);
//获得当前项目所在路径
String pathRoot=request.getSession().getServletContext().getRealPath("");
System.out.println("当前项目所在路径:"+pathRoot);
String sqlFile = "http://localhost:8003/"+fileName;
Business business =new Business();
business.setPicture(sqlFile);
businessDao.save(business);
// }
resUrl.put("src", sqlFile);
res.put("code", 0);
res.put("msg", "上传成功");
res.put("data", resUrl);
String str="";
str = "{\"code\": 0,\"msg\": \"\",\"data\": {\"src\":\"" +dir + "\"}}";
return res;
/*Map<String, String> map = new HashMap<>();
map.put("filePath", path);
map.put("fileName", fileName);
Map<String, Object> result = new HashMap<>();
result.put("code", 0);
result.put("msg", "上传成功");
result.put("count", 1);
result.put("data", map);
return result;*/
}
//@RequestParam(required=false)MultipartFile file 表示图片接受可为空
@ResponseBody
@RequestMapping(value = "/saveOrUpdate",method = RequestMethod.POST)
public Integer saveOrUpdate (@RequestParam("shopId") int shopId,
@RequestParam("Introduction") String Introduction,
@RequestParam("picture") String picture,
// @RequestParam("file") String file,
MultipartFile file,
HttpServletRequest request){
JSONObject res = new JSONObject();
JSONObject resUrl = new JSONObject();
try {
String pictureFile = file.getOriginalFilename();
Business business =new Business();
business.setPicture(picture);
// business.setBusinessid(bussinessid);
business.setIntroduction(Introduction);
business.setShopId(shopId);
businessDao.save(business);
} catch (Exception e) {
e.printStackTrace();
/*res.put("code", 500);
res.put("msg", "服务器内部错误");
res.put("count", 0);
res.put("data", new ArrayList());
return res;*/
}
/* res.put("count", 10);
res.put("code", 0);
res.put("msg", "上传成功");
res.put("data", new ArrayList());*/
return 0;
}
}
实体类:Business
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Objects;
@Entity
public class Business {
private int shopId;
private Integer businessid;
private String name;
private String picture;
private String introduction;
@Id
@Column(name = "shop_id", nullable = false)
public int getShopId() {
return shopId;
}
public void setShopId(int shopId) {
this.shopId = shopId;
}
@Basic
@Column(name = "businessid", nullable = true)
public Integer getBusinessid() {
return businessid;
}
public void setBusinessid(Integer businessid) {
this.businessid = businessid;
}
@Basic
@Column(name = "name", nullable = true, length = 128)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Basic
@Column(name = "picture", nullable = true, length = 255)
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
@Basic
@Column(name = "Introduction", nullable = true, length = 255)
public String getIntroduction() {
return introduction;
}
public void setIntroduction(String introduction) {
this.introduction = introduction;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Business business = (Business) o;
return shopId == business.shopId &&
Objects.equals(businessid, business.businessid) &&
Objects.equals(name, business.name) &&
Objects.equals(picture, business.picture) &&
Objects.equals(introduction, business.introduction);
}
@Override
public int hashCode() {
return Objects.hash(shopId, businessid, name, picture, introduction);
}
}
Dao层
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface BusinessDao extends JpaRepository<Business, Integer>, JpaSpecificationExecutor<Business> {
/*@Query(value="select * from business where bus_id=?",nativeQuery=true)
Business findAllByBusIdA(int bus_id);
@Query(value="select * from business",nativeQuery=true)
List<Business> findAll(Specification<Business> specification);
*/
/*@Query(value="select * from business",nativeQuery=true)
List<Business> findAll();*/
}
好了到这里就完成了,最后附上界面