合并代码

This commit is contained in:
wuy 2019-07-11 16:13:03 +08:00
commit de67c7cad2
41 changed files with 1291 additions and 46 deletions

View File

@ -58,7 +58,9 @@ subprojects {
// JSON
compile("com.alibaba:fastjson:$fastjsonVersion")
// Apache Commons
compile("org.apache.commons:commons-lang3:3.8.1")
compile("org.apache.commons:commons-lang3:3.8.1",
"commons-fileupload:commons-fileupload:1.3.3",
"commons-io:commons-io:2.6")
//
testCompile("org.springframework.boot:spring-boot-starter-test:$springBootVersion")

View File

@ -0,0 +1,9 @@
dependencies {
compile project(":diboot-core")
// java mail
compile("javax.mail:mail:1.4.7",
"org.apache.commons:commons-email:1.5")
testCompile group: 'junit', name: 'junit', version: '4.12'
}

View File

@ -0,0 +1,11 @@
package com.diboot.components.msg.config;
/*
* 配置基类之后的邮件短信等实现时都需要需要继承此类
* 并在此基础上扩展
* */
public abstract class BaseConfig {
//关键配置是否为空
public abstract boolean isEmpty();
}

View File

@ -0,0 +1,41 @@
package com.diboot.components.msg.config;
import com.diboot.core.util.Encryptor;
import com.diboot.core.util.V;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* @author : wangyongliang@dibo.ltd
* @version v2.0
* @Description: 读取配置文件类
* @Date 2019-07-8
*/
@Configuration
@EnableConfigurationProperties(EmailConfig.class)
@ConfigurationProperties("email.sender")
@Data
public class EmailConfig extends BaseConfig {
private String name;
private String address;
private String password;
private String host;
private String sslport;
@Override
public boolean isEmpty() {
if(V.notEmpty(address) && V.notEmpty(password)){
return false;
}
return true;
}
}

View File

@ -0,0 +1,10 @@
package com.diboot.components.msg.config;
public class MsgCons {
public enum MSG_TYPE{
EMAIL, //邮件消息
SMS, //短信消息
WECHAT //微信消息
}
}

View File

@ -0,0 +1,104 @@
package com.diboot.components.msg.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.components.msg.entity.Message;
import com.diboot.components.msg.service.MessageService;
import com.diboot.components.msg.vo.MessageVO;
import com.diboot.core.binding.manager.AnnotationBindingManager;
import com.diboot.core.controller.BaseCrudRestController;
import com.diboot.core.service.BaseService;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Pagination;
import com.diboot.core.vo.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
@RequestMapping("/message")
public class MessageController extends BaseCrudRestController {
@Autowired
private MessageService messageService;
@Override
protected BaseService getService() {
return messageService;
}
@GetMapping("/list")
public JsonResult list(HttpServletRequest request) throws Exception {
//构建查询条件
QueryWrapper<Message> queryWrapper = buildQuery(request);
//构建分页
Pagination pagination = buildPagination(request);
// 查询当前页的Entity主表数据
List<Message> entityList = getService().getEntityList(queryWrapper, pagination);
// 自动转换VO中注解绑定的关联
List<MessageVO> voList = AnnotationBindingManager.autoConvertAndBind(entityList, MessageVO.class);
//返回结果
return new JsonResult(Status.OK, voList).bindPagination(pagination);
}
/***
* 查询Entity
* @param id
* @return
* @throws Exception
*/
@GetMapping("/{id}")
public JsonResult getModel(@PathVariable("id")Long id, HttpServletRequest request, ModelMap modelMap)
throws Exception{
MessageVO entityVO = messageService.getViewObject(id, MessageVO.class);
return new JsonResult(entityVO);
}
/***
* 创建Entity
* @return
* @throws Exception
*/
@PostMapping("/")
public JsonResult createEntity(@ModelAttribute Message entity, BindingResult result, HttpServletRequest request, ModelMap modelMap)
throws Exception{
return super.createEntity(entity, result, modelMap);
}
/***
* 更新Entity
* @param id
* @return
* @throws Exception
*/
@PutMapping("/{id}")
public JsonResult updateModel(@PathVariable("id")Long id, @ModelAttribute Message entity, BindingResult result,
HttpServletRequest request, ModelMap modelMap) throws Exception{
return super.updateEntity(entity, result, modelMap);
}
/***
* 删除
* @param id
* @return
* @throws Exception
*/
@DeleteMapping("/{id}")
public JsonResult deleteModel(@PathVariable("id")Long id, HttpServletRequest request) throws Exception{
return super.deleteEntity(id);
}
/***
* 创建并发送消息
* @throws Exception
*/
@PostMapping("/createAndSendMsg")
public JsonResult createAndSendMsg(@RequestBody Message message, HttpServletRequest request) throws Exception{
boolean success = messageService.createAndSendMsg(message);
return new JsonResult(success);
}
}

View File

@ -0,0 +1,90 @@
package com.diboot.components.msg.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.components.msg.entity.MessageTemplate;
import com.diboot.components.msg.service.MessageTemplateService;
import com.diboot.core.controller.BaseCrudRestController;
import com.diboot.core.service.BaseService;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Pagination;
import com.diboot.core.vo.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
@RequestMapping("/messageTemplate")
public class MessageTemplateController extends BaseCrudRestController {
@Autowired
private MessageTemplateService messageTemplateService;
@Override
protected BaseService getService() {
return messageTemplateService;
}
@GetMapping("/list")
public JsonResult list(HttpServletRequest request) throws Exception {
//构建查询条件
QueryWrapper<MessageTemplate> queryWrapper = buildQuery(request);
//构建分页
Pagination pagination = buildPagination(request);
// 查询当前页的Entity主表数据
List<MessageTemplate> entityList = getService().getEntityList(queryWrapper, pagination);
//返回结果
return new JsonResult(Status.OK, entityList).bindPagination(pagination);
}
/***
* 查询Entity
* @param id
* @return
* @throws Exception
*/
@GetMapping("/{id}")
public JsonResult getModel(@PathVariable("id")Long id, HttpServletRequest request, ModelMap modelMap)
throws Exception{
MessageTemplate entity = messageTemplateService.getEntity(id);
return new JsonResult(entity);
}
/***
* 创建Entity
* @return
* @throws Exception
*/
@PostMapping("/")
public JsonResult createEntity(@ModelAttribute MessageTemplate entity, BindingResult result, HttpServletRequest request, ModelMap modelMap)
throws Exception{
return super.createEntity(entity, result, modelMap);
}
/***
* 更新Entity
* @param id
* @return
* @throws Exception
*/
@PutMapping("/{id}")
public JsonResult updateModel(@PathVariable("id")Long id, @ModelAttribute MessageTemplate entity, BindingResult result,
HttpServletRequest request, ModelMap modelMap) throws Exception{
return super.updateEntity(entity, result, modelMap);
}
/***
* 删除
* @param id
* @return
* @throws Exception
*/
@DeleteMapping("/{id}")
public JsonResult deleteModel(@PathVariable("id")Long id, HttpServletRequest request) throws Exception{
return super.deleteEntity(id);
}
}

View File

@ -0,0 +1,18 @@
package com.diboot.components.msg.entity;
import lombok.Data;
/*
* 消息基类之后的邮件短信等实现时都需要需要继承此类
* 并在此基础上扩展
* */
@Data
public class BaseMessage {
//接收人
private String receiver;
//消息内容
private String content;
}

View File

@ -0,0 +1,20 @@
package com.diboot.components.msg.entity;
import com.diboot.components.msg.config.MsgCons;
import lombok.Data;
/*
*
* */
@Data
public class EmailMessage extends BaseMessage {
private String receiverName;
private String[] ccEmails;
private String title;
private String[] filePaths;
}

View File

@ -0,0 +1,49 @@
package com.diboot.components.msg.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.diboot.core.entity.BaseExtEntity;
import lombok.Data;
import java.util.Date;
@Data
public class Message extends BaseExtEntity {
@TableField
private String type;
@TableField
private Long templateId;
@TableField
private String businessType;
@TableField
private String businessId;
@TableField
private String sender;
@TableField
private String receiver;
@TableField
private String title;
@TableField
private String content;
@TableField
private String url;
@TableField
private String status;
@TableField
private Date scheduleTime;
@TableField
private String response;
}

View File

@ -0,0 +1,34 @@
package com.diboot.components.msg.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.diboot.core.entity.BaseExtEntity;
import lombok.Data;
@Data
public class MessageTemplate extends BaseExtEntity {
@TableField
private String type;
@TableField
private String code;
@TableField
private String msgType;
@TableField
private String businessType;
@TableField
private Long businessId;
@TableField
private String title;
@TableField
private String msgTitle;
@TableField
private String content;
}

View File

@ -0,0 +1,7 @@
package com.diboot.components.msg.mapper;
import com.diboot.components.msg.entity.Message;
import com.diboot.core.mapper.BaseCrudMapper;
public interface MessageMapper extends BaseCrudMapper<Message> {
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "./mybatis-3-mapper.dtd">
<mapper namespace="com.diboot.components.msg.mapper.MessageMapper">
</mapper>

View File

@ -0,0 +1,7 @@
package com.diboot.components.msg.mapper;
import com.diboot.components.msg.entity.MessageTemplate;
import com.diboot.core.mapper.BaseCrudMapper;
public interface MessageTemplateMapper extends BaseCrudMapper<MessageTemplate> {
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "./mybatis-3-mapper.dtd">
<mapper namespace="com.diboot.components.msg.mapper.MessageTemplateMapper">
</mapper>

View File

@ -0,0 +1,17 @@
package com.diboot.components.msg.service;
import com.diboot.components.msg.entity.BaseMessage;
import com.diboot.components.msg.entity.Message;
public interface BaseSendService {
//发送消息
boolean send(BaseMessage message) throws Exception;
//转化为可发送的消息对象
BaseMessage parseToSendMessage(Message message);
//获取发送消息类型(邮件短信微信等类型)
String getType();
}

View File

@ -0,0 +1,5 @@
package com.diboot.components.msg.service;
public interface EmailSendService extends BaseSendService {
}

View File

@ -0,0 +1,26 @@
package com.diboot.components.msg.service;
import com.diboot.components.msg.entity.Message;
import com.diboot.core.service.BaseService;
public interface MessageService extends BaseService<Message> {
/***
* 保存并发送消息
* @param msg
* @return
*/
boolean createAndSendMsg(Message msg);
/***
* 发送消息
* @param msg
* @return
*/
boolean sendMsg(Message msg);
/***
* 根据消息类型获取对应的发送消息service
*/
BaseSendService getSendService(String type);
}

View File

@ -0,0 +1,7 @@
package com.diboot.components.msg.service;
import com.diboot.components.msg.entity.MessageTemplate;
import com.diboot.core.service.BaseService;
public interface MessageTemplateService extends BaseService<MessageTemplate> {
}

View File

@ -0,0 +1,106 @@
package com.diboot.components.msg.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.diboot.components.msg.config.EmailConfig;
import com.diboot.components.msg.config.MsgCons;
import com.diboot.components.msg.entity.BaseMessage;
import com.diboot.components.msg.entity.EmailMessage;
import com.diboot.components.msg.entity.Message;
import com.diboot.components.msg.service.EmailSendService;
import com.diboot.core.config.Cons;
import com.diboot.core.util.V;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.mail.EmailAttachment;
import org.apache.commons.mail.HtmlEmail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.List;
@Service
@Slf4j
public class EmailSendServiceImpl implements EmailSendService {
private static final Logger logger = LoggerFactory.getLogger(EmailSendServiceImpl.class);
@Autowired
EmailConfig emailConfig;
@Override
public boolean send(BaseMessage message) throws Exception {
EmailMessage emailMessage = (EmailMessage)message;
if(logger.isDebugEnabled()){
logger.debug("发送邮件开始, 收件人:" + message.getReceiver() + ", message=" + message.getContent());
}
if(emailConfig.isEmpty()){
logger.warn("发送邮件相关配置为空,发送失败");
return false;
}
// Create the email message
HtmlEmail email = new HtmlEmail();
email.setHostName(emailConfig.getHost());
email.setCharset(Cons.CHARSET_UTF8);
email.setSSLOnConnect(true);
if(V.notEmpty(emailConfig.getSslport())){
email.setSslSmtpPort(emailConfig.getSslport());
}
email.setAuthentication(emailConfig.getAddress(), emailConfig.getPassword());
email.addTo(emailMessage.getReceiver(), emailMessage.getReceiverName());
if(V.notEmpty(emailMessage.getCcEmails())){
for(String cc : emailMessage.getCcEmails()){
email.addCc(cc);
}
}
email.setFrom(emailConfig.getAddress(), emailConfig.getName());
email.setSubject(emailMessage.getTitle());
// set the html message
email.setHtmlMsg(message.getContent());
// 发送附件
if(V.notEmpty(emailMessage.getFilePaths())){
for(String path : emailMessage.getFilePaths()){
File file = new File(path);
if(!file.exists()){
logger.warn("附件文件不存在无法发送path="+path);
return false;
}
EmailAttachment attachment = new EmailAttachment();
attachment.setName(file.getName());
attachment.setPath(path);
attachment.setDisposition(EmailAttachment.ATTACHMENT);
email.attach(attachment);
}
}
// send the email
email.send();
if(logger.isDebugEnabled()){
logger.debug("发送邮件完成, 收件人:" + message.getReceiver());
}
return true;
}
@Override
public EmailMessage parseToSendMessage(Message message) {
EmailMessage email = new EmailMessage();
email.setReceiver(message.getReceiver());
email.setReceiverName(message.getReceiver());
email.setTitle(message.getTitle());
email.setContent(message.getContent());
JSONArray jsonArray = (JSONArray)message.getFromExt("filePaths");
List<String> filePathList = JSONArray.parseArray(jsonArray.toString(), String.class);
String[] filePaths = filePathList.toArray(new String[0]);
email.setFilePaths(filePaths);
return email;
}
@Override
public String getType() {
return MsgCons.MSG_TYPE.EMAIL.name();
}
}

View File

@ -0,0 +1,67 @@
package com.diboot.components.msg.service.impl;
import com.diboot.components.msg.entity.BaseMessage;
import com.diboot.components.msg.entity.Message;
import com.diboot.components.msg.mapper.MessageMapper;
import com.diboot.components.msg.service.BaseSendService;
import com.diboot.components.msg.service.MessageService;
import com.diboot.core.service.impl.BaseServiceImpl;
import com.diboot.core.util.V;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
@Slf4j
public class MessageServiceImpl extends BaseServiceImpl<MessageMapper, Message> implements MessageService {
private static final Logger logger = LoggerFactory.getLogger(MessageServiceImpl.class);
@Autowired
private Map<String, BaseSendService> sendServiceMap;
@Override
public boolean createAndSendMsg(Message msg) {
boolean success = super.createEntity(msg);
if(success){
success = sendMsg(msg);
}
return success;
}
@Override
public boolean sendMsg(Message msg) {
boolean success = false;
try {
//根据消息类型获取发送消息service
BaseSendService sendService = getSendService(msg.getType());
if(V.isEmpty(sendService)){
logger.warn("没获取到相应发送消息的service");
return false;
}
//将Message对象转化为可发送的消息对象
BaseMessage baseMessage = sendService.parseToSendMessage(msg);
//发送消息
success = sendService.send(baseMessage);
} catch (Exception e) {
logger.warn("消息发送失败", e);
return false;
}
return success;
}
@Override
public BaseSendService getSendService(String type) {
if(V.notEmpty(sendServiceMap)){
for(BaseSendService sendService : sendServiceMap.values()){
if(type.equals(sendService.getType())){
return sendService;
}
}
}
return null;
}
}

View File

@ -0,0 +1,13 @@
package com.diboot.components.msg.service.impl;
import com.diboot.components.msg.entity.MessageTemplate;
import com.diboot.components.msg.mapper.MessageTemplateMapper;
import com.diboot.components.msg.service.MessageTemplateService;
import com.diboot.core.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class MessageTemplateServiceImpl extends BaseServiceImpl<MessageTemplateMapper, MessageTemplate> implements MessageTemplateService {
}

View File

@ -0,0 +1,21 @@
package com.diboot.components.msg.vo;
import com.diboot.components.msg.entity.Message;
import com.diboot.components.msg.entity.MessageTemplate;
import com.diboot.core.binding.annotation.BindDict;
import com.diboot.core.binding.annotation.BindEntity;
import lombok.Data;
@Data
public class MessageVO extends Message {
private static final long serialVersionUID = 141470955506938430L;
@BindDict(type="MSG_TYPE", field="type")
private String typeLabel;
@BindDict(type="MSG_STATUS", field="status")
private String statusLabel;
@BindEntity(entity=MessageTemplate.class, condition="this.template_id=id")
private MessageTemplate messageTemplate;
}

View File

@ -58,5 +58,6 @@ List<User> entityList = userService.getEntityList(queryWrapper);
List<MyUserVO> voList = AnnotationBindingManager.autoConvertAndBind(userList, MyUserVO.class);
~~~
> 本地运行test单元测试需先执行/test/resources/init-{db}.sql到你的数据库暂提供Mysql脚本
> 注解自动绑定实现基于Mybatis-plus需确保你的{Entity}对应的Service,ServiceImpl,Mapper存在。
##### 使用样例请参考 - [diboot-core-example](https://github.com/dibo-software/diboot-v2-example/tree/master/diboot-core-example)

View File

@ -119,10 +119,8 @@ public class FieldBinder<T> extends BaseBinder<T> {
}
// 将结果list转换成map
Map<String, Map<String, Object>> referencedEntityPk2DataMap = new HashMap<>(mapList.size());
// 转换列名为字段名MyBatis-plus的getMapList结果会将列名转成驼峰式
String referencedEntityPkFieldName = S.toLowerCaseCamel(referencedEntityPkName);
for(Map<String, Object> map : mapList){
Object pkVal = map.get(referencedEntityPkFieldName);
Object pkVal = map.get(referencedEntityPkName);
if(pkVal != null){
referencedEntityPk2DataMap.put(String.valueOf(pkVal), map);
}
@ -139,7 +137,7 @@ public class FieldBinder<T> extends BaseBinder<T> {
Map<String, Object> relationMap = referencedEntityPk2DataMap.get(annoObjectId);
if(relationMap != null){
for(int i = 0; i< annoObjectSetterPropNameList.size(); i++){
BeanUtils.setProperty(annoObject, annoObjectSetterPropNameList.get(i), relationMap.get(S.toLowerCaseCamel(referencedGetterColumnNameList.get(i))));
BeanUtils.setProperty(annoObject, annoObjectSetterPropNameList.get(i), relationMap.get(referencedGetterColumnNameList.get(i)));
}
}
}

View File

@ -122,7 +122,7 @@ public class MiddleTable {
sb.append(params).append(")");
if(this.additionalConditions != null){
for(String condition : this.additionalConditions){
sb.append(" AND ").append(condition);
sb.append(" AND (").append(condition).append(")");
}
}
return sb.toString();

View File

@ -207,10 +207,10 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
String[] keyValueArray = sqlSelect.split(Cons.SEPARATOR_COMMA);
List<KeyValue> keyValueList = new ArrayList<>(mapList.size());
for(Map<String, Object> map : mapList){
if(map.get(convert2Hump(keyValueArray[0])) != null){
KeyValue kv = new KeyValue((String)map.get(convert2Hump(keyValueArray[0])), map.get(convert2Hump(keyValueArray[1])));
if(map.get(keyValueArray[0]) != null){
KeyValue kv = new KeyValue((String)map.get(keyValueArray[0]), map.get(keyValueArray[1]));
if(keyValueArray.length > 2){
kv.setExt(map.get(convert2Hump(keyValueArray[2])));
kv.setExt(map.get(keyValueArray[2]));
}
keyValueList.add(kv);
}
@ -218,27 +218,6 @@ public class BaseServiceImpl<M extends BaseCrudMapper<T>, T> extends ServiceImpl
return keyValueList;
}
//将含有_下划线的字符串变成驼峰形式的字符串
public String convert2Hump(String str){
if(str.indexOf("_") < 0){
return str;
}
StringBuffer strBuffer = new StringBuffer();
String [] strs = str.split("_");
if(V.notEmpty(strs)){
for(int i=0; i<strs.length; i++){
String tempStr = null;
if(i > 0){
tempStr = strs[i].substring(0,1).toUpperCase() + strs[i].substring(1);
}else{
tempStr = strs[i];
}
strBuffer.append(tempStr);
}
}
return strBuffer.toString();
}
@Override
public FieldBinder<T> bindingFieldTo(List voList){
return new FieldBinder<>(this, voList);

View File

@ -13,7 +13,7 @@ import java.util.Arrays;
import java.util.List;
/**
* 分页
* 分页 (属性以下划线开头以避免与提交参数字段冲突)
* @author Mazhicheng
* @version v2.0
* @date 2019/01/01

View File

@ -4,6 +4,10 @@ dependencies {
compile project(":diboot-shiro-wx-mp")
compile project(":diboot-shiro-wx-cp")
compile project(":diboot-components-msg")
//
compile ("com.qiniu:qiniu-java-sdk:7.2.7")
testCompile group: 'junit', name: 'junit', version: '4.12'
}

View File

@ -3,6 +3,7 @@ package com.diboot.example.config;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.diboot.core.config.Cons;
import com.diboot.core.util.D;
import com.diboot.core.util.DateConverter;
import org.mybatis.spring.annotation.MapperScan;
@ -10,6 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ -17,6 +19,8 @@ import org.springframework.format.FormatterRegistry;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
@ -29,13 +33,16 @@ import java.util.List;
* @date 2019/1/19
*/
@Configuration
@EnableAutoConfiguration
@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
@EnableTransactionManagement(proxyTargetClass=true)
@ComponentScan(basePackages={"com.diboot"})
@MapperScan({"com.diboot.**.mapper"})
public class SpringMvcConfig implements WebMvcConfigurer{
private static final Logger log = LoggerFactory.getLogger(SpringMvcConfig.class);
//10M
private static final Long MAX_UPLOAD_SIZE = 10*1024*1024L;
/**
* JSON转换组件替换为fastJson
*/
@ -58,6 +65,15 @@ public class SpringMvcConfig implements WebMvcConfigurer{
return new HttpMessageConverters(httpMsgConverter);
}
// 需要文件上传开启此配置
@Bean
public MultipartResolver multipartResolver(){
CommonsMultipartResolver bean = new CommonsMultipartResolver();
bean.setDefaultEncoding(Cons.CHARSET_UTF8);
bean.setMaxUploadSize(MAX_UPLOAD_SIZE);
return bean;
}
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new DateConverter());

View File

@ -0,0 +1,141 @@
package com.diboot.example.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.binding.manager.AnnotationBindingManager;
import com.diboot.core.controller.BaseCrudRestController;
import com.diboot.core.entity.Dictionary;
import com.diboot.core.service.BaseService;
import com.diboot.core.util.V;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Pagination;
import com.diboot.core.vo.Status;
import com.diboot.example.service.DictionaryService;
import com.diboot.example.vo.DictionaryListVO;
import com.diboot.example.vo.DictionaryVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
@RequestMapping("/dictionary")
public class DictionaryController extends BaseCrudRestController {
private static final Logger logger = LoggerFactory.getLogger(DictionaryController.class);
@Autowired
private DictionaryService dictionaryService;
@Override
protected BaseService getService() {
return dictionaryService;
}
/*
* 获取列表页数据
* */
@GetMapping("/list")
public JsonResult list(HttpServletRequest request) throws Exception {
//构建查询条件
QueryWrapper<Dictionary> queryWrapper = buildQuery(request);
queryWrapper.lambda().eq(Dictionary::getParentId, 0)
.orderByAsc(Dictionary::getSortId);
//构建分页
Pagination pagination = buildPagination(request);
//获取实体list
List<Dictionary> dictionaryList = dictionaryService.getEntityList(queryWrapper, pagination);
//筛选出在列表页展示的字段
List<DictionaryListVO> dicVoList = AnnotationBindingManager.autoConvertAndBind(dictionaryList, DictionaryListVO.class);
//返回结果
return new JsonResult(Status.OK, dicVoList).bindPagination(pagination);
}
/*
* 获取entity详细数据
* */
@GetMapping("/{id}")
public JsonResult getEntity(@PathVariable("id") Long id, HttpServletRequest request){
DictionaryVO vo = dictionaryService.getViewObject(id, DictionaryVO.class);
return new JsonResult(vo);
}
/*
* 新建
* */
@PostMapping("/")
public JsonResult create(@RequestBody DictionaryVO entityVO, HttpServletRequest request){
boolean success = dictionaryService.createDictionary(entityVO);
if(success){
return new JsonResult(Status.OK);
}else{
return new JsonResult(Status.FAIL_OPERATION);
}
}
/*
* 更新
* */
@PutMapping("/{id}")
public JsonResult update(@PathVariable("id")Long id, @RequestBody DictionaryVO entityVO, HttpServletRequest request){
entityVO.setId(id);
boolean success = dictionaryService.updateDictionary(entityVO);
if(success){
return new JsonResult(Status.OK);
}else{
return new JsonResult(Status.FAIL_OPERATION);
}
}
/*
* 删除
* */
@DeleteMapping("/{id}")
public JsonResult delete(@PathVariable("id") Long id){
boolean success = dictionaryService.deleteDictionary(id);
if(success){
return new JsonResult(Status.OK);
}else{
return new JsonResult(Status.FAIL_OPERATION );
}
}
/*
* 校验类型编码是否重复
* */
@GetMapping("/checkTypeRepeat")
public JsonResult checkUsernameRepeat(@RequestParam("id") Long id,@RequestParam("type") String type, HttpServletRequest request){
if(V.notEmpty(type)){
QueryWrapper<Dictionary> wrapper = new QueryWrapper();
wrapper.lambda().eq(Dictionary::getType, type)
.eq(Dictionary::getParentId, 0)
;
List<Dictionary> dictionaryList = dictionaryService.getEntityList(wrapper);
if(V.isEmpty(id)){//新建时
if(V.notEmpty(dictionaryList)){
return new JsonResult(Status.FAIL_OPERATION, "类型编码已存在");
}
}else{//更新时
Dictionary dictionary = dictionaryService.getEntity(id);
if(V.notEmpty(dictionary)){
if(V.notEmpty(dictionaryList)){
if(dictionaryList.size() >= 2){
return new JsonResult(Status.FAIL_OPERATION, "类型编码已存在");
}else if(!(dictionary.getId().equals(dictionaryList.get(0).getId()))){
return new JsonResult(Status.FAIL_OPERATION, "类型编码已存在");
}
}
}else{
if(V.notEmpty(dictionaryList)){
return new JsonResult(Status.FAIL_OPERATION, "类型编码已存在");
}
}
}
}
return new JsonResult(Status.OK);
}
}

View File

@ -0,0 +1,147 @@
package com.diboot.example.controller;
import com.diboot.core.config.BaseConfig;
import com.diboot.core.util.S;
import com.diboot.core.util.V;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Status;
import com.diboot.example.util.QiniuHelper;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/upload")
public class FileUploadController {
private static final Logger logger = LoggerFactory.getLogger(FileUploadController.class);
private static String SAVE_PATH = BaseConfig.getProperty("files.storage.directory");
/*
* 单图片
* */
@PostMapping("/image")
public JsonResult imageUpload(@RequestParam("image") MultipartFile image, ModelMap modelMap, HttpServletRequest request){
String fileName = saveFile(image);
if(V.notEmpty(fileName)){
modelMap.put("url", fileName);
modelMap.put("status", "done");
return new JsonResult(modelMap);
}
modelMap.put("status", "error");
return new JsonResult(Status.FAIL_OPERATION, modelMap);
}
/*
* 多图片
* */
@PostMapping("/images")
public JsonResult imagesUpload(@RequestParam("images") MultipartFile[] images, ModelMap modelMap, HttpServletRequest request){
if(V.notEmpty(images)){
List<String> fileNameList = new ArrayList();
for(MultipartFile image : images){
String fileName = saveFile(image);
if(V.notEmpty(fileName)){
fileNameList.add(fileName);
}else{
logger.warn("有文件上传失败:"+image.getOriginalFilename());
}
}
if(V.notEmpty(fileNameList)){
modelMap.put("url", fileNameList);
modelMap.put("status", "done");
return new JsonResult(modelMap);
}
}
modelMap.put("status", "error");
return new JsonResult(Status.FAIL_OPERATION, modelMap);
}
/*
* 单文件
* */
@PostMapping("/office")
public JsonResult officeUpload(@RequestParam("office") MultipartFile office, ModelMap modelMap, HttpServletRequest request){
String fileName = saveFile(office);
if(V.notEmpty(fileName)){
modelMap.put("url", fileName);
modelMap.put("status", "done");
return new JsonResult(modelMap);
}
modelMap.put("status", "error");
return new JsonResult(Status.FAIL_OPERATION, modelMap);
}
/*
* 多文件
* */
@PostMapping("/offices")
public JsonResult officesUpload(@RequestParam("offices") MultipartFile[] offices, ModelMap modelMap, HttpServletRequest request){
if(V.notEmpty(offices)){
List<String> fileNameList = new ArrayList();
for(MultipartFile office : offices){
String fileName = saveFile(office);
if(V.notEmpty(fileName)){
fileNameList.add(fileName);
}else{
logger.warn("有文件上传失败:"+office.getOriginalFilename());
}
}
if(V.notEmpty(fileNameList)){
modelMap.put("url", fileNameList);
modelMap.put("status", "done");
return new JsonResult(modelMap);
}
}
return new JsonResult(Status.FAIL_OPERATION, modelMap);
}
public String saveFile(MultipartFile file){
if(V.isEmpty(file)){
return null;
}
String fileName = file.getOriginalFilename();
String ext = fileName.substring(fileName.lastIndexOf(".")+1);
String newFileName = S.newUuid() + "." + ext;
String fullPath = SAVE_PATH + newFileName;
File f = new File(fullPath);
if(!f.exists()){
try {
FileUtils.writeByteArrayToFile(f, file.getBytes());
if(logger.isDebugEnabled()){
logger.info("文件保存成功");
return fullPath;
//如果上传文件到七牛打开此注释
/*String link = QiniuHelper.uploadFile2Qiniu(newFileName, SAVE_PATH);
if(V.notEmpty(link)){
logger.info("文件上传七牛成功");
return link;
}*/
}
} catch (IOException e) {
logger.error("文件保存失败");
e.printStackTrace();
}
}
return null;
}
}

View File

@ -51,7 +51,6 @@ public class SysUserController extends BaseCrudRestController {
@GetMapping("/list")
public JsonResult getVOList(HttpServletRequest request) throws Exception{
System.out.println(SysUser.class.getSimpleName());
QueryWrapper<SysUser> queryWrapper = buildQuery(request);
// 构建分页
Pagination pagination = buildPagination(request);
@ -174,7 +173,7 @@ public class SysUserController extends BaseCrudRestController {
* 校验用户名是否重复
* */
@GetMapping("/checkUsernameRepeat")
public JsonResult checkUsernameRepeat(Long id, String username, HttpServletRequest request){
public JsonResult checkUsernameRepeat(@RequestParam("id") Long id,@RequestParam("username") String username, HttpServletRequest request){
if(V.notEmpty(username)){
QueryWrapper<SysUser> wrapper = new QueryWrapper();
wrapper.lambda().eq(SysUser::getUsername, username);

View File

@ -0,0 +1,23 @@
package com.diboot.example.service;
import com.diboot.core.entity.Dictionary;
import com.diboot.core.service.BaseService;
import com.diboot.example.vo.DictionaryVO;
/**
* 数据字典相关Service
* @author Wangyongliang
* @version v2.0
* @date 2019/7/8
*/
public interface DictionaryService extends BaseService<Dictionary> {
//新增
boolean createDictionary(DictionaryVO entity);
//更新
boolean updateDictionary(DictionaryVO entity);
//删除
boolean deleteDictionary(Long id);
}

View File

@ -0,0 +1,125 @@
package com.diboot.example.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.binding.manager.AnnotationBindingManager;
import com.diboot.core.entity.Dictionary;
import com.diboot.core.mapper.DictionaryMapper;
import com.diboot.core.service.impl.BaseServiceImpl;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.V;
import com.diboot.example.service.DictionaryService;
import com.diboot.example.vo.DictionaryVO;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* 数据字典相关Service
* @author Wangyongliang
* @version v2.0
* @date 2019/7/8
*/
@Service("dictionaryService")
@Slf4j
public class DictionaryServiceImpl extends BaseServiceImpl<DictionaryMapper, Dictionary> implements DictionaryService {
private static final Logger logger = LoggerFactory.getLogger(DictionaryServiceImpl.class);
@Override
@Transactional
public boolean createDictionary(DictionaryVO entityVO) {
//将DictionaryVO转化为Dictionary
Dictionary dictionary = new Dictionary();
dictionary = (Dictionary)BeanUtils.copyProperties(entityVO, dictionary);
if(!super.createEntity(dictionary)){
logger.warn("新建父数据字典失败type="+entityVO.getType());
return false;
}
List<Dictionary> children = entityVO.getChildren();
if(V.notEmpty(children)){
try {
for(Dictionary dict : children){
dict.setParentId(dictionary.getId());
dict.setType(dictionary.getType());
}
if(!super.createEntities(children)){
logger.warn("新建子数据字典失败type="+entityVO.getType());
throw new RuntimeException();
}
} catch (Exception e) {
logger.warn("新建子数据字典失败type="+entityVO.getType());
throw new RuntimeException();
}
}
return true;
}
@Override
@Transactional
public boolean updateDictionary(DictionaryVO entityVO) {
//将DictionaryVO转化为Dictionary
Dictionary dictionary = new Dictionary();
dictionary = (Dictionary)BeanUtils.copyProperties(entityVO, dictionary);
if(!super.updateEntity(dictionary)){
logger.warn("更新父数据字典失败type="+entityVO.getType());
return false;
}
//获取原 子数据字典list
QueryWrapper<Dictionary> queryWrapper = new QueryWrapper();
queryWrapper.lambda().eq(Dictionary::getParentId, entityVO.getId());
List<Dictionary> oldDictList = super.getEntityList(queryWrapper);
List<Dictionary> newDictList = entityVO.getChildren();
StringBuffer newBuffer = new StringBuffer();
if(V.notEmpty(newDictList)){
for(Dictionary dict : newDictList){
dict.setType(entityVO.getType());
dict.setParentId(entityVO.getId());
if(V.notEmpty(dict.getId())){
newBuffer.append(dict.getId()).append(",");
if(!super.updateEntity(dict)){
logger.warn("更新子数据字典失败itemName="+dict.getItemName());
throw new RuntimeException();
}
}else{
if(!super.createEntity(dict)){
logger.warn("新建子数据字典失败itemName="+dict.getItemName());
throw new RuntimeException();
}
}
}
}
if(V.notEmpty(oldDictList)){
for(Dictionary dict : oldDictList){
if(!(newBuffer.toString().contains(dict.getId().toString()))){
if(!super.deleteEntity(dict.getId())){
logger.warn("删除子数据字典失败itemName="+dict.getItemName());
throw new RuntimeException();
}
}
}
}
return true;
}
@Override
public boolean deleteDictionary(Long id) {
QueryWrapper<Dictionary> queryWrapper = new QueryWrapper();
queryWrapper.lambda().eq(Dictionary::getId, id)
.or()
.eq(Dictionary::getParentId, id);
try {
super.deleteEntities(queryWrapper);
} catch (Exception e) {
logger.warn("删除数据字典失败", e);
return false;
}
return true;
}
}

View File

@ -0,0 +1,80 @@
package com.diboot.example.util;
import com.diboot.core.config.BaseConfig;
import com.diboot.core.util.S;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
/**
* @author wangyongliang
* @version 2019/7/4
*/
public class QiniuHelper {
private static final Logger logger = LoggerFactory.getLogger(QiniuHelper.class);
private static String accessKey = BaseConfig.getProperty("qiniu.key.access");
private static String secretKey = BaseConfig.getProperty("qiniu.key.secret");
private static String bucket = BaseConfig.getProperty("qiniu.bucket.name");
private static String imageDomain = BaseConfig.getProperty("qiniu.image.domain");
public static String getAccessKey(){
return accessKey;
}
public static String getSecretKey(){
return secretKey;
}
public static String getBucket(){
return bucket;
}
/***
* 上传文件到七牛
* @param fileName
* @return
*/
public static String uploadFile2Qiniu(String fileName, String savePath){
//构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(Zone.zone0());
//...其他参数参考类注释
UploadManager uploadManager = new UploadManager(cfg);
//默认不指定key的情况下以文件内容的hash值作为文件名
Auth auth = Auth.create(accessKey, secretKey);
String upToken = auth.uploadToken(bucket);
String localImageFullPath = savePath+fileName;
try {
Response response = uploadManager.put(localImageFullPath, S.newUuid(), upToken);
//解析上传成功的结果
DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
// 返回全路径URL
if(putRet.key != null){
//删除零时文件
File wavFile = new File(localImageFullPath);
if(wavFile.exists()){
wavFile.delete();
}
return imageDomain + putRet.key;
}
}
catch (QiniuException ex) {
Response r = ex.response;
logger.error(r.toString());
try {
logger.error(r.bodyString());
} catch (QiniuException ex2) {
//ignore
}
}
return fileName;
}
}

View File

@ -0,0 +1,21 @@
package com.diboot.example.vo;
import lombok.Data;
import java.util.Date;
@Data
public class DictionaryListVO {
private Long id;
private String type;
private String itemName;
private String itemValue;
private String comment;
private Date createTime;
}

View File

@ -0,0 +1,16 @@
package com.diboot.example.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.diboot.core.binding.annotation.BindEntityList;
import com.diboot.core.entity.Dictionary;
import lombok.Data;
import java.util.List;
@Data
public class DictionaryVO extends Dictionary {
@BindEntityList(entity=Dictionary.class, condition="this.type=type AND parent_id>0 AND deleted=0")
private List<Dictionary> children;
}

View File

@ -6,6 +6,19 @@ spring.server.protocol=org.apache.coyote.http11.Http11Nio2Protocol
spring.server.redirectPort=443
spring.server.compression=on
#文件请求大小
spring.server.MaxFileSize=10MB
spring.server.MaxRequestSize=50MB
#文件本地存放路径
files.storage.directory=C:/Users/wuweiqing/Downloads/upload/
#七牛
qiniu.key.access=xJPWOwatadCt8ANWPaxrhj3Dj8DGIFoN9jD29SCP
qiniu.key.secret=IbWRTTXdOKoD8qdpug7Xm+rTXX2yhKuh8tfY6Ov4t1SDq/P1oT4cbREWnbgXofwt
qiniu.bucket.name=thirdparty
qiniu.image.domain=http://thirdparty.dibo.ltd/
# spring config
spring.devtools.restart.enabled=true
@ -62,6 +75,19 @@ logging.level.com.diboot=debug
logging.level.org.mybatis=debug
#邮件发送配置
#发送方邮箱
email.sender.address=
#发送方授权码
email.sender.password=
#SMTP发送服务器的名字
email.sender.host=smtp.163.com
#发送端口
email.sender.sslport=
#发送方称呼
email.sender.name=wangyl
#权限配置
#是否存储数据库:默认不开启
diboot.shiro.auth.storage=true

View File

@ -16,10 +16,7 @@ import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@ -43,13 +40,11 @@ public class CpAuthTokenController {
* @throws Exception
*/
@GetMapping("/buildOAuthUrl")
public JsonResult buildOAuthUrl4cp(HttpServletRequest request) throws Exception{
String url = request.getParameter("url");
String agentId = request.getParameter("agentId");//应用ID
public JsonResult buildOAuthUrl4cp(@RequestParam("url") String url,@RequestParam("agentId") Integer agentId, HttpServletRequest request) throws Exception{
if (V.isEmpty(url)){
return new JsonResult(Status.FAIL_OPERATION, new String[]{"url为空获取OAuth链接失败"});
}
wxCpService = (WxCpServiceExtImpl)WxCpConfig.getCpService(Integer.parseInt(agentId));
wxCpService = (WxCpServiceExtImpl)WxCpConfig.getCpService(agentId);
String oauthUrl = wxCpService.getOauth2Service().buildAuthorizationUrl(url, null, WxConsts.OAuth2Scope.SNSAPI_PRIVATEINFO);
return new JsonResult(Status.OK, oauthUrl, new String[]{"获取OAuth链接成功"});
@ -62,8 +57,7 @@ public class CpAuthTokenController {
* @throws Exception
*/
@PostMapping("/apply")
public JsonResult applyTokenByOAuth2cp(HttpServletRequest request) throws Exception{
String code = request.getParameter("code");
public JsonResult applyTokenByOAuth2cp(@RequestParam("code") String code, HttpServletRequest request) throws Exception{
String userId = "";
if (JwtHelper.isRequestTokenEffective(request)){
String account = JwtHelper.getAccountFromToken(JwtHelper.getRequestToken(request));

View File

@ -14,4 +14,5 @@ include 'diboot-shiro'
include 'diboot-shiro-wx-mp'
include 'diboot-docs'
include 'diboot-shiro-wx-cp'
include 'diboot-components-msg'