目录:

  1 数据库密码加密

  2 service层概述

  3 web层概述

  4 后端CRUD

    4.1 READ

    4.2 UPDATE

    4.3 CREATE

    4.4 DELETE

  5 facade层概述

1 数据库密码加密

  iBase4J项目的service层中数据库配置文件中数据库的连接密码必须是经过加密过后的,如何获取加密方法

  1.1 加密类是 org.ibase4j.core.util.PropertiesUtil

end

2 Service层

  2.1 所有service层都继承于BaseService

package top.ibase4j.core.base;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page; import top.ibase4j.core.Constants;
import top.ibase4j.core.util.CacheUtil;
import top.ibase4j.core.util.DataUtil;
import top.ibase4j.core.util.ExceptionUtil;
import top.ibase4j.core.util.InstanceUtil;
import top.ibase4j.core.util.PropertiesUtil; /**
* 业务逻辑层基类,继承基类后必须配置CacheConfig(cacheNames="")
*
* @author ShenHuaJie
* @version 2016年5月20日 下午3:19:19
*/
public abstract class BaseService<T extends BaseModel> implements ApplicationContextAware {
protected Logger logger = LogManager.getLogger(getClass());
@Autowired
protected BaseMapper<T> mapper; protected ApplicationContext applicationContext; int maxThread = PropertiesUtil.getInt("db.reader.list.maxThread", 50);
int threadSleep = PropertiesUtil.getInt("db.reader.list.threadWait", 5);
ExecutorService executorService = Executors.newFixedThreadPool(maxThread); /**
* 分页查询
* @param params
* @return
*/
@SuppressWarnings("unchecked")
public static Page<Long> getPage(Map<String, Object> params) {
Integer current = 1;
Integer size = 10;
String orderBy = "id_", sortAsc = null;
if (DataUtil.isNotEmpty(params.get("pageNumber"))) {
current = Integer.valueOf(params.get("pageNumber").toString());
}
if (DataUtil.isNotEmpty(params.get("pageIndex"))) {
current = Integer.valueOf(params.get("pageIndex").toString());
}
if (DataUtil.isNotEmpty(params.get("pageSize"))) {
size = Integer.valueOf(params.get("pageSize").toString());
}
if (DataUtil.isNotEmpty(params.get("limit"))) {
size = Integer.valueOf(params.get("limit").toString());
}
if (DataUtil.isNotEmpty(params.get("offset"))) {
current = Integer.valueOf(params.get("offset").toString()) / size + 1;
}
if (DataUtil.isNotEmpty(params.get("sort"))) {
orderBy = (String)params.get("sort");
params.remove("sort");
}
if (DataUtil.isNotEmpty(params.get("orderBy"))) {
orderBy = (String)params.get("orderBy");
params.remove("orderBy");
}
if (DataUtil.isNotEmpty(params.get("sortAsc"))) {
sortAsc = (String)params.get("sortAsc");
params.remove("sortAsc");
}
Object filter = params.get("filter");
if (filter != null) {
params.clear();
params.putAll(JSON.parseObject(filter.toString(), Map.class));
}
if (size == -1) {
Page<Long> page = new Page<Long>();
page.setOrderByField(orderBy);
page.setAsc("Y".equals(sortAsc));
return page;
}
Page<Long> page = new Page<Long>(current, size, orderBy);
page.setAsc("Y".equals(sortAsc));
return page;
} /**
* @param id
* @param userId
*/
@Transactional
public void del(Long id, Long userId) {
try {
T record = this.queryById(id);
record.setEnable(0);
record.setUpdateTime(new Date());
record.setUpdateBy(userId);
mapper.updateById(record);
try {
CacheUtil.getCache().set(getCacheKey(id), record);
} catch (Exception e) {
logger.error(Constants.Exception_Head, e);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
} /**
* @param id
*/
@Transactional
public void delete(Long id) {
try {
mapper.deleteById(id);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
try {
CacheUtil.getCache().del(getCacheKey(id));
} catch (Exception e) {
logger.error(Constants.Exception_Head, e);
}
} /**
* @param t
* @return
*/
@Transactional
public Integer deleteByEntity(T t) {
Wrapper<T> wrapper = new EntityWrapper<T>(t);
return mapper.delete(wrapper);
} /**
* @param columnMap
* @return
*/
@Transactional
public Integer deleteByMap(Map<String, Object> columnMap) {
return mapper.deleteByMap(columnMap);
} /**
* 根据Id查询(默认类型T)
* @param ids
* @return
*/
public List<T> getList(final List<Long> ids) {
final List<T> list = InstanceUtil.newArrayList();
if (ids != null) {
for (int i = 0; i < ids.size(); i++) {
list.add(null);
}
final Map<Integer, Object> thread = InstanceUtil.newConcurrentHashMap();
for (int i = 0; i < ids.size(); i++) {
final int index = i;
executorService.execute(new Runnable() {
public void run() {
try {
list.set(index, queryById(ids.get(index)));
} finally {
thread.put(index, 0);
}
}
});
}
while (thread.size() < list.size()) {
try {
Thread.sleep(threadSleep);
} catch (InterruptedException e) {
logger.error("", e);
}
}
}
return list;
} /**
* 根据Id查询(cls返回类型Class)
* @param ids
* @param cls
* @return
*/
public <K> List<K> getList(final List<Long> ids, final Class<K> cls) {
final List<K> list = InstanceUtil.newArrayList();
if (ids != null) {
for (int i = 0; i < ids.size(); i++) {
list.add(null);
}
final Map<Integer, Object> thread = InstanceUtil.newConcurrentHashMap();
for (int i = 0; i < ids.size(); i++) {
final int index = i;
executorService.execute(new Runnable() {
public void run() {
try {
T t = queryById(ids.get(index));
K k = InstanceUtil.to(t, cls);
list.set(index, k);
} finally {
thread.put(index, 0);
}
}
});
}
while (thread.size() < list.size()) {
try {
Thread.sleep(threadSleep);
} catch (InterruptedException e) {
logger.error("", e);
}
}
}
return list;
} /**
* 根据Id查询(默认类型T)
* @param ids
* @return
*/
public Page<Map<String, Object>> getPageMap(final Page<Long> ids) {
if (ids != null) {
Page<Map<String, Object>> page = new Page<Map<String, Object>>(ids.getCurrent(), ids.getSize());
page.setTotal(ids.getTotal());
final List<Map<String, Object>> records = InstanceUtil.newArrayList();
for (int i = 0; i < ids.getRecords().size(); i++) {
records.add(null);
}
final Map<Integer, Object> thread = InstanceUtil.newConcurrentHashMap();
for (int i = 0; i < ids.getRecords().size(); i++) {
final int index = i;
executorService.execute(new Runnable() {
public void run() {
try {
records.set(index, InstanceUtil.transBean2Map(queryById(ids.getRecords().get(index))));
} finally {
thread.put(index, 0);
}
}
});
}
while (thread.size() < records.size()) {
try {
Thread.sleep(threadSleep);
} catch (InterruptedException e) {
logger.error("", e);
}
}
page.setRecords(records);
return page;
}
return new Page<Map<String, Object>>();
} /**
* @param params
* @return
*/
public Page<T> query(Map<String, Object> params) {
Page<Long> page = getPage(params);
page.setRecords(mapper.selectIdPage(page, params));
return getPage(page);
} /**
* @param id
* @return
*/
@Transactional
public T queryById(Long id) {
return queryById(id, 1);
} /**
* @param params
* @return
*/
public List<T> queryList(Map<String, Object> params) {
List<Long> ids = mapper.selectIdPage(params);
List<T> list = getList(ids);
return list;
} /**
* @param entity
* @return
*/
public List<T> selectList(Wrapper<T> entity) {
return mapper.selectList(entity);
} /**
* @param entity
* @return
*/
public T selectOne(T entity) {
return mapper.selectOne(entity);
} /* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.
* ApplicationContext) */
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
} /**
* @param record
* @return
*/
@SuppressWarnings("unchecked")
@Transactional
public T update(T record) {
try {
record.setUpdateTime(new Date());
if (record.getId() == null) {
record.setCreateTime(new Date());
mapper.insert(record);
try {
CacheUtil.getCache().set(getCacheKey(record.getId()), record);
} catch (Exception e) {
logger.error(Constants.Exception_Head, e);
}
} else {
String lockKey = getLockKey("U" + record.getId());
if (CacheUtil.tryLock(lockKey)) {
try {
T org = null;
String key = getCacheKey(record.getId());
try {
org = (T)CacheUtil.getCache().get(key);
} catch (Exception e) {
logger.error(Constants.Exception_Head, e);
}
if (org == null) {
org = mapper.selectById(record.getId());
} T update = InstanceUtil.getDiff(org, record);
update.setId(record.getId());
mapper.updateById(update);
record = mapper.selectById(record.getId());
try {
CacheUtil.getCache().set(key, record);
} catch (Exception e) {
logger.error(Constants.Exception_Head, e);
}
} finally {
CacheUtil.unlock(lockKey);
}
} else {
throw new RuntimeException("数据不一致!请刷新页面重新编辑!");
}
}
} catch (DuplicateKeyException e) {
logger.error(Constants.Exception_Head, e);
throw new RuntimeException("已经存在相同的配置.");
} catch (Exception e) {
logger.error(Constants.Exception_Head, e);
throw new RuntimeException(ExceptionUtil.getStackTraceAsString(e));
}
return record;
} /**
* 获取缓存键值
* @param id
* @return
*/
protected String getCacheKey(Object id) {
String cacheName = getCacheKey();
return new StringBuilder(Constants.CACHE_NAMESPACE).append(cacheName).append(":").append(id).toString();
} /**
* 获取缓存键值
* @param id
* @return
*/
protected String getLockKey(Object id) {
String cacheName = getCacheKey();
return new StringBuilder(Constants.CACHE_NAMESPACE).append(cacheName).append(":LOCK:").append(id).toString();
} /**
* @param params
* @param cls
* @return
*/
protected <P> Page<P> query(Map<String, Object> params, Class<P> cls) {
Page<Long> page = getPage(params);
page.setRecords(mapper.selectIdPage(page, params));
return getPage(page, cls);
} /**
* @param millis
*/
protected void sleep(int millis) {
try {
Thread.sleep(RandomUtils.nextLong(10, millis));
} catch (InterruptedException e) {
logger.error("", e);
}
} /**
* @return
*/
private String getCacheKey() {
Class<?> cls = getClass();
String cacheName = Constants.cacheKeyMap.get(cls);
if (StringUtils.isBlank(cacheName)) {
CacheConfig cacheConfig = cls.getAnnotation(CacheConfig.class);
if (cacheConfig != null && ArrayUtils.isNotEmpty(cacheConfig.cacheNames())) {
cacheName = cacheConfig.cacheNames()[0];
} else {
cacheName = getClass().getName();
}
Constants.cacheKeyMap.put(cls, cacheName);
}
return cacheName;
} /** 根据Id查询(默认类型T) */
private Page<T> getPage(final Page<Long> ids) {
if (ids != null) {
Page<T> page = new Page<T>(ids.getCurrent(), ids.getSize());
page.setTotal(ids.getTotal());
final List<T> records = InstanceUtil.newArrayList();
for (int i = 0; i < ids.getRecords().size(); i++) {
records.add(null);
}
final Map<Integer, Object> thread = InstanceUtil.newConcurrentHashMap();
for (int i = 0; i < ids.getRecords().size(); i++) {
final int index = i;
executorService.execute(new Runnable() {
public void run() {
try {
records.set(index, queryById(ids.getRecords().get(index)));
} finally {
thread.put(index, 0);
}
}
});
}
while (thread.size() < records.size()) {
try {
Thread.sleep(threadSleep);
} catch (InterruptedException e) {
logger.error("", e);
}
}
page.setRecords(records);
return page;
}
return new Page<T>();
} /** 根据Id查询(cls返回类型Class) */
private <K> Page<K> getPage(final Page<Long> ids, final Class<K> cls) {
if (ids != null) {
Page<K> page = new Page<K>(ids.getCurrent(), ids.getSize());
page.setTotal(ids.getTotal());
final List<K> records = InstanceUtil.newArrayList();
for (int i = 0; i < ids.getRecords().size(); i++) {
records.add(null);
}
final Map<Integer, Object> thread = InstanceUtil.newConcurrentHashMap();
for (int i = 0; i < ids.getRecords().size(); i++) {
final int index = i;
executorService.execute(new Runnable() {
public void run() {
try {
T t = queryById(ids.getRecords().get(index));
K k = InstanceUtil.to(t, cls);
records.set(index, k);
} finally {
thread.put(index, 0);
}
}
});
}
while (thread.size() < records.size()) {
try {
Thread.sleep(threadSleep);
} catch (InterruptedException e) {
logger.error("", e);
}
}
page.setRecords(records);
return page;
}
return new Page<K>();
} @SuppressWarnings("unchecked")
private T queryById(Long id, int times) {
String key = getCacheKey(id);
T record = null;
try {
record = (T)CacheUtil.getCache().get(key);
} catch (Exception e) {
logger.error(Constants.Exception_Head, e);
}
if (record == null) {
String lockKey = getLockKey(id);
if (CacheUtil.tryLock(lockKey)) {
try {
record = mapper.selectById(id);
try {
CacheUtil.getCache().set(key, record);
} catch (Exception e) {
logger.error(Constants.Exception_Head, e);
}
} finally {
CacheUtil.unlock(lockKey);
}
} else {
if (times > 3) {
return mapper.selectById(id);
}
logger.debug(getClass().getSimpleName() + ":" + id + " retry queryById.");
sleep(20);
return queryById(id, times + 1);
}
}
return record;
}
}

BaseService

    技巧01:BaseService类实现了ApplicationContextAware后就可以通过ApplicationContext类型的成员变量去获取在spring容器中定义的其他bean了

protected ApplicationContext applicationContext;

      参考文档:点击前往

    技巧02:BaseService类提供了一些类的数据操作方法

  2.2 SysUserService类的query方法详解

    注意:仅仅解释如何获取数据,权限先关的暂时还未弄清楚,当更新

    

    2.2.1 调用父类的query方法

      技巧01:query方法是一个没有约束的查询方法,该方法的参数是和分页查询有关的,不涉及任何与条件查询相关的参数

/**
* @param params
* @return
*/
public Page<T> query(Map<String, Object> params) {
Page<Long> page = getPage(params);
page.setRecords(mapper.selectIdPage(page, params));
return getPage(page);
}

      技巧02:从query方法的源代码中可以看出,query方法调用了BaseService类中的getPage方法

    /**
* 分页查询
* @param params
* @return
*/
@SuppressWarnings("unchecked")
public static Page<Long> getPage(Map<String, Object> params) {
Integer current = 1;
Integer size = 10;
String orderBy = "id_", sortAsc = null;
if (DataUtil.isNotEmpty(params.get("pageNumber"))) {
current = Integer.valueOf(params.get("pageNumber").toString());
}
if (DataUtil.isNotEmpty(params.get("pageIndex"))) {
current = Integer.valueOf(params.get("pageIndex").toString());
}
if (DataUtil.isNotEmpty(params.get("pageSize"))) {
size = Integer.valueOf(params.get("pageSize").toString());
}
if (DataUtil.isNotEmpty(params.get("limit"))) {
size = Integer.valueOf(params.get("limit").toString());
}
if (DataUtil.isNotEmpty(params.get("offset"))) {
current = Integer.valueOf(params.get("offset").toString()) / size + 1;
}
if (DataUtil.isNotEmpty(params.get("sort"))) {
orderBy = (String)params.get("sort");
params.remove("sort");
}
if (DataUtil.isNotEmpty(params.get("orderBy"))) {
orderBy = (String)params.get("orderBy");
params.remove("orderBy");
}
if (DataUtil.isNotEmpty(params.get("sortAsc"))) {
sortAsc = (String)params.get("sortAsc");
params.remove("sortAsc");
}
Object filter = params.get("filter");
if (filter != null) {
params.clear();
params.putAll(JSON.parseObject(filter.toString(), Map.class));
}
if (size == -1) {
Page<Long> page = new Page<Long>();
page.setOrderByField(orderBy);
page.setAsc("Y".equals(sortAsc));
return page;
}
Page<Long> page = new Page<Long>(current, size, orderBy);
page.setAsc("Y".equals(sortAsc));
return page;
}

getPage

      技巧03:getPage方法主要是查看query方法中的参数是否有和分页查询相关的参数,如果有就将这些参数封装成一个对象返回给query方法使用

      技巧04:mapper.selectIdPage(page, params)的作用是调用相应的mapper接口去获取数据

      技巧05:page.setRecords(mapper.selectIdPage(page, params));的作用是将获取到的数据封装到一个page对象中

      技巧06:getPage(page);的作用是对获取到的数据进一步进行封装,仅仅将需要查询的页码数据进行封装

    2.2.2 向web层返回一个Page对象

      技巧01:该Page对象封装了查询到的数据信息,以及一些分页查询参数

end

3 Web层

  3.1 所有的web层都会继承AbstractController

/**
*
*/
package top.ibase4j.core.base; import java.util.Date;
import java.util.List;
import java.util.Map; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap; import com.baomidou.mybatisplus.plugins.Page; /**
* 控制器基类
*
* @author ShenHuaJie
* @version 2016年5月20日 下午3:47:58
*/
public abstract class AbstractController<T extends BaseProvider> extends BaseController {
protected final Logger logger = LogManager.getLogger(this.getClass());
@Autowired
protected T provider; public abstract String getService(); public Object query(ModelMap modelMap, Map<String, Object> param) {
if (param.get("keyword") == null && param.get("search") != null) {
param.put("keyword", param.get("search"));
}
Parameter parameter = new Parameter(getService(), "query", param);
logger.info("{} execute query start...", parameter.getNo());
Page<?> list = provider.execute(parameter).getResultPage();
logger.info("{} execute query end.", parameter.getNo());
return setSuccessModelMap(modelMap, list);
} public Object queryList(ModelMap modelMap, Map<String, Object> param) {
Parameter parameter = new Parameter(getService(), "queryList", param);
logger.info("{} execute queryList start...", parameter.getNo());
List<?> list = provider.execute(parameter).getResultList();
logger.info("{} execute queryList end.", parameter.getNo());
return setSuccessModelMap(modelMap, list);
} public Object get(ModelMap modelMap, BaseModel param) {
Parameter parameter = new Parameter(getService(), "queryById", param.getId());
logger.info("{} execute queryById start...", parameter.getNo());
Object result = provider.execute(parameter).getResult();
logger.info("{} execute queryById end.", parameter.getNo());
return setSuccessModelMap(modelMap, result);
} public Object update(ModelMap modelMap, BaseModel param) {
Long userId = getCurrUser();
if (param.getId() == null) {
param.setCreateBy(userId);
param.setCreateTime(new Date());
}
param.setUpdateBy(userId);
param.setUpdateTime(new Date());
Parameter parameter = new Parameter(getService(), "update", param);
logger.info("{} execute update start...", parameter.getNo());
provider.execute(parameter);
logger.info("{} execute update end.", parameter.getNo());
return setSuccessModelMap(modelMap);
} public Object delete(ModelMap modelMap, BaseModel param) {
Parameter parameter = new Parameter(getService(), "delete", param.getId());
logger.info("{} execute delete start...", parameter.getNo());
provider.execute(parameter);
logger.info("{} execute delete end.", parameter.getNo());
return setSuccessModelMap(modelMap);
}
}

AbstractController

    技巧01:AbstractController中的BaseProvider对象通过excute方法去调用Service层相关方法,excute方法接收的是一个包含service名称、service中的方法名称、参数封装成的的Parameter对象;Page<?> list = provider.execute(parameter).getResultPage()的作用是将从service层查询到的数据放到一个Page对象中;return setSuccessModelMap(modelMap, list)的作用是将数据进行封装并放回给前端

    技巧02:AbsstractController中的抽象方法getService是用来指定调用那个Service的,返回值是一个字符串;所有继承自AbsstractController的类都必须实现该方法,因为在调用Service层的时候回用到该方法,而且该方法在AbsstractController是一个抽象方法,所有的子类必须实现

  3.2 AbstractController还继承自BaseController接口

    该接口提供了最外层数据的封装方法

/**
*
*/
package top.ibase4j.core.base; import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.plugins.Page; import top.ibase4j.core.Constants;
import top.ibase4j.core.exception.BaseException;
import top.ibase4j.core.exception.IllegalParameterException;
import top.ibase4j.core.support.DateFormat;
import top.ibase4j.core.support.HttpCode;
import top.ibase4j.core.util.InstanceUtil;
import top.ibase4j.core.util.WebUtil; /**
* 控制器基类
*
* @author ShenHuaJie
* @version 2016年5月20日 下午3:47:58
*/
public abstract class BaseController {
protected final Logger logger = LogManager.getLogger(this.getClass()); /** 获取当前用户Id */
protected Long getCurrUser() {
return WebUtil.getCurrentUser();
} @InitBinder
protected void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new DateFormat(), true));
} /** 设置成功响应代码 */
protected ResponseEntity<ModelMap> setSuccessModelMap(ModelMap modelMap) {
return setSuccessModelMap(modelMap, null);
} /** 设置成功响应代码 */
protected ResponseEntity<ModelMap> setSuccessModelMap(ModelMap modelMap, Object data) {
return setModelMap(modelMap, HttpCode.OK, data);
} /** 设置响应代码 */
protected ResponseEntity<ModelMap> setModelMap(ModelMap modelMap, HttpCode code) {
return setModelMap(modelMap, code, null);
} /** 设置响应代码 */
protected ResponseEntity<ModelMap> setModelMap(ModelMap modelMap, HttpCode code, Object data) {
Map<String, Object> map = InstanceUtil.newLinkedHashMap();
map.putAll(modelMap);
modelMap.clear();
for (Iterator<String> iterator = map.keySet().iterator(); iterator.hasNext();) {
String key = iterator.next();
if (!key.startsWith("org.springframework.validation.BindingResult") && !key.equals("void")) {
modelMap.put(key, map.get(key));
}
}
if (data != null) {
if (data instanceof Page) {
Page<?> page = (Page<?>)data;
modelMap.put("rows", page.getRecords());
modelMap.put("current", page.getCurrent());
modelMap.put("size", page.getSize());
modelMap.put("pages", page.getPages());
modelMap.put("total", page.getTotal());
} else if (data instanceof List<?>) {
modelMap.put("rows", data);
modelMap.put("total", ((List<?>)data).size());
} else {
modelMap.put("data", data);
}
}
modelMap.put("code", code.value().toString());
modelMap.put("msg", code.msg());
modelMap.put("timestamp", System.currentTimeMillis());
logger.info("RESPONSE : " + JSON.toJSONString(modelMap));
return ResponseEntity.ok(modelMap);
} /** 异常处理 */
@ExceptionHandler(Exception.class)
public void exceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception ex)
throws Exception {
logger.error(Constants.Exception_Head, ex);
ModelMap modelMap = new ModelMap();
if (ex instanceof BaseException) {
((BaseException)ex).handler(modelMap);
} else if (ex instanceof IllegalArgumentException) {
new IllegalParameterException(ex.getMessage()).handler(modelMap);
} else if (ex instanceof UnauthorizedException) {
modelMap.put("code", HttpCode.FORBIDDEN.value().toString());
modelMap.put("msg", StringUtils.defaultIfBlank(ex.getMessage(), HttpCode.FORBIDDEN.msg()));
} else {
modelMap.put("code", HttpCode.INTERNAL_SERVER_ERROR.value().toString());
String msg = StringUtils.defaultIfBlank(ex.getMessage(), HttpCode.INTERNAL_SERVER_ERROR.msg());
modelMap.put("msg", msg.length() > 100 ? "系统走神了,请稍候再试." : msg);
}
response.setContentType("application/json;charset=UTF-8");
modelMap.put("timestamp", System.currentTimeMillis());
logger.info("RESPONSE : " + JSON.toJSON(modelMap));
byte[] bytes = JSON.toJSONBytes(modelMap, SerializerFeature.DisableCircularReferenceDetect);
response.getOutputStream().write(bytes);
}
}

BaseController

end 

4 后端CRUD

  4.1 READ

    4.1.1 在数据库中创建一个名为 test_user 表

      坑01:如果和数据库表对应的实体类继承了BaseModel类,那么在创建数据库表时就必须在数据表中添加和BaseModel中属性对应的字段,否则就会报错:XXX字段不存在

CREATE TABLE `NewTable` (
`id_` bigint(20) NOT NULL ,
`name` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' ,
`enable_` int(11) NOT NULL ,
`remark_` varchar(22) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`create_by` bigint(22) NULL DEFAULT NULL ,
`create_time` date NULL DEFAULT NULL ,
`update_by` bigint(20) NULL DEFAULT NULL ,
`update_time` date NULL DEFAULT NULL ,
`keyword` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`id_`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
ROW_FORMAT=COMPACT
;

    4.1.2 在facade层创建一个名为 Test.java 实体类

      技巧01:将每个实体类中公用的属性提取出来作为父类,在iBase4j中是将公用的属性提取出来放在了BaseModel中

      坑01:由于实体类继承了BaseModel,所以和实体类对应的数据库表必须有和BaseModel对应的字段,否则会报错:XXX字段不存在 

package org.ibase4j.model;

import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName; import top.ibase4j.core.base.BaseModel; @TableName("test_user")
@SuppressWarnings("serial")
public class Test extends BaseModel { @TableField("name")
private String name;
@TableField("phone")
private String phone; @TableField(exist = false)
private String oldPassword;
@TableField(exist = false)
private String deptName;
@TableField(exist = false)
private String userTypeText;
@TableField(exist = false)
private String permission; public String getOldPassword() {
return oldPassword;
}
public void setOldPassword(String oldPassword) {
this.oldPassword = oldPassword;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getUserTypeText() {
return userTypeText;
}
public void setUserTypeText(String userTypeText) {
this.userTypeText = userTypeText;
}
public String getPermission() {
return permission;
}
public void setPermission(String permission) {
this.permission = permission;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
} }

Test.java

    4.1.3 在service层创建一个名为 TestService.java 服务类

      技巧01:在iBase4j中所有的服务类都继承了BaseService类,因为在BaseService类中基本的CRUD方法

      技巧02:在自定义的服务中定义一个查询方法,在这个查询方法中调用父类的query方法进行查询

      坑01:自定义服务类在继承BaseService服务类时需要制定泛型类型,这个泛型类型必须是facade中定义的实体类,即使是Object类型也会报错

package org.ibase4j.service;

import java.util.List;
import java.util.Map; import org.apache.commons.lang3.StringUtils;
import org.ibase4j.mapper.SysUserThirdpartyMapper;
import org.ibase4j.model.SysUser;
import org.ibase4j.model.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.plugins.Page; import top.ibase4j.core.base.BaseService; @Service
public class TestService extends BaseService<Test> { @Autowired
private SysUserThirdpartyMapper thirdpartyMapper;
@Autowired
private SysDicService sysDicService;
@Autowired
private SysDeptService sysDeptService;
@Autowired
private SysAuthorizeService sysAuthorizeService; // public Page<SysUser> query(Map<String, Object> params) {
// System.out.println("测试服务层");
// Map<String, String> userTypeMap = sysDicService.queryDicByType("USERTYPE");
// Page<SysUser> pageInfo = super.query(params);
// for (SysUser userBean : pageInfo.getRecords()) {
// if (userBean.getUserType() != null) {
// userBean.setUserTypeText(userTypeMap.get(userBean.getUserType()));
// }
// List<String> permissions = sysAuthorizeService.queryUserPermission(userBean.getId());
// for (String permission : permissions) {
// if (StringUtils.isBlank(userBean.getPermission())) {
// userBean.setPermission(permission);
// } else {
// userBean.setPermission(userBean.getPermission() + ";" + permission);
// }
// }
// }
// return pageInfo;
// } public Page<Test> query(Map<String, Object> params) {
// Page<Test> pageInfo = new Page<Test>();
Page<Test> pageInfo = super.query(params);
return pageInfo;
} }

TestService.java

    4.1.4 在service层中创建一个名为 TestMapper.java 接口

      这个接口就类似于springboot中的JPA接口,该接口和对应的XML文件配合来实现数据库的CRUD操作

      技巧01:自定义的DAO接口继承自BaseMapper接口,BaseMapper接口中定义了公用的分页查询

package org.ibase4j.mapper;

import java.util.List;
import java.util.Map; import org.apache.ibatis.annotations.Param;
import org.ibase4j.model.Test; import top.ibase4j.core.base.BaseMapper; public interface TestMapper extends BaseMapper<Test> {
List<Long> selectIdPage(@Param("cm") Map<String, Object> params);
}

TestMapper.java

    4.1.5 在service层中创建一个名为 TestMapper.xml 文件

      这个自定义的XML文件主要是和Mapper接口配合使用实现数据库的CRUD操作的

      详情请参见mybatis先关的技术文档

<?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="org.ibase4j.mapper.TestMapper">
<!-- 查询列表-->
<select id="selectIdPage" resultType="java.lang.Long">
SELECT id_ FROM test_user
ORDER BY id_ DESC
</select>
</mapper>

    4.1.6 在web层创建一个名为 TestController.java 控制类

      自定义的控制类必须继承AbstractController,因为在AbstractController类中封装了CRUD操作

      技巧01:继承AbstractController类后必须实现getService方法,该方法的返回值就是service层中对应的一个服务类的类名(PS:类名首字母小写后的结果)

      技巧02:在自定义的控制类中随便写一个方法,然后在该方法中调用的父类的query方法就可以实现数据查询操作了

package org.ibase4j.web;

import java.util.Map;

import org.ibase4j.provider.ISysProvider;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import top.ibase4j.core.base.AbstractController; @RestController
@RequestMapping(value = "/test")
public class TestController extends AbstractController<ISysProvider> {
@Override
public String getService() {
// TODO Auto-generated method stub
return "testService";
} @PutMapping(value = "/test01")
public Object test01(ModelMap modelMap, @RequestBody Map<String, Object> param) {
System.out.println("测试控制层");
// return "测试请求成功";
return super.query(modelMap, param); } }

TestController.java

    4.1.7 效果展示

      利用Postman或者Advanced REST client 模拟前端进行测试即可

      坑01:由于iBase4j后台默认使用的是分页查询,所以在请求中必须传入pageSize的值,例如:

        

      请求成功后的效果如下:

        

  4.2 UPDATE

    待更新......2018年3月21日09:21:09

  4.3 CREATE

    待更新......2018-3-21 09:21:21

  4.4 DELETE

    待更新......2018-3-21 09:21:29

end

5 facade层概述

  facade中主要编写的是实体类,每一个实体类都和数据库中表有着严格的对应关系;每个实体类类都继承自BaseModel,在BaseModel中定义了一些通用的属性,例如:id、enable、remark等等

  坑01:由于所有的实体类都继承自BaseModel类,所以在创建数据库时BaseModel中的属性必须有相应的字段与其对应,否则在启动service层时会报错:XXX字段不存在

end

iBase4J项目笔记的更多相关文章

  1. 《BI项目笔记》——微软BI项目笔记连载

    本系列文章主要是结合实际项目,加上自己的总结,整理出来的一系列项目笔记,涉及微软SQL Server2008中商务智能开发中的SSAS.SSIS模块:  准备工作: <BI项目笔记>基于雪 ...

  2. 项目笔记---CSharp图片处理

    原文:项目笔记---CSharp图片处理 项目笔记---CSharp图片处理 最近由于项目上需要对图片进行二值化处理,就学习了相关的图片处理上的知识,从开始的二值化的意义到动态阀值检测二值化等等,并用 ...

  3. Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid

    Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid 上一步获取QQ登录网址之后,测试登录之后本该跳转到这个界面 但是报错了: 新建oauth_callback.html & ...

  4. Django商城项目笔记No.11用户部分-QQ登录1获取QQ登录网址

    Django商城项目笔记No.11用户部分-QQ登录 QQ登录,亦即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目. 若想实现QQ登录,需要成为QQ互联 ...

  5. Django商城项目笔记No.10用户部分-登录接口

    Django商城项目笔记No.10用户部分-登录接口 添加url路由 接下来第二步,增加返回内容: 增加结果如下: 配置:上边的方法定义了返回的内容都有哪些,那这个方法jwt还不知道,需要配置: 修改 ...

  6. Django商城项目笔记No.9用户部分-注册接口签发JWTtoken

    Django商城项目笔记No.9用户部分-注册接口签发JWTtoken 我们在验证完用户的身份后(检验用户名和密码),需要向用户签发JWT,在需要用到用户身份信息的时候,还需核验用户的JWT. 关于签 ...

  7. Django商城项目笔记No.8用户部分-注册接口实现

    Django商城项目笔记No.8用户部分-注册接口实现 users的view.py中增加如下代码 class RegisterUserView(CreateAPIView): "" ...

  8. Django商城项目笔记No.7用户部分-注册接口-判断用户名和手机号是否存在

    Django商城项目笔记No.7用户部分-注册接口-判断用户名和手机号是否存在 判断用户名是否存在 后端视图代码实现,在users/view.py里编写如下代码 class UsernameCount ...

  9. Django商城项目笔记No.6用户部分-注册接口-短信验证码实现celery异步

    Django商城项目笔记No.4用户部分-注册接口-短信验证码实现celery异步 接上一篇,如何解决前后端请求跨域问题? 首先想一下,为什么图片验证码请求的也是后端的api.meiduo.site: ...

随机推荐

  1. OUTlook无法预览xls文件

    outlook可以正常预览doc,pdf,jpg格式的附件,但是xls和xlsx格式就是不能预览.找了好多网络上的办法,都是不行,最终还是找一个靠谱的办法,记录一下 这个方法非常有用:如题, 本人安装 ...

  2. Python-正则表达式及实战小例子

    注意Python的字符串本身也用'\'转义,所以要特别注意,一般我们都建议使用Python的r前缀,就不用考虑转义的问题了  1,行的起始 例子:匹配‘cat’ 开头 patt=re.compile( ...

  3. Spring_总结_02_依赖注入

    一.前言 本文承接上一节:Spring_总结_01_Spring概述 在上一节中,我们了解了Spring的最根本使命.四大原则.六大模块以及Spring的生态. 这一节我们开始了解Spring的第二大 ...

  4. middle school

    One of the most difficult transitions faced by parents and youth is that of going from elementary to ...

  5. Ajax做无刷新三级联动

    1.引入JS and Jquery包 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  6. libmodbus相关资料整理

    /****************************************************************************** * libmodbus相关资料整理 * ...

  7. CodeForces - 154C:Double Profiles (hash+排序)

    You have been offered a job in a company developing a large social network. Your first task is conne ...

  8. C#进阶之路(三):深拷贝和浅拷贝

    一.前言 本文主要讨论深浅拷贝的区别,如果实现.浅拷贝日常的应用比较懂,这里不做深入讨论,那么深拷贝如何实现?目前我知道的方式有三种:反射,反序列化和表达树的方式.这里需要注意如果用反射来实现深拷贝的 ...

  9. NOIp2018集训test-10-24(am&pm)

    李巨连续AK三场了,我跟南瓜打赌李巨连续AK七场,南瓜赌李巨连续AK五场. DAY1 T1 qu 按题意拿stack,queue和priority_que模拟即可.特判没有元素却要取出的情况. T2 ...

  10. JvisualVm添加远程监控

    一.Weblogic远程监控 1.首先需要在远程的weblogic的域下面,找到/bin/ setDomainEnv.sh ,需要在此文件下加入如下内容: -Dcom.sun.management.j ...