为了提现代码的高可用性,我们可以常见的把dao层进行抽取,service ,但是很少看见有controller的抽取,其实dao层也是可以被抽取的。
首先我们定义一个BaseController接口
package com.zhan.common.controller.base; import com.zhan.common.domain.base.Identifiable; import com.zhan.common.domain.base.Result; import org.springframework.data.domain.Pageable; import org.springframework.web.servlet.ModelAndView; /** * 基础控制器接口 * @author LiuJunGuang * @date 2014年3月5日下午12:01:23 */ public interface BaseController<T extends Identifiable, Q extends T> { /** * 根据ID列表删除对象,如果idList 为空或者空列表则直接返回{@link Result},状态为OK * <blockquote> * <table cellpadding=1 border=1 cellspacing=0 summary="Capturing group numberings"> * <tr> * <th><tt>路径 </tt></th> * <th>访问方式 </th> * <th><tt>返回路径 </tt></th> * </tr> * <tr> * <th><tt>/sys/dictionary/delete</tt></th> * <th>post</th> * <th><tt>{@link Result}的json对象</tt></th> * </tr> * </table> * </blockquote> * @param idList 要删除对象的ID列表 * @return ModelAndView */ public Result deleteList(String[] ids); /** * 删除一条记录 * <blockquote> * <table cellpadding=1 border=1 cellspacing=0 summary="Capturing group numberings"> * <tr> * <th><tt>路径 </tt></th> * <th>访问方式 </th> * <th><tt>返回路径 </tt></th> * </tr> * <tr> * <th><tt>/sys/dictionary/${id}</tt></th> * <th>delete</th> * <th><tt>{@link Result}的json对象</tt></th> * </tr> * </table> * </blockquote> * @param id 不能为null,则跳转到错误页面 * @return ModelAndView */ public Result deleteOne(String id); /** * 添加一条实体,实体不能为null * <blockquote> * <table cellpadding=1 border=1 cellspacing=0 summary="Capturing group numberings"> * <tr> * <th><tt>路径 </tt></th> * <th>访问方式 </th> * <th><tt>返回路径 </tt></th> * </tr> * <tr> * <th><tt>/sys/dictionary</tt></th> * <th>post</th> * <th><tt>redirect:/sys/dictionary/</tt></th> * </tr> * </table> * </blockquote> * @param entity 要添加的实体 * @return ModelAndView */ public ModelAndView addOne(T entity); /** * 跳转到添加页面为insertXXX页面<br>示例Bean对象:SysDictionay->生成路径:/sys/dictionary * <blockquote> * <table cellpadding=1 border=1 cellspacing=0 summary="Capturing group numberings"> * <tr> * <th><tt>路径 </tt></th> * <th>访问方式 </th> * <th><tt>返回路径 </tt></th> * </tr> * <tr> * <th><tt>/sys/dictionary/add</tt></th> * <th>get</th> * <th><tt>/sys/dictionary/addDictionary.ftl</tt></th> * </tr> * </table> * </blockquote> * @return ModelAndView */ public ModelAndView addView(); /** * 查询对象列表,返回页面 listXXX页面 * <blockquote> * <table cellpadding=1 border=1 cellspacing=0 summary="Capturing group numberings"> * <tr> * <th><tt>路径 </tt></th> * <th>访问方式 </th> * <th><tt>返回路径 </tt></th> * </tr> * <tr> * <th><tt>/sys/dictionary</tt></th> * <th>get</th> * <th><tt>/sys/dictionary/listDictionary.ftl</tt></th> * </tr> * </table> * </blockquote> * @param query 查询对象 * @param pageable 分页参数与排序参数 * @return ModelAndView */ public ModelAndView selectList(Q query, Pageable pageable); /** * 根据ID查询一个对象,返回页面为viewXXX页面 * <blockquote> * <table cellpadding=1 border=1 cellspacing=0 summary="Capturing group numberings"> * <tr> * <th><tt>路径 </tt></th> * <th>访问方式 </th> * <th><tt>返回路径 </tt></th> * </tr> * <tr> * <th><tt>/sys/dictionary/${id}</tt></th> * <th>get</th> * <th><tt>/sys/dictionary/viewDictionary.ftl</tt></th> * </tr> * </table> * </blockquote> * @param id 不能为null,则跳转到错误页面 * @return ModelAndView */ public ModelAndView viewOne(String id); /** * 更新一个实体,实体不能为null * <blockquote> * <table cellpadding=1 border=1 cellspacing=0 summary="Capturing group numberings"> * <tr> * <th><tt>路径 </tt></th> * <th>访问方式 </th> * <th><tt>返回路径 </tt></th> * </tr> * <tr> * <th><tt>/sys/dictionary/</tt></th> * <th>put</th> * <th><tt>{@link Result}已更新的实体对象json字符串</tt></th> * </tr> * </table> * </blockquote> * @param entity 要更新的实体 * @return Result */ public ModelAndView editOne(T entity); /** * 跳转到更新页面为editXXX页面 * <blockquote> * <table cellpadding=1 border=1 cellspacing=0 summary="Capturing group numberings"> * <tr> * <th><tt>路径 </tt></th> * <th>访问方式 </th> * <th><tt>返回路径 </tt></th> * </tr> * <tr> * <th><tt>/sys/dictionary/edit/${id}</tt></th> * <th>get</th> * <th><tt>/sys/dictionary/editDictionary.ftl</tt></th> * </tr> * </table> * </blockquote> * @param id 不能为null,则跳转到错误页面 * @return ModelAndView */ public ModelAndView editView(String id); /* * ajax Post添加数据 * */ public Result postAdd(T entity); /* * ajax Post修改数据 * */ public Result postEdit(T entity); }
basecontrollerImpl 接口的实现类
package com.zhan.common.controller.base; import com.zhan.common.domain.ControllerPath; import com.zhan.common.domain.base.Identifiable; import com.zhan.common.domain.base.Result; import com.zhan.common.service.base.BaseService; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import java.util.Arrays; /** * 基础控制器接口实现类 * @author LiuJunGuang * @date 2014年3月5日下午12:03:13 */ public abstract class BaseControllerImpl<T extends Identifiable, Q extends T> implements BaseController<T, Q> { private Logger log = LoggerFactory.getLogger(BaseControllerImpl.class); /** * @fields path 页面路径信息 */ protected ControllerPath path = new ControllerPath(this.getClass()); /** * 获取基础的服务 * @return BaseService */ protected abstract BaseService<T> getBaseService(); @Override @ResponseBody @RequestMapping(value = "/delete", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE) public Result deleteList(String[] ids) { if (ArrayUtils.isEmpty(ids)) { log.error("未设置批量删除对象的ID号!对象:{}", path.getEntityName()); return new Result(Result.Status.ERROR, "没有传入要删除的ID号数组!"); } try { getBaseService().deleteByIdInBatch(Arrays.asList(ids)); } catch (Exception e) { log.error("批量删除对象失败!对象:" + path.getEntityName(), e); return new Result(Result.Status.ERROR, "批量删除失败!"); } return new Result(Result.Status.OK, ids.length); } @Override @ResponseBody @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE) public Result deleteOne(@PathVariable("id") String id) { if (StringUtils.isBlank(id)) { log.error("要删除的ID号为null或空字符串!对象:{}", path.getEntityName()); return new Result(Result.Status.ERROR, "没有传入要删除的ID号!"); } int count = getBaseService().deleteById(id); if (count == 0) return new Result(Result.Status.ERROR, "要删除的记录不存在!"); log.debug("成功删除{}个对象,id:{},对象:{}", count, id, path.getEntityName()); return new Result(Result.Status.OK, count); } @Override @RequestMapping(method = RequestMethod.POST) public ModelAndView addOne(T entity) { getBaseService().insert(entity); return new ModelAndView(path.getRedirectListPath()); } @Override @RequestMapping(value = "/add", method = RequestMethod.GET) public ModelAndView addView() { return new ModelAndView(path.getAddViewPath()); } @Override @RequestMapping(method = RequestMethod.GET) public ModelAndView selectList(Q query, @PageableDefault Pageable pageable) { Page<T> page = getBaseService().queryPageList(query, pageable); ModelAndView mav = new ModelAndView(path.getListViewPath(), "page", page); mav.addObject("query", query); return mav; } @Override @RequestMapping(value = "/{id}", method = RequestMethod.GET) public ModelAndView viewOne(@PathVariable("id") String id) { Object obj = getBaseService().queryById(id); return new ModelAndView(path.getOneViewPath(), path.getEntityName(), obj); } @Override @RequestMapping(method = RequestMethod.PUT) public ModelAndView editOne(T entity) { getBaseService().updateById(entity); return new ModelAndView(path.getRedirectListPath()); } @Override @RequestMapping(value = "/edit/{id}", method = RequestMethod.GET) public ModelAndView editView(@PathVariable("id") String id) { Object obj = getBaseService().queryById(id); return new ModelAndView(path.getEditViewPath(), path.getEntityName(), obj); } /* * ajax Post添加数据 * */ @Override @ResponseBody @RequestMapping(value = "/ajaxAdd", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) public Result postAdd(T entity){ getBaseService().insert(entity); return new Result(Result.Status.OK,null); } /* * ajax Post修改数据 * */ @Override @ResponseBody @RequestMapping(value = "/ajaxEdit", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) public Result postEdit(T entity){ getBaseService().updateById(entity); return new Result(Result.Status.OK,null); package com.zhan.common.domain; import com.zhan.common.constants.PagePrefix; import com.zhan.common.utils.BeanUtils; import com.zhan.common.utils.StringEx; import org.apache.commons.lang3.StringUtils; /** * Controller路径构建起 * @author LiuJunGuang * @date 2014年3月5日下午3:11:43 */ public class ControllerPath { /** * @fields entityClass 简单的实体类 */ private Class<?> entityClass = null; /** * @fields URL_SEPARATOR 路径分隔符 */ private static final String URL_SEPARATOR = "/"; /** * @fields entityName 实体名称 */ private String entityName = null; /** * @fields words 实体类路径 */ private String[] words = null; public ControllerPath(Class<?> genericClass) { if (genericClass == null) throw new IllegalArgumentException("[genericClass] - must not be null!"); entityClass = BeanUtils.getGenericClass(genericClass); if (entityClass == null) throw new IllegalArgumentException(genericClass.getName() + "不是泛型类型!"); words = getWords(entityClass.getSimpleName()); entityName = words[words.length - 1]; } /** * 获取显示页面路径 * @return String "sys/dictionary/viewDictionary" */ public String getOneViewPath() { StringBuilder sb = new StringBuilder(); sb.append(getBasePath()); sb.append(PagePrefix.VIEW); sb.append(StringEx.toUpperCaseFirstOne(entityName)); return sb.toString(); } /** * 显示列表路径 * @return String "sys/dictionary/listDictionary" */ public String getListViewPath() { StringBuilder sb = new StringBuilder(); sb.append(getBasePath()); sb.append(PagePrefix.LIST); sb.append(StringEx.toUpperCaseFirstOne(entityName)); return sb.toString(); } /** * 添加页面路径信息 * @return */ public String getAddViewPath() { StringBuilder sb = new StringBuilder(); sb.append(getBasePath()); sb.append(PagePrefix.ADD); sb.append(StringEx.toUpperCaseFirstOne(entityName)); return sb.toString(); } /** * 添加页面路径信息 * @return */ public String getEditViewPath() { StringBuilder sb = new StringBuilder(); sb.append(getBasePath()); sb.append(PagePrefix.EDIT); sb.append(StringEx.toUpperCaseFirstOne(entityName)); return sb.toString(); } /** * 推送页面路径信息 * @return */ public String getPushViewPath() { StringBuilder sb = new StringBuilder(); sb.append(getBasePath()); sb.append(PagePrefix.PUSH); sb.append(StringEx.toUpperCaseFirstOne(entityName)); return sb.toString(); } /** * 获取删除返回路径,默认重定向到列表页面 * @return */ public String getRedirectListPath() { return "redirect:/" + getBasePath(); } /** * 获取实体的名称,全小写 * @return */ public String getEntityName() { return entityName; } /** * 以字符串中的大写字母为标示拆分字符串,如果字符串为null或空则返回null * @param str * @return String[] 拆分后的字符串,已转换为全小写 */ private String[] getWords(String str) { if (StringUtils.isEmpty(str)) return null; String[] words = str.split("(?<!^)(?=[A-Z])"); for (int i = 0; i < words.length; i++) { words[i] = StringUtils.lowerCase(words[i]); } return words; } /** * 获取类名路径信息,例如:SysDictionary 则返回 "sys/dictionary/" * @param clazz 类 * @return String 类名路径信息 */ private String getBasePath() { StringBuffer sb = new StringBuffer(); for (String word : words) { sb.append(word).append(URL_SEPARATOR); } return sb.toString(); } } 原文:https://blog.csdn.net/qq_36838191/article/details/80063043