Controller层相当于MVC中的C,也是安卓或者前端请求的接口。

首先说Controller为什么需要写的更加简化?

第一、Controller是不能复用的;

第二、即便是将Controller分类,如果Controller代码过于庞大,不利于维护;

第三、Controller中的CRUD之类的基本都是重复的,要么是返回数据,要么是返回状态码(通常定义一个ResultBean即可搞定);

我在第一个项目和第二个项目以及现在的项目犯了很多错误。

关于第一个项目和第二个项目的错误,今天暂不说。

第三个项目也就是现在的项目,Controller写的是过于庞大,参数表单校验都写在里面。

正常情况下,像比如参数非空校验之类的很常见,完全可以封装成一个ValidateUtils来校验,犯不着重复写了很多,虽然Hutool这个开源项目封装的StrUtils里面有对应的判断方法,但是感觉写了很多遍,着实不爽。觉得不经意间又犯了很多错误。重复写,显得代码冗余。

下面以人人开源的代码生成器为例,人人开源的代码生成器生成的Controller是这样的,代码如下:

@RestController
@RequestMapping("/sys/menu")
public class SysMenuController extends AbstractController {
@Autowired
private SysMenuService sysMenuService; /**
* 导航菜单
*/
@RequestMapping("/nav")
public R nav(){
List<SysMenuEntity> menuList = sysMenuService.getUserMenuList(getUserId());
return R.ok().put("menuList", menuList);
} /**
* 所有菜单列表
*/
@RequestMapping("/list")
@RequiresPermissions("sys:menu:list")
public List<SysMenuEntity> list(){
List<SysMenuEntity> menuList = sysMenuService.selectList(null);
for(SysMenuEntity sysMenuEntity : menuList){
SysMenuEntity parentMenuEntity = sysMenuService.selectById(sysMenuEntity.getParentId());
if(parentMenuEntity != null){
sysMenuEntity.setParentName(parentMenuEntity.getName());
}
} return menuList;
} /**
* 选择菜单(添加、修改菜单)
*/
@RequestMapping("/select")
@RequiresPermissions("sys:menu:select")
public R select(){
//查询列表数据
List<SysMenuEntity> menuList = sysMenuService.queryNotButtonList(); //添加顶级菜单
SysMenuEntity root = new SysMenuEntity();
root.setMenuId(0L);
root.setName("一级菜单");
root.setParentId(-1L);
root.setOpen(true);
menuList.add(root); return R.ok().put("menuList", menuList);
} /**
* 菜单信息
*/
@RequestMapping("/info/{menuId}")
@RequiresPermissions("sys:menu:info")
public R info(@PathVariable("menuId") Long menuId){
SysMenuEntity menu = sysMenuService.selectById(menuId);
return R.ok().put("menu", menu);
} /**
* 保存
*/
@SysLog("保存菜单")
@RequestMapping("/save")
@RequiresPermissions("sys:menu:save")
public R save(@RequestBody SysMenuEntity menu){
//数据校验
verifyForm(menu); sysMenuService.insert(menu); return R.ok();
} /**
* 修改
*/
@SysLog("修改菜单")
@RequestMapping("/update")
@RequiresPermissions("sys:menu:update")
public R update(@RequestBody SysMenuEntity menu){
//数据校验
verifyForm(menu); sysMenuService.updateById(menu); return R.ok();
} /**
* 删除
*/
@SysLog("删除菜单")
@RequestMapping("/delete")
@RequiresPermissions("sys:menu:delete")
public R delete(long menuId){
if(menuId <= 31){
return R.error("系统菜单,不能删除");
} //判断是否有子菜单或按钮
List<SysMenuEntity> menuList = sysMenuService.queryListParentId(menuId);
if(menuList.size() > 0){
return R.error("请先删除子菜单或按钮");
} sysMenuService.delete(menuId); return R.ok();
} /**
* 验证参数是否正确
*/
private void verifyForm(SysMenuEntity menu){
if(StringUtils.isBlank(menu.getName())){
throw new RRException("菜单名称不能为空");
} if(menu.getParentId() == null){
throw new RRException("上级菜单不能为空");
} //菜单
if(menu.getType() == Constant.MenuType.MENU.getValue()){
if(StringUtils.isBlank(menu.getUrl())){
throw new RRException("菜单URL不能为空");
}
} //上级菜单类型
int parentType = Constant.MenuType.CATALOG.getValue();
if(menu.getParentId() != 0){
SysMenuEntity parentMenu = sysMenuService.selectById(menu.getParentId());
parentType = parentMenu.getType();
} //目录、菜单
if(menu.getType() == Constant.MenuType.CATALOG.getValue() ||
menu.getType() == Constant.MenuType.MENU.getValue()){
if(parentType != Constant.MenuType.CATALOG.getValue()){
throw new RRException("上级菜单只能为目录类型");
}
return ;
} //按钮
if(menu.getType() == Constant.MenuType.BUTTON.getValue()){
if(parentType != Constant.MenuType.MENU.getValue()){
throw new RRException("上级菜单只能为菜单类型");
}
return ;
}
}
}

再看看我的Controller吧,代码示例如下:

@RestController
@RequiresAuthentication
@RequestMapping("/sysMenu")
public class SysMenuController {
@Autowired
private SysModuleService sysModuleService; @Autowired
private SysMenuService sysMenuService; @Autowired
private SysUserService sysUserServicec; /**
* 菜单分页查询
* @param request
* @return
*/
@GetMapping(value="/menuPagingQuery",produces="application/json;charset=utf-8")
@ApiOperation(value="菜单分页查询",httpMethod="GET",notes="菜单分页查询")
public JSONObject modulePageQuery(HttpServletRequest request) { JSONObject json = new JSONObject(); //公司编码
String companyCode = request.getParameter("companyCode"); //获取前台当前页
String currentPage = request.getParameter("pageno"); //获取前台每页显示数据
String pageSize = request.getParameter("pagesize"); //将前台通过request获取的currentPage参数转为Integer类型
Integer pageno = Integer.parseInt(currentPage.trim()); //将前台通过request获取的pageSize参数转为Integer类型
Integer pagesize = Integer.parseInt(pageSize.trim()); //将条件放入Map中
Map<String,Object> conditionMap = new HashMap<String,Object>(); conditionMap.put("companyCode", companyCode);
conditionMap.put("start", (pageno-1)*pagesize);
conditionMap.put("size", pagesize); //调用查询集合数据方法
List<SysMenu> list = sysMenuService.queryMenuPagingListInfo(conditionMap); int count =sysMenuService.queryMenuPagingTotalCount(conditionMap); //总页数计算 初始化为0
int totalPageCount = 0;
if ( count % pagesize == 0 ) {
totalPageCount = count / pagesize;
} else {
totalPageCount = count / pagesize + 1;
} //判断集合数据是否为空
if(!list.isEmpty()) { Page<SysMenu> page = new Page<SysMenu>();
page.setDatas(list);
page.setTotalno(totalPageCount);
page.setTotalsize(count);
json.put(CommonEnum.RETURN_MSG, "获得菜单信息");
json.put("page", page);
json.put(CommonEnum.RETURN_CODE, "000000"); }else { json.put(CommonEnum.RETURN_MSG, "暂无数据");
json.put(CommonEnum.RETURN_CODE, "111111");
} return json; } /**
* 根据模块编码获得对应的菜单信息
* @param moduleCodes
* @return
*/
@GetMapping(value = "/getMenuListInfo",produces="application/json;charset=utf-8")
@ApiOperation(value="根据模块编码获得对应的菜单信息",httpMethod="GET",notes="根据模块编码获得对应的菜单信息")
public JSONObject getMenuListInfo(String moduleCodes) {
JSONObject json = new JSONObject();
try { if(!StrUtil.isEmpty(moduleCodes)) { EntityWrapper<SysMenu> wrapper = new EntityWrapper<SysMenu>();
wrapper.eq("module_codes", moduleCodes);
List<SysMenu> sysMenuList = sysMenuService.selectList(wrapper); if(!sysMenuList.isEmpty()) {
json.put(CommonEnum.RETURN_CODE, "000000");
json.put(CommonEnum.RETURN_MSG, "获得该模块下的所有菜单信息");
json.put("sysMenuList", sysMenuList);
json.put("menuSize", sysMenuList.size()); }else {
json.put(CommonEnum.RETURN_CODE, "111111");
json.put(CommonEnum.RETURN_MSG, "没有数据");
} }else {
json.put(CommonEnum.RETURN_CODE, "333333");
json.put(CommonEnum.RETURN_MSG, "参数异常:参数不能为空"); } } catch (Exception e) { json.put(CommonEnum.RETURN_CODE, "444444");
json.put(CommonEnum.RETURN_MSG, "其他异常");
} return json;
} /**
* 新增菜单
* @return
*/
@PostMapping(value = "/addMenu",produces="application/json;charset=utf-8")
@ApiOperation(value="新增菜单",httpMethod="POST",notes="新增菜单")
public JSONObject addMenu(@RequestBody MenuDto menuDto) {
JSONObject json = new JSONObject(); try { //参数非空校验
if(!StrUtil.isEmptyIfStr(menuDto)) { //根据用户编号获取操作用户信息
EntityWrapper<SysUser> wrapper =new EntityWrapper<SysUser>();
wrapper.eq("user_code", menuDto.getUserCode());
SysUser user = sysUserServicec.selectOne(wrapper); //根据模块名字获取对应模块信息
EntityWrapper<SysModule> wrapper2 = new EntityWrapper<SysModule>();
wrapper2.eq("module_name", menuDto.getModuleName());
SysModule module = sysModuleService.selectOne(wrapper2); SysMenu menu = new SysMenu();
menu.setMenuCode(String.valueOf(RandomUtil.randomInt(666666)));
menu.setMenuName(menuDto.getMenuName());
menu.setMenuHref(menuDto.getMenuHref());
menu.setMenuIcon(menuDto.getMenuIcon());
menu.setMenuType(menuDto.getMenuType());
menu.setCreateBy(user.getUserName());
menu.setIsShow(menuDto.getIsShow());
menu.setTreeSort(menuDto.getTreeSort());
menu.setSysCode(module.getModuleCode());
menu.setModuleCodes(module.getModuleCode());
menu.setPermission(menuDto.getPermission());
menu.setCreateDate(DateUtil.date().toString());
menu.setUpdateBy(user.getUserName());
menu.setUpdateDate(DateUtil.date().toString());
menu.setRemarks(menuDto.getRemarks()); //调用添加逻辑
boolean isAddMenu = sysMenuService.insert(menu); if(isAddMenu) {
json.put(CommonEnum.RETURN_CODE, "000000");
json.put(CommonEnum.RETURN_MSG, "添加菜单成功");
}else {
json.put(CommonEnum.RETURN_CODE, "111111");
json.put(CommonEnum.RETURN_MSG, "添加菜单失败");
} }else { json.put(CommonEnum.RETURN_CODE, "222222");
json.put(CommonEnum.RETURN_MSG, "参数校验异常");
} } catch (Exception e) { json.put(CommonEnum.RETURN_CODE, "333333");
json.put(CommonEnum.RETURN_MSG, "其他异常");
} return json;
} /**
* 根据菜单编号获取对应的菜单信息
* @param menuCode
* @return
*/
@GetMapping(value="/selectByMenuCodeInfo",produces="application/json;charset=utf-8")
@ApiOperation(value="根据菜单编号获取对应的菜单信息",httpMethod="GET",notes="根据菜单编号获取对应的菜单信息")
public JSONObject selectByMenuCodeInfo(String menuCode) { JSONObject json = new JSONObject(); try { if(!StrUtil.isEmpty(menuCode)) {
EntityWrapper<SysMenu> wrapper = new EntityWrapper<SysMenu>();
wrapper.eq("menu_code", menuCode);
SysMenu menu = sysMenuService.selectOne(wrapper); if(menu!=null) { json.put("menu", menu);
json.put(CommonEnum.RETURN_CODE, "000000");
json.put(CommonEnum.RETURN_MSG, "获取菜单信息成功"); }else {
json.put(CommonEnum.RETURN_CODE, "1111111");
json.put(CommonEnum.RETURN_MSG, "获取菜单信息失败");
}
}else {
json.put(CommonEnum.RETURN_CODE, "222222");
json.put(CommonEnum.RETURN_MSG, "参数异常");
} } catch (Exception e) { json.put(CommonEnum.RETURN_CODE, "333333");
json.put(CommonEnum.RETURN_MSG, "其他异常");
} return json;
} /**
* 删除菜单
* @param menuCode
* @return
*/
@PostMapping(value="/deleteMenuInfo",produces="application/json;charset=utf-8")
@ApiOperation(value="删除菜单",httpMethod="POST",notes="删除菜单")
public JSONObject deleteMenuInfo(String menuCode) { JSONObject json = new JSONObject(); try { if(!StrUtil.isEmpty(menuCode)) { boolean isDelete = sysMenuService.deleteById(menuCode);
if(isDelete) {
json.put(CommonEnum.RETURN_CODE, "000000");
json.put(CommonEnum.RETURN_MSG, "删除成功");
}else {
json.put(CommonEnum.RETURN_CODE, "111111");
json.put(CommonEnum.RETURN_MSG, "删除失败");
}
}else {
json.put(CommonEnum.RETURN_CODE, "222222");
json.put(CommonEnum.RETURN_MSG, "参数异常");
} } catch (Exception e) { json.put(CommonEnum.RETURN_CODE, "333333");
json.put(CommonEnum.RETURN_MSG, "其他异常");
} return json; } /**
* 修改菜单
* @return
*/
@PostMapping(value = "/modifyMenu",produces="application/json;charset=utf-8")
@ApiOperation(value="修改菜单",httpMethod="POST",notes="修改菜单")
public JSONObject modifyMenu(@RequestBody MenuDto menuDto) {
JSONObject json = new JSONObject(); try { //参数非空校验
if(!StrUtil.isEmptyIfStr(menuDto)) { //根据用户编号获取操作用户信息
EntityWrapper<SysUser> wrapper =new EntityWrapper<SysUser>();
wrapper.eq("user_code", menuDto.getUserCode());
SysUser user = sysUserServicec.selectOne(wrapper); //根据模块名字获取对应模块信息
EntityWrapper<SysModule> wrapper2 = new EntityWrapper<SysModule>();
wrapper2.eq("module_name", menuDto.getModuleName());
SysModule module = sysModuleService.selectOne(wrapper2); SysMenu menu = new SysMenu();
menu.setMenuCode(menuDto.getMenuCode());
menu.setMenuName(menuDto.getMenuName());
menu.setMenuHref(menuDto.getMenuHref());
menu.setMenuIcon(menuDto.getMenuIcon());
menu.setMenuType(menuDto.getMenuType());
menu.setIsShow(menuDto.getIsShow());
menu.setTreeSort(menuDto.getTreeSort());
menu.setSysCode(module.getModuleCode());
menu.setPermission(menuDto.getPermission());
menu.setModuleCodes(module.getModuleCode());
menu.setUpdateBy(user.getUserName());
menu.setUpdateDate(DateUtil.date().toString());
menu.setRemarks(menuDto.getRemarks()); //调用修改逻辑
boolean isAddMenu = sysMenuService.updateById(menu); if(isAddMenu) {
json.put(CommonEnum.RETURN_CODE, "000000");
json.put(CommonEnum.RETURN_MSG, "修改菜单成功");
}else {
json.put(CommonEnum.RETURN_CODE, "111111");
json.put(CommonEnum.RETURN_MSG, "修改菜单失败");
} }else { json.put(CommonEnum.RETURN_CODE, "222222");
json.put(CommonEnum.RETURN_MSG, "参数校验异常");
} } catch (Exception e) { json.put(CommonEnum.RETURN_CODE, "333333");
json.put(CommonEnum.RETURN_MSG, "其他异常");
} return json;
} /**
* 图标存储(以Cookie的形式保存)
* @param icon
* @param response
* @return
*/
@GetMapping(value="iconStorage",produces="application/json;charset=utf-8")
@ApiOperation(value="图标存储",httpMethod="GET",notes="图标存储")
public JSONObject iconStorage(String icon,HttpServletResponse response) {
JSONObject json = new JSONObject(); try { if(!StrUtil.isEmpty(icon)) { CookieUtils.setCookie(response, "icon", icon, 3600); json.put(CommonEnum.RETURN_CODE, "000000");
json.put(CommonEnum.RETURN_MSG, "图标存储成功");
}else {
json.put(CommonEnum.RETURN_CODE, "1111111");
json.put(CommonEnum.RETURN_MSG, "图标存储失败");
}
} catch (Exception e) { json.put(CommonEnum.RETURN_CODE, "222222");
json.put(CommonEnum.RETURN_MSG, "其他异常");
} return json; } }

两者比较,前者对重复的代码和一些常见的参数校验和异常捕捉拦截做了很好的封装,后者则相反。俗话说:向好同学学习。

下面我将贴一下上面的封装类:

R.java

import java.util.HashMap;
import java.util.Map; public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L; public R() {
put("code", 0);
put("msg", "success");
} public static R error() {
return error(500, "未知异常,请联系管理员");
} public static R error(String msg) {
return error(500, msg);
} public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
} public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
} public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
} public static R ok() {
return new R();
} @Override
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}

RRException.java

import io.renren.common.utils.R;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice; /**
* 异常处理器
*
* @author Mark sunlightcs@gmail.com
* @since 1.0.0 2016-10-27
*/
@RestControllerAdvice
public class RRExceptionHandler {
private Logger logger = LoggerFactory.getLogger(getClass()); /**
* 处理自定义异常
*/
@ExceptionHandler(RRException.class)
public R handleRRException(RRException e){
R r = new R();
r.put("code", e.getCode());
r.put("msg", e.getMessage()); return r;
} @ExceptionHandler(DuplicateKeyException.class)
public R handleDuplicateKeyException(DuplicateKeyException e){
logger.error(e.getMessage(), e);
return R.error("数据库中已存在该记录");
} @ExceptionHandler(AuthorizationException.class)
public R handleAuthorizationException(AuthorizationException e){
logger.error(e.getMessage(), e);
return R.error("没有权限,请联系管理员授权");
} @ExceptionHandler(Exception.class)
public R handleException(Exception e){
logger.error(e.getMessage(), e);
return R.error();
}
}

小结:

本次讲解的是如何将Controller写的更加简洁,同时也不要忘记一点,前面说到Controller的代码不能过于庞大,那么service可以稍微庞大点,前提是在业务需要的情况下。当然了,最好还是那句话,代码能写短点就短点,利于维护,提高性能。当然了,凡事没有绝对,不一定代码写的长,执行性能就差。这就需要开发者们实际开发中多注意。同时关于代码规范,可以参考借鉴《阿里巴巴Java开发手册》,毕竟是咱们中国人自己开创的。另外最近再看一本新书叫《码出高效》,翻了几章,觉得挺不错的,在此推荐给大家。

Controller如何写的更简化的更多相关文章

  1. 如何在 ASP.NET Core 中写出更干净的 Controller

    你可以遵循一些最佳实践来写出更干净的 Controller,一般我们称这种方法写出来的 Controller 为瘦Controller,瘦 Controller 的好处在于拥有更少的代码,更加单一的职 ...

  2. Controller里写自己需要的Action,参数的名字必须和路由设置的参数名一致

    Controller里写自己需要的Action,参数的名字必须和路由设置的参数名一致,如果参数不一致,传过去为null

  3. java 11 移除的一些其他内容,更简化的编译运行程序,Unicode 10,移除了不太使用的JavaEE模块和CORBA技术,废除Nashorn javascript引擎,不建议使用Pack200 相关api

    移除的一些其他内容 移除项 移除了com.sun.awt.AWTUtilities 移除了sun.misc.Unsafe.defineClass, 使用java.lang.invoke.MethodH ...

  4. 使用Groovy+Spock轻松写出更简洁的单测

    当无法避免做一件事时,那就让它变得更简单. 概述 单测是规范的软件开发流程中的必不可少的环节之一.再伟大的程序员也难以避免自己不犯错,不写出有BUG的程序.单测就是用来检测BUG的.Java阵营中,J ...

  5. SSD 为什么顺序写比随机写性能更好?

    SSD以Page为单位做读写,以Block为单位做垃圾回收,Page一般有16KB大小,Block一般有几十MB大小,SSD写数据的逻辑是: 1)将该块数据所在的Page读出 2)修改该Page中该块 ...

  6. [label][翻译][JavaScript-Translation]七个步骤让你写出更好的JavaScript代码

    7 steps to better JavaScript 原文链接: http://www.creativebloq.com/netmag/7-steps-better-javascript-5141 ...

  7. Groovy系列-groovy比起Java--有哪些地方写起来更舒服?

    groovy比起java-有哪些地方写起来更舒服 java发展缓慢,语法落后冗余 说起java,其实java挺好的,java现在的性能也不错,但是,java的语法显然比较落后,而且冗余,getter/ ...

  8. 用Less定义常用的CSS3效果函数及常用颜色搭配(让CSS写起来更有趣)

    定义圆角及调用 /* 定义圆角 @radius 圆角大小 */ .round(@radius:5px){ border-radius:@radius; -webkit-border-radius: @ ...

  9. 如何让你的JS代码写的更漂亮

    感觉这篇文章总结的js的规范写法不错,拿来收藏.转自:https://mp.weixin.qq.com/s/AtR94IL9BW9EXOTnKOilmA 1. 按强类型风格写代码 JS是弱类型的,但是 ...

随机推荐

  1. Mavean多工程依赖项目

    前言 本篇文章基于Java开发小技巧(二):自定义Maven依赖中创建的父工程project-monitor实现,运用我们自定义的依赖包进行多工程依赖项目的开发. 下面以多可执行Jar包项目的开发为例 ...

  2. CenOs7安装oracle图文详细过程(01)

    原创作品,转载请在文章头部(显眼位置)注明出处:https://www.cnblogs.com/sunshine5683/p/10011441.html 1.检查必要的安装包是否安装 命令脚本: rp ...

  3. C# 设计模式·创建型模式

    面试问到这个··答不出来就是没有架构能力···这里学习一下···面试的时候直接让我说出26种设计模式··当时就懵逼了··我记得好像之前看的时候是23种的 还有3个是啥的··· 这里先列出几种创建型模式 ...

  4. Java自定义cas操作

    java Unsafe工具类提供了一个方法 public final native boolean compareAndSwapObject(Object var1, long var2, Objec ...

  5. zoj 1037 最短路

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=37 找规律,水题 #include<iostream> #inclu ...

  6. cf1060D. Social Circles(贪心)

    题意 题目链接 Sol 我是这样考虑的:从大到小考虑每个\(l, r\),最大的\(l\)应该和最大的\(r\)匹配(不然就亏了),其次次大的\(r\)应该和次大的\(l\)匹配 然后就过了.. /* ...

  7. Django实现验证码

    简单搞定生成验证码: 1.views.py from io import BytesIO import random from PIL import Image,ImageDraw,ImageFont ...

  8. MUI框架-11-MUI前端 +php后台接入百度文字识别API

    MUI框架-11-MUI前端 +php后台接入百度文字识别API 这里后台不止一种,Python,Java,PHP,Node,C++,C# 都可以 这里使用的是 php 来介绍,已经解决所有问题,因为 ...

  9. Android解析WindowManagerService(一)WMS的诞生

    前言 此前我用多篇文章介绍了WindowManager,这个系列我们来介绍WindowManager的管理者WMS,首先我们先来学习WMS是如何产生的.本文源码基于Android 8.0,与Andro ...

  10. 启用代理导致 有道云笔记未知错误、网络错误和OneDrive断线

    最近有道云笔记和OneDrive时不时的连接不上服务器,不知道什么原因?后来到有道官网上看了下,才发现,和IE浏览器的设置有关系: 我本地因为之前设置了代理,然后自己忘记了,代理的软件没开,导致IE上 ...