Controller层编码规范

controller层在MVC设计中属于控制层;设计初衷:接受请求并响应请求;所以,该层尽量轻薄,避免编写涉及业务处理的代码。

前后端分离的开发设计模式下,推荐使用@RestController注解,它相当于@ResponseBody + @Controller的组合使用。

1) 如果只是使用@RestController注解Controller类,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容,默认转成json串。

2) 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。

    如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。

总之,使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面;若返回json等内容到页面,则需要加@ResponseBody注解

1)设定请求路径

使用注解@PostMapping("/page"),类命名和方法命名之上都可以加。

注意按照不同业务进行划分使用,避免乱写乱用。

2)设置请求方式

    常用的POST/GET。使用注解:@RequestMapping   和  @GetMapping @PostMapping。

    Spring4.3中引进了{@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping} 来帮助简化常用的HTTP方法的映射 并更好地表达被注解方法的语义 

该注解将HTTP Get 映射到 特定的处理方法上

    @GetMapping是一个组合注解,它是@RequestMapping(method = RequestMethod.GET)的缩写

    @PostMapping是一个组合注解,它是@RequestMapping(method = RequestMethod.POST)的缩写

3)设置请求参数方式

表单提交,直接使用vo类或具体参数名接收;

@Controller

public class LoginController {

    @RequestMapping(value = "login", method = RequestMethod.POST)

    public String login(UserVO user){

        System.out.println("POJO: " + user.getClass().getName() +

                ", hash code: " + user.hashCode() + ", " + user.toString());

        return "redirect:/";

    }

}

②@RequestParam

@RequestParam(value="", required=true, defaultValue="")

@RequestParam 有三个属性:

(1)value:请求参数名(必须配置)

(2)required:是否必需,默认为 true,即 请求中必须包含该参数,如果没有包含,将会抛出异常(可选配置)

(3)defaultValue:默认值,如果设置了该值,required 将自动设为 false

@ApiOperation(value = "根据id查询")

@PostMapping("/show")

public Responses show(@RequestParam(value="userId",defaultValue="-1") Long userId) {

    Record data = recordService.getOne(vo.getId());

    return Responses.success(data);

}

③n提交,使用注解@RequestBody。

@RequestBody主要用来接收前端以POST方式传递给后端的json字符串中的数据的(请求体中的数据的);GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。

注:一个请求,只有一个RequestBody;一个请求,可以有多个RequestParam。

@ApiOperation(value = "根据id查询")

@PostMapping("/get")

public Responses getOne(@Validated @RequestBody IdVO vo){

    Record data = recordService.getOne(vo.getId());

    return Responses.success(data);

}

④athVariable

@RestController

@RequestMapping("/")

public class ChineseDrugController {

@ResponseBody

@RequestMapping(value = "/{name}")

public String showName(@PathVariable String name, @PathVariable(value = "name", required = false) String sex) {

return "Hello " + name + sex;

}

⑤@PathParam

url:http://127.0.0.1:8080/sexvalue/namevalue?name=唐&sex=男

@RestController

@RequestMapping(value = "/{sex}")

public class ChineseDrugController {

@ResponseBody

@RequestMapping(value = "/{name}")

public String showName(@PathVariable(value = "name") String name, @PathParam(value = "sex") String sex) {

return "Hello " + name + " " + sex;

}

}

说明:以上代码仅仅展示功能上有很好的灵活性,实际开发中避免如此任意使用 。

4)校验请求参数

参数校验

①使用注解@Validated,使得参数自动校验生效,它是spring-contex中的注解;

②vo类中自定义各类校验,比如@NotNull等,他是javax下validation-api中的注解此处不赘述;

③程序层面的校验。

方法示例如下

@ApiOperation(value = "应用类型和应用关系绑定")

@PostMapping("/applicationTypeBind")

public Boolean applicationTypeBind(@Validated @RequestBody ApplicationBindVO vo){

    applicationTypeService.applicationTypeBind(vo);

    return true;

}

对应VO类示例

import io.swagger.annotations.ApiModel;

import io.swagger.annotations.ApiModelProperty;

import lombok.Data;

import javax.validation.constraints.NotEmpty;

import javax.validation.constraints.NotNull;

import java.util.List;

import java.util.Set;

@Data

@ApiModel(value = "ApplicationBindVO",description = "关系绑定vo")

public class ApplicationBindVO {

    @NotNull

    @ApiModelProperty("应用类型id")

    private Long typeId;

    @ApiModelProperty("应用id集合")

    private List<Long> applicationIdList;

}

 5)入参出参设计

依据业务而定,格式尽量做到统一;

响应前端(APP/PC)的参数,一般再封装一层,方便前端统一处理,如下返回

Responses.success(data);

import com.fasterxml.jackson.annotation.JsonView;

import com.myfutech.common.util.enums.ResponseCode;

import com.myfutech.common.util.vo.BaseView;

import io.swagger.annotations.ApiModel;

import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "Responses",description = "响应信息")

public class Responses<T> {


@JsonView({BaseView.class})

    @ApiModelProperty("响应编码")

    private String code;


    @JsonView({BaseView.class})

    @ApiModelProperty("响应消息")

    private String msg;


    @JsonView({BaseView.class})

    @ApiModelProperty("响应体")

    private T result;


    public static <T> Responses<T> success() {

        return new Responses(ResponseCode.SUCCESS_CODE, "", (Object)null);

    }

    public static <T> Responses<T> success(T result) {

        return new Responses(ResponseCode.SUCCESS_CODE, "", result);

    }

    public static <T> Responses<T> success(String msg, T result) {

        return new Responses(ResponseCode.SUCCESS_CODE, msg, result);

    }

    public static <T> Responses<T> error(String msg) {

        return new Responses(ResponseCode.ERROR_CODE, msg, (Object)null);

    }

    public static <T> Responses<T> error(ResponseCode code) {

        return new Responses(code, code.getDefaultMsg(), (Object)null);

    }

    public static <T> Responses<T> error(ResponseCode code, String msg) {

        return new Responses(code, msg, (Object)null);

    }

    public Responses() {

    }

    private Responses(ResponseCode code, String msg, T result) {

        this.code = code.getCode();

        this.msg = msg;

        this.result = result;

    }

    public String getCode() {

        return this.code;

    }

    public boolean notSuccess() {

        return !ResponseCode.SUCCESS_CODE.getCode().equals(this.code);

    }

    public String getMsg() {

        return this.msg;

    }

    public T getResult() {

        return this.result;

    }

    public void setCode(String code) {

        this.code = code;

    }

    public void setMsg(String msg) {

        this.msg = msg;

    }

    public void setResult(T result) {

        this.result = result;

    }



}

6) 自动生成接口文档

    使用SwaggerAPI,

    常用注解

//加载类名之上

@Api(tags = "日志相关接口", description="操作日志",

        consumes= MediaType.APPLICATION_JSON_UTF8_VALUE,

        produces=MediaType.APPLICATION_JSON_UTF8_VALUE)

//加在方法名之上

@ApiOperation(value = "查询分页列表")

//加载实体或VO类名之上

@Data

@ApiModel(value = "ApprovalRoleModifyVO",description = "审批角色修改信息")

public class ApprovalRoleModifyVO{

 @Api:作用在类上,用来标注该类具体实现内容。表示标识这个类是swagger的资源 。 

    参数: 

    ①tags:可以使用tags()允许您为操作设置多个标签的属性,而不是使用该属性。 

    ②description:可描述描述该类作用。 

@ApiOperation:用于方法,表示一个http请求的操作 。

@ApiModel:用于方法,字段 ,表示对model属性的说明或者数据操作更改 

 2、一个相对标准controller类示例

package com.myfutech.employee.service.provider.ctrl;

import com.myfutech.common.util.Responses;

import com.myfutech.common.util.vo.IdVO;

import com.myfutech.common.util.vo.Page;

import com.myfutech.common.util.vo.Pageable;

import com.myfutech.employee.service.api.vo.response.record.RecordListVo;

import com.myfutech.employee.service.provider.model.Record;

import com.myfutech.employee.service.provider.service.RecordService;

import io.swagger.annotations.Api;

import io.swagger.annotations.ApiOperation;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.http.MediaType;

import org.springframework.validation.annotation.Validated;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**

*  相关接口

*/

@Api(tags = "日志相关接口", description="操作日志",

        consumes= MediaType.APPLICATION_JSON_UTF8_VALUE,

        produces=MediaType.APPLICATION_JSON_UTF8_VALUE)

@RestController

@RequestMapping("/record")

public class RecordCtrl {

    private static final Logger log = LoggerFactory.getLogger(RecordCtrl.class);

    @Resource(name="recordService")

    private RecordService recordService;

    @ApiOperation(value = "查询分页列表")

    @PostMapping("/page")

    public Page<RecordListVo> page( @RequestBody Pageable pageable){

        Page<RecordListVo> list = recordService.findConditionPage(pageable);

        return list;

    }

    @ApiOperation(value = "根据id查询")

    @PostMapping("/get")

    public Responses getOne(@Validated @RequestBody IdVO vo){

        Record data = recordService.getOne(vo.getId());

        return Responses.success(data);

    }

    @ApiOperation(value = "新增")

    @PostMapping("/add")

    public Responses add(@Validated(Record.Create.class) @RequestBody Record data){

        recordService.save(data);

        return Responses.success();

    }

    @ApiOperation(value = "更新")

    @PostMapping("/update")

    public Responses update(@Validated(Record.Update.class) @RequestBody Record data){

        recordService.save(data);

        return Responses.success();

    }

    @ApiOperation(value = "删除")

    @PostMapping("/delete")

    public Responses delete(@Validated @RequestBody IdVO vo){

        recordService.deleteById(vo.getId());

        return Responses.success();

    }

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容