SpringBoot
<!-- 引入swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--集成通用mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>
<!-- apache 工具类 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
WebMvcConfig 配置
package com.study.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* 虚拟目录配置
* 将服务目录映射成web资源
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//swagger增加url映射
registry.addResourceHandler("/**")
//swagger2静态资源文件配置
.addResourceLocations("classpath:/META-INF/resources/")
.addResourceLocations("classpath:/META-INF/resources/templates/")
.addResourceLocations("file:F:/weChatProject/movieProject/movieSystem/");
}
}
UserController
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import com.study.base.result.JSONResult;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
@RestController
@Api(value="用户相关业务的接口", tags= {"用户相关业务的controller"})
@RequestMapping("/user")
public class UserController extends BasicController {
@Autowired
private UserService userService;
//http://localhost:8080/swagger-ui.html
//http:localhost:8080/1002/face/a.png
/**
* 用户上传头像(单张)
* @param userId
* @param files
* @return
* @throws Exception
*/
@ApiOperation(value="用户上传头像", notes="用户上传头像的接口")
@ApiImplicitParam(name="userId", value="用户id", required=true,
dataType="String", paramType="query")
@PostMapping("/uploadFace")
public JSONResult uploadFace(String userId, @RequestParam("file") MultipartFile[] files) throws Exception {
if (StringUtils.isBlank(userId)) {
return JSONResult.errorMsg("用户id不能为空...");
}
// 文件保存的命名空间
String fileSpace = "F:/WeChatProject/movieProject/movieSystem";
// 保存到数据库中的相对路径
String uploadPathDB = "/" + userId + "/face";
FileOutputStream fileOutputStream = null;
InputStream inputStream = null;
try {
//如果微信端传来的头像不为空
if (files != null && files.length > 0) {
//获取文件名
String fileName = files[0].getOriginalFilename();
//如果文件名不为空
if (StringUtils.isNotBlank(fileName)) {
// 文件上传的最终保存路径
String finalFacePath = fileSpace + uploadPathDB + "/" + fileName;
// 设置数据库保存的路径
uploadPathDB += ("/" + fileName);
File outFile = new File(finalFacePath);
//判断父文件夹是否存在
if (outFile.getParentFile() != null || !outFile.getParentFile().isDirectory()) {
// 父文件夹不存在则创建父文件夹
outFile.getParentFile().mkdirs();
}
fileOutputStream = new FileOutputStream(outFile);
inputStream = files[0].getInputStream();
IOUtils.copy(inputStream, fileOutputStream);
}
} else {
return JSONResult.errorMsg("上传出错...");
}
} catch (Exception e) {
e.printStackTrace();
return JSONResult.errorMsg("上传出错...");
} finally {
if (fileOutputStream != null) {
fileOutputStream.flush();
fileOutputStream.close();
}
}
Users users=new Users();
users.setId(userId);
users.setFaceImage(uploadPathDB);
//修改用户信息
userService.updateUserInfo(users);
return JSONResult.ok(uploadPathDB);
}
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.study.mapper.UsersMapper" >
<resultMap id="BaseResultMap" type="com.study.model.Users" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="VARCHAR" />
<result column="username" property="username" jdbcType="VARCHAR" />
<result column="password" property="password" jdbcType="VARCHAR" />
<result column="face_image" property="faceImage" jdbcType="VARCHAR" />
<result column="nickname" property="nickname" jdbcType="VARCHAR" />
<result column="fans_counts" property="fansCounts" jdbcType="INTEGER" />
<result column="follow_counts" property="followCounts" jdbcType="INTEGER" />
<result column="receive_like_counts" property="receiveLikeCounts" jdbcType="INTEGER" />
</resultMap>
</mapper>
MyMapper
package com.study.base.mapper;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
//TODO
//FIXME 特别注意,该接口不能被扫描到,否则会出错
}
UserMapper
package com.study.mapper;
import com.study.base.mapper.MyMapper;
import com.study.model.Users;
public interface UsersMapper extends MyMapper<Users> {
}
SpringBoot主类
//import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.ComponentScan;
import tk.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
//扫描mapper文件
@MapperScan("com.study.mapper")
@ComponentScan(basePackages = {"com.study","com.study.config"})
public class WechatMovieManageApplication {
public static void main(String[] args) {
SpringApplication.run(WechatMovieManageApplication.class, args);
}
}
service
@Service
public class UserServiceImpl implements UserService {
@Resource
private UsersMapper userMapper;
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void updateUserInfo(Users user) {
Example userExample = new Example(Users.class);
Example.Criteria criteria = userExample.createCriteria();
//通过ID查询用户
criteria.andEqualTo("id", user.getId());
//updateByExampleSelective是将一行中某几个属性更新,而不改变其他的值
userMapper.updateByExampleSelective(user, userExample);
}
}
JSONResult
package com.study.base.result;
/**
* @Description: 自定义响应数据结构
* 这个类是提供给门户,ios,安卓,微信商城用的
* 门户接受此类数据后需要使用本类的方法转换成对于的数据类型格式(类,或者list)
* 其他自行处理
* 200:表示成功
* 500:表示错误,错误信息在msg字段中
* 501:bean验证错误,不管多少个错误都以map形式返回
* 502:拦截器拦截到用户token出错
* 555:异常抛出信息
*/
public class JSONResult {
// 响应业务状态
private Integer status;
// 响应消息
private String msg;
// 响应中的数据
private Object data;
private String ok; // 不使用
public static JSONResult build(Integer status, String msg, Object data) {
return new JSONResult(status, msg, data);
}
public static JSONResult ok(Object data) {
return new JSONResult(data);
}
public static JSONResult ok() {
return new JSONResult(null);
}
public static JSONResult errorMsg(String msg) {
return new JSONResult(500, msg, null);
}
public static JSONResult errorMap(Object data) {
return new JSONResult(501, "error", data);
}
public static JSONResult errorTokenMsg(String msg) {
return new JSONResult(502, msg, null);
}
public static JSONResult errorException(String msg) {
return new JSONResult(555, msg, null);
}
public JSONResult() {
}
public JSONResult(Integer status, String msg, Object data) {
this.status = status;
this.msg = msg;
this.data = data;
}
public JSONResult(Object data) {
this.status = 200;
this.msg = "OK";
this.data = data;
}
public Boolean isOK() {
return this.status == 200;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getOk() {
return ok;
}
public void setOk(String ok) {
this.ok = ok;
}
}
微信小程序端
wxml
<block wx:if="{{isMe}}">
<image src="{{faceUrl}}" class="face" bindtap='changeFace'></image>
</block>
<block wx:if="{{!isMe}}">
<image src="{{faceUrl}}" class="face"></image>
</block>
js
data: {
faceUrl: "../resource/images/noneface.png",
isMe: true,
},
/**
*上传头像
*/
changeFace: function () {
var me = this;
wx.chooseImage({
count: 1,//最多选择的图片张数,默认是9
sizeType: ['compressed'],//original原图;compressed压缩图,默认两者都有
sourceType: ['album'],//album从相册选图,camera使用相机,默认两者都有
success: function (res) {//成功则返回图片的本地文件路径列表tempFilePaths
//返回选定照片的本地文件路径列表, tempFilePath可以作为img标签的src属性显示图片
var tempFilePaths = res.tempFilePaths;
console.log(tempFilePaths);
wx.showLoading({
title: '上传中...',
})
var serverUrl = app.serverUrl;
// fixme 修改原有的全局对象为本地缓存
var userInfo = app.getGlobalUserInfo();
console.log(userInfo);
wx.uploadFile({
url: serverUrl + '/user/uploadFace?userId='+app.userInfo.id, //app.userInfo.id,
filePath: tempFilePaths[0],
name: 'file',
header: {
'content-type': 'application/json', // 默认值
'headerUserId': user.id,
'headerUserId':1002,
'headerUserToken': user.userToken
},
success: function (res) {
//接受过来的数据为String类型
console.log(res.data);
//接受过来的数据为String类型,将String类型转化为JSON对象
var data = JSON.parse(res.data);
wx.hideLoading();
if (data.status == 200) {
wx.showToast({
title: '上传成功!~~',
icon: "success"
});
//获取相对路径
var imageUrl = data.data;
me.setData({
faceUrl: serverUrl + imageUrl
});
} else if (data.status == 500) {
wx.showToast({
title: data.msg
});
} else if (res.data.status == 502) {
wx.showToast({
title: res.data.msg,
duration: 2000,
icon: "none",
success: function () {
wx.redirectTo({
url: '../userLogin/login',
})
}
});
}
}
})
}
})
},