iBase4J项目笔记
目录:
1 数据库密码加密
3 web层概述
4 后端CRUD
4.1 READ
4.2 UPDATE
4.3 CREATE
4.4 DELETE
1 数据库密码加密
iBase4J项目的service层中数据库配置文件中数据库的连接密码必须是经过加密过后的,如何获取加密方法
1.1 加密类是 org.ibase4j.core.util.PropertiesUtil
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对象封装了查询到的数据信息,以及一些分页查询参数
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
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
5 facade层概述
facade中主要编写的是实体类,每一个实体类都和数据库中表有着严格的对应关系;每个实体类类都继承自BaseModel,在BaseModel中定义了一些通用的属性,例如:id、enable、remark等等
坑01:由于所有的实体类都继承自BaseModel类,所以在创建数据库时BaseModel中的属性必须有相应的字段与其对应,否则在启动service层时会报错:XXX字段不存在
iBase4J项目笔记的更多相关文章
- 《BI项目笔记》——微软BI项目笔记连载
本系列文章主要是结合实际项目,加上自己的总结,整理出来的一系列项目笔记,涉及微软SQL Server2008中商务智能开发中的SSAS.SSIS模块: 准备工作: <BI项目笔记>基于雪 ...
- 项目笔记---CSharp图片处理
原文:项目笔记---CSharp图片处理 项目笔记---CSharp图片处理 最近由于项目上需要对图片进行二值化处理,就学习了相关的图片处理上的知识,从开始的二值化的意义到动态阀值检测二值化等等,并用 ...
- Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid
Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid 上一步获取QQ登录网址之后,测试登录之后本该跳转到这个界面 但是报错了: 新建oauth_callback.html & ...
- Django商城项目笔记No.11用户部分-QQ登录1获取QQ登录网址
Django商城项目笔记No.11用户部分-QQ登录 QQ登录,亦即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目. 若想实现QQ登录,需要成为QQ互联 ...
- Django商城项目笔记No.10用户部分-登录接口
Django商城项目笔记No.10用户部分-登录接口 添加url路由 接下来第二步,增加返回内容: 增加结果如下: 配置:上边的方法定义了返回的内容都有哪些,那这个方法jwt还不知道,需要配置: 修改 ...
- Django商城项目笔记No.9用户部分-注册接口签发JWTtoken
Django商城项目笔记No.9用户部分-注册接口签发JWTtoken 我们在验证完用户的身份后(检验用户名和密码),需要向用户签发JWT,在需要用到用户身份信息的时候,还需核验用户的JWT. 关于签 ...
- Django商城项目笔记No.8用户部分-注册接口实现
Django商城项目笔记No.8用户部分-注册接口实现 users的view.py中增加如下代码 class RegisterUserView(CreateAPIView): "" ...
- Django商城项目笔记No.7用户部分-注册接口-判断用户名和手机号是否存在
Django商城项目笔记No.7用户部分-注册接口-判断用户名和手机号是否存在 判断用户名是否存在 后端视图代码实现,在users/view.py里编写如下代码 class UsernameCount ...
- Django商城项目笔记No.6用户部分-注册接口-短信验证码实现celery异步
Django商城项目笔记No.4用户部分-注册接口-短信验证码实现celery异步 接上一篇,如何解决前后端请求跨域问题? 首先想一下,为什么图片验证码请求的也是后端的api.meiduo.site: ...
随机推荐
- Eclipse 快捷键大全(群里共享的,留下来以后兴许会用到)
Eclipse快捷键大全Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加) Ctrl+Alt+↑ 复制当前行到上一行 ...
- 分布式_理论_08_Consistent Hash(一致性哈希算法)
一.前言 五.参考资料 1.分布式理论(八)—— Consistent Hash(一致性哈希算法)
- https页面 和 http请求的问题
(1)强制升级http 静态资源地址为https地址 https页面中不能使用http请求,http页面中可以使用https请求. 关于在https 页面有一些http的请求,可以在<head& ...
- 2017-2018-1 20179215 第十一周 ShellShock攻击实验
<Linux内核原理与设计>第十一周作业 ShellShock攻击实验 分组:和20179205王雅哲共同完成实验及博客攥写 实验内容: Bash中发现了一个严重漏洞shellshock ...
- SQL Server 学习系列之四(SQL 内幕)
SQL Server 学习系列之四(SQL 内幕) SQL Server 学习系列之一(薪酬方案+基础) SQL Server 学习系列之二(日期格式问题) SQL Server 学习系列之三(SQL ...
- 使用ajax技术实现简单登录操作
1.ajax:特点在web上面通过JavaScript,使用异步的XmlHttp请求,实现无刷新的Web界面 首先:创建ajax对象 再次:向服务器端实现ajax请求 最后:回调 创建异步请求对象 & ...
- ETHNET DHCP的两种方式
DHCP API: nx_dhcp_create nx_dhcp_start nx_dhcp_stop nx_dhcp_delete nx_ip_address_get //客户端IP获取 nx_dh ...
- Java基础--枚举Enum
Java中的枚举是一种特殊的类,可以将一组固定常量的集合组成一种类型,使用方便且类型安全.使用enum关键字定义. enum类型父类为Enum,通过Enum.class可见Enum为抽象类,实现了Co ...
- (转)c# Linq及Lamda表达式应用经验之 GroupBy 分组
本文转载自:http://www.cnblogs.com/han1982/p/4138163.html 示例1: GroupBy 分组在List<>泛型中的应用 原表: 按姓名Nam 分组 ...
- 组装恢复rbd
标签: ceph,ceph实验,rbd cluster相关环境: # cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) # ce ...