SSM-Springboot笔记(2)- SpringBoot常用开发技能

1 SpringBoot常用开发技能

1.1 项目架构

  • 创建项⽬
  • 配置启动类
  • 建⽴对应的包,先建⽴这些包,其他⽤到再补充
controller
service
mapper
domain
utils

1.2 开发HTTP接⼝GET请求

GET请求
场景:⼀般的查询接⼝就是get请求
注解:@GetMapping = @RequestMapping(method = RequestMethod.GET)
⼀个顶两的注解

@GetMapping = @RequestMapping(method = RequestMethod.GET)
@PostMapping = @RequestMapping(method = RequestMethod.POST)
@PutMapping = @RequestMapping(method = RequestMethod.PUT)
@DeleteMapping = @RequestMapping(method = RequestMethod.DELETE)

示例:视频列表查询

  • 实体类:Video
public class Vedio implements Serializable {
    private Integer id;
    private String title;
    private String summary;
    private Integer price;
    private String coverImg;
    private Date createTime;

    public Vedio() {
    }

    public Vedio(Integer id, String title) {
        this.id = id;
        this.title = title;
        this.createTime = new Date();
    }
// 省get、set、tostring方法
  • mapper类:VideoMapper
@Repository
public class VideoMapper {
    private static Map<Integer, Vedio> videoMap = new HashMap<>();

    /**
     * 模拟数据
     */
    static {
        videoMap.put(1, new Vedio(1 , "东邪西毒"));
        videoMap.put(2, new Vedio(2 , "精武英雄"));
        videoMap.put(3, new Vedio(3 , "霸王别姬"));
        videoMap.put(4, new Vedio(4 , "南极大冒险"));
        videoMap.put(5, new Vedio(5 , "变形金刚"));
        videoMap.put(6, new Vedio(6 , "流浪地球"));
    }

// 获取视频列表
    public List<Vedio> listVideo() {
        List<Vedio> list = new LinkedList<>();

        list.addAll(videoMap.values());

        return list;
    }
}
  • service类,包括接口和实现类
    接口类: VideoService
public interface VideoService {
    List<Vedio> listVideo();
}

实现类:VideoServiceImpl

@Service
public class VideoServiceImpl implements VideoService {

    @Autowired  // 自动注入VideoMapper
    private VideoMapper videoMapper;

    @Override
    public List<Vedio> listVideo() {
        return videoMapper.listVideo();
    }
}
  • Controller类:VideoController
@RestController
@RequestMapping("/app/v1/video")
public class VideoController {
    @Autowired  // 自动注入VideoService实现类
    private VideoService videoService;

    @RequestMapping("list")
    public Object getList() {

        return videoService.listVideo();
    }
}

测试:

  • 启动程序
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.2)

2022-01-12 14:11:05.388  INFO 20464 --- [           main] c.j.s.Springbootdemo2Application         : No active profile set, falling back to default profiles: default
2022-01-12 14:11:06.005  INFO 20464 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-01-12 14:11:06.011  INFO 20464 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-01-12 14:11:06.011  INFO 20464 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-12 14:11:06.068  INFO 20464 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-01-12 14:11:06.068  INFO 20464 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 646 ms
2022-01-12 14:11:06.315  INFO 20464 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-12 14:11:06.321  INFO 20464 --- [           main] c.j.s.Springbootdemo2Application         : Started Springbootdemo2Application in 1.198 seconds (JVM running for 1.959)
  • 访问接口

1.3 制定统⼀接⼝返回协议

实际开发中通过⾃定义返回对象,统⼀协议,能够有效的避免开发中协议不统一导致的许多问题,而且还能提供工作的效率。

  • 自定义返回信息对象(务必生成get、set方法)
/**
 * 业务返回信息类
 */
public class RetData {
    /**
     * 业务返回码,默认:0:成功,-1:失败
     */
    private int code;   // 业务返回码

    /**
     * 业务数据
     */
    private Object data;    // 业务数据

    /**
     * 返回信息
     */
    private String message; // 状态信息

    public RetData(){}

    public RetData(int code, Object data, String message) {
        this.code = code;
        this.data = data;
        this.message = message;
    }

    /**
     * 无参返回成功,默认返回码
     */
    public static RetData RetSuccess() {
        return new RetData(0, null, "success");
    }

    /**
     * 有参返回成功,默认返回码
     * @param data
     * @return
     */
    public static RetData RetSuccess(Object data) {
        return new RetData(0, data, "success");
    }

    /**
     * 无参返回错误,默认返回码
     * @return
     */
    public static RetData RetError() {
        return new RetData(-1, null, "unknow error");
    }

    /**
     * 默认返回码带错误信息
     * @param msg
     * @return
     */
    public static RetData RetError(String msg) {
        return new RetData(-1, null, msg);
    }

    /**
     * 自定义返回码带错误信息
     * @param code
     * @param msg
     * @return
     */
    public static RetData RetError(int code, String msg) {
        return new RetData(code, null, msg);
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
  • 在VideoController类中使用RetData返回
    @RequestMapping("list")
    public Object getList() {

        return RetData.RetSuccess(videoService.listVideo()); // 使用RetData返回
    }
  • 重启程序并访问接口,返回结果如下:
    code:业务返回码
    data:业务数据
    message:返回信息
{
    "code": 0,
    "data": [
        {
            "id": 1,
            "title": "东邪西毒",
            "summary": null,
            "price": null,
            "coverImg": null,
            "createTime": "2022-01-12T06:43:36.907+00:00"
        },
        {
            "id": 2,
            "title": "精武英雄",
            "summary": null,
            "price": null,
            "coverImg": null,
            "createTime": "2022-01-12T06:43:36.907+00:00"
        },
        {
            "id": 3,
            "title": "霸王别姬",
            "summary": null,
            "price": null,
            "coverImg": null,
            "createTime": "2022-01-12T06:43:36.907+00:00"
        },
        {
            "id": 4,
            "title": "南极大冒险",
            "summary": null,
            "price": null,
            "coverImg": null,
            "createTime": "2022-01-12T06:43:36.907+00:00"
        },
        {
            "id": 5,
            "title": "变形金刚",
            "summary": null,
            "price": null,
            "coverImg": null,
            "createTime": "2022-01-12T06:43:36.907+00:00"
        },
        {
            "id": 6,
            "title": "流浪地球",
            "summary": null,
            "price": null,
            "coverImg": null,
            "createTime": "2022-01-12T06:43:36.907+00:00"
        }
    ],
    "message": "success"
}

1.4 开发HTTP接⼝POST请求

POST请求-form表单
场景:表单提交,如果不⽤细分PUT/DELETE⽅法,则都可以⽤POST
注解:@PostMapping = @RequestMapping(method = RequestMethod.POST)
测试:

  • 编写UserController类
@RestController
@RequestMapping("/app/v1/user")
public class UserController {

    @PostMapping("login")
    public RetData login(String username, String pwd) {

        System.out.println("username:" + username + ",pwd:" + pwd);
        return RetData.RetSuccess("");
    }
}
  • 启动程序
  • 采用参数形式

能够正常接收post提交的参数

  • 采用form表单形式

也能够正常接收post提交的参数

实际开发中,参数数量比较多,通常我们会用对象接收参数,修改UserController如下:

@RestController
@RequestMapping("/app/v1/user")
public class UserController {

    @PostMapping("login")
    public RetData login(User user) {

        System.out.println("user:" + user.toString());
        return RetData.RetSuccess("");
    }
}

再次使用form表达形式提交

程序依然能够正常接收post提交的参数

user:User{id=null, username='tom', password='8888'}

但实际开发中,接口一般都是以json形式提交参数,提交方式如下:

此时程序无法正常接收数据

user:User{id=null, username='null', password='null'}

为了正常接收json形式的参数,需要在对象参数前面加注解:@RequestBody
注意:参数名字与对象属性名称保持一致

    @PostMapping("login")
    public RetData login(@RequestBody User user) {

        System.out.println("user:" + user.toString());
        return RetData.RetSuccess("");
    }

这样才能正常的接收

user:User{id=null, username='fanny', password='123456'}

开发示例:账号密码提交登录接⼝,form表单形式

  • Mapper类:UserMapper
@Repository
public class UserMapper {
    private static Map<String, User> userMap = new HashMap<>();

    static {
        userMap.put("jackyan", new User(1, "jackyan", "123456"));
        userMap.put("lucy", new User(2, "lucy", "888888"));
        userMap.put("tom", new User(3, "tom", "666666"));
        userMap.put("fancy", new User(4, "fancy", "555555"));
    }

    public User login(String username, String password) {
        User user = userMap.get(username);

        if (user == null) {
            return null;
        } else if (user.getPassword().equals(password)) {
            return user;
        }

        return null;
    }
}
  • Service类
    接口类:UserService
public interface UserService {
    public String login(String username, String password);
}

实现类:

@Service
public class UserServiceImpl implements UserService {
    // 模拟保存用户session
    private static Map<String, User> sessionMap = new HashMap<>();

    @Autowired
    private UserMapper userMapper;

    @Override
    public String login(String username, String password) {
        User user = userMapper.login(username, password);

        if (user == null) {
            return null;
        }

        String token = UUID.randomUUID().toString();
        
        // 保存用户session
        sessionMap.put(token, user);

        return token;
    }
}
  • Controller类:UserController
@RestController
@RequestMapping("/app/v1/user")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("login")
    public RetData login(@RequestBody User user) {

        String token = userService.login(user.getUsername(), user.getPassword());

        if (token == null) {
            return RetData.RetError("用户名或密码错误!");
        }
        return RetData.RetSuccess(token);
    }
}
  • 测试

登录成功

登录失败

1.5 RequestBody对象数组提交接⼝

POST请求-RequestBody⽅式
开发示例:新增视频json对象,章数组提交

  • Video类增加章列表信息
    private List<Chapter> chapterList;
  • 新增Chapter类
/**
 * 视频章信息
 */
public class Chapter {
    private Integer id;
    private Integer videoId;
    private String title;

    public Chapter() {
    }
    
    public Chapter(Integer id, Integer videoId, String title) {
        this.id = id;
        this.videoId = videoId;
        this.title = title;
    }
// 省略set、get、tostring方法
  • 编写Controller类测试
    @PostMapping("save_video")
    public RetData saveVideo(@RequestBody Video video) {
        return RetData.RetSuccess(video);
    }
  • 测试,发送数据
{
    "id":1001,
    "title":"精武英雄",
    "chapterList":[
        {
        "id":10001,
        "title": "日本求学"
        },
        {
        "id":10002,
        "title": "回国探师"
        },
        {
        "id":10003,
        "title": "比武切磋"
        }
    ]
}
  • 测试结果
{
    "code": 0,
    "data": {
        "id": 1001,
        "title": "精武英雄",
        "summary": null,
        "price": null,
        "coverImg": null,
        "createTime": null,
        "chapterList": [
            {
                "id": 10001,
                "videoId": null,
                "title": "日本求学"
            },
            {
                "id": 10002,
                "videoId": null,
                "title": "回国探师"
            },
            {
                "id": 10003,
                "videoId": null,
                "title": "比武切磋"
            }
        ]
    },
    "message": "success"
}

1.6 定制JSON字段

springboot中自带jackson相关包,可以用来定制化处理实体类字段相关信息:
指定字段不返回:@JsonIgnore
指定⽇期格式:@JsonFormat(pattern="yyyy-MM-dd hh:mm:ss",locale="zh",timezone="GMT+8")
空字段不返回:@JsonInclude(Include.NON_NULL)
指定别名:@JsonProperty

    @JsonProperty("cover_img") // 给字段取别名
    private String coverImg;
    @JsonFormat(pattern="yyyy-MM-dd hh:mm:ss",locale="zh",timezone="GMT+8")
    @JsonProperty("create_time")
    private Date createTime;
    @JsonProperty("chapter_list")
    @JsonIgnore // 该字段不返回
    private String password;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,442评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,604评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,576评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,652评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,495评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,370评论 1 274
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,792评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,435评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,735评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,777评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,553评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,399评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,806评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,038评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,330评论 1 253
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,766评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,964评论 2 337

推荐阅读更多精彩内容

  • 写文章 一、SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的j...
    刺绣兰溪阅读 542评论 0 0
  • maven 什么是maven 项目管理工具 pom mybatis参数 默认通过书信值引用。 多个参数 map s...
    万里无风来阅读 284评论 0 0
  • 1、什么是MVC 2、什么是SpringMVC 3、SpringMVC的特点 1、开发环境 2、创建maven工程...
    小茅同学阅读 270评论 0 0
  • 三层架构 和 MVC模型 三层架构:我们在Servlet 学习笔记讲过,当前 Web 应用体系主要为 C/S架构 ...
    Whyn阅读 511评论 0 0
  • springmvc学习笔记 学习springmvc框架原理 包括哪些组件: 前端控制器(中心) 处理器映射器(三大...
    罗志贇阅读 1,170评论 0 51