基于SpringBoot的Web前后端分离开发

基于SpringBoot的Web前后端分离开发

SpringBoot主程序

@SpringBootApplication

这是一个SpringBoot启动类的注解。

可以完成一系列自动化配置。

@SpringBootApplication
public class DemoApplication {

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }

}

开发一个URL

开发一个可以在浏览器直接访问的URL地址,也就是常说的API接口,前后端分离后一般都是RESTful风格

返回的数据是Json格式,因此有了@RequestBody注解

  • @Controller
  • @RequestMapping("url地址")
  • @ResponseBody

@Controller 可以让你的类成为一个API接口类

@RequestMapping("url地址") 可以让你用一个方法开发出一个url接口

@ResponseBody 可以让你返回的数据为json格式

因此在这样的环境下,业内有了 controller 层,即建一个 controller 包来放置你的API类

@Controller
public class DemoController {

    @RequestMapping("/demo")
    @ResponseBody
    public String print(){
        System.out.println("钟小湖");
        return "哈哈";
    }
}

带参数的URL

例如Get请求

实现也很简单

直接在方法上加入参数即可

@Controller
public class DemoController {

    @RequestMapping("/demo")
    @ResponseBody
    public String print(String name){
        System.out.println("Hello," + name);
        return name;
    }
}

public String print(String name)

然后你也可以更花哨点使用别名对name进行映射,或者前端工程师已经规定好了参数名,你迫于无奈。

举个例子:请求体参数是nick,你想在后台转化为name

nick = name

这时候 @RequestParam 注解就发挥作用了

@Controller
public class DemoController {

    @RequestMapping("/demo")
    @ResponseBody
    public String print(@RequestParam("nick") String name){
        System.out.println("Hello," + name);
        return name;
    }
}

问题来了,RESTful 讲究把参数直接通过网址的形式传送

例如 localhost:8080/demo/乐心湖

这时候 @PathVariable 注解就出来了

@Controller
public class DemoController {

    @RequestMapping("/demo/{name}")
    @ResponseBody
    public String print(@PathVariable String name){
        System.out.println("Hello," + name);
        return name;
    }
}

重点: @RequestMapping("/demo/{name}") 中的 {} 符号

多个参数也是可以的

@RequestMapping("/demo/{id}/{name}")
@ResponseBody
public String print(@PathVariable String name, @PathVariable String id) {
    System.out.println(id + name);
    return id + name;
}

还有更高级的自定义

@PathVariable("映射的参数")

例如:

@PathVariable("name") String name
//这样就可以把地址上的name变成程序内部的name了。
//就是最基础的映射
//因为name本身结果也是name,所以SpringMvc会自动帮我们映射,这个映射是没有必要写的。

所以,很多人习惯性把映射也写上,以为这是必需要的。

事实上你只需确保你的参数名不要瞎改,很多多余工作我们也就省去了。

值得一提的是:这一切的注解和花哨操作都是基于两个接口

HttpServletRequest

HttpServletResponse

例如我们使用 @RequestParam 获取了请求头中的name参数

也可以用老大哥 HttpServletRequest 实现

@Controller
public class DemoController {

    @RequestMapping("/demo")
    @ResponseBody
    public String print(HttpServletRequest request){
        String name = request.getParameter("name");
        System.out.println("Hello," + name);
        return name;
    }
}

例如我们使用 @ResponseBody + return 来返回数据

我们也可以用老大哥 HttpServletResponse

@Controller
public class DemoController {

    @RequestMapping("/demo")
//    @ResponseBody
    public void print(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String name = request.getParameter("name");
        System.out.println("Hello," + name);
        response.getWriter().print("Hello " + name );
//        return name;
    }
}

当然你会发现 name 中文时会出现乱码,因此有了设置编码的操作

response.setContentType("application/json;charset=utf-8");
response.setCharacterEncoding("utf-8");

聪明的你一定知道要写在输出之前吧!

关于 HttpServletRequest 接口是非常非常非常常用的。

方法 用途
getRequestURL() 返回客户端发出请求时的完整URL。
getRequestURI() 返回请求行中的参数部分。
getQueryString () 方法返回请求行中的参数部分(参数名+值)
getRemoteHost() 返回发出请求的客户机的完整主机名。
getRemoteAddr() 返回发出请求的客户机的IP地址。
getPathInfo() 返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以"/"开头。
getRemotePort() 返回客户机所使用的网络端口号。
getLocalAddr() 返回WEB服务器的IP地址。
getLocalName() 返回WEB服务器的主机名。
getHeader(string name) 以 String 的形式返回指定请求头的值。如果该请求不包含指定名称的头,则此方法返回 null。如果有多个具有相同名称的头,则此方法返回请求中的第一个头。头名称是不区分大小写的。可以将此方法与任何请求头一起使用
getParameter(String name) 根据name获取请求参数(常用)

可以自己测试使用。都是比较简单易用的方法。

业务封装

当你的代码多了,全部写在 controller 层就不雅观而已难看

所以有了 Service 层

Spring鼓励我们面向接口开发,因此这层Service我们一般会使用 接口+实现类的方式。

例如 我现在要对 response中文乱码的解决方案放到 Service

新建一个接口 DemoService

public interface DemoService {
    void print(HttpServletResponse response);
}

接着去实现这个方法。

@Service
public class DemoServiceImpl implements DemoService {
    @Override
    public void print(HttpServletResponse response) {
        response.setContentType("application/json;charset=utf-8");
        response.setCharacterEncoding("utf-8");
    }
}

你会注意到这里多了个 @Service 注解,他能够帮你将这个实现类托管到Spring工厂中,使其成为一个组件,日后你就不用new了。直接注入组件即可。

于是注入组件我们用到了一个 @AutoWired 注解

@Controller
public class DemoController {

    @Autowired
    private DemoService demoService;
}

你可以观察到这里注入的是接口,而非实现类。

这就是Spring的优雅之处,能够让你真正面向接口开发。你只管按规矩办事,其他交给Spring处理。

现在的接口层是下面这样的。

@Controller
public class DemoController {

    @Autowired
    private DemoService demoService;

    @RequestMapping("/demo")
//    @ResponseBody
    public void print(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String name = request.getParameter("name");
        System.out.println("Hello," + name);
        demoService.print(response);
        response.getWriter().print("Hello " + name );
//        return name;
    }
}

是不是依旧很优雅。

为了开发更加便捷,加上 RESTful 风格的大力推广。前后端分离的趋势难以阻挡,很多时候我们几乎都是返回json串。

因此有了一个新的注解

@RestController

它是 @ResponseBody + @Controller 的组合体。使用在类上,可以让你这个类的所有方法都返回json数据。

数据封装

当然Web开发离不开数据传输。

事实上,Map就可以自动装配这一点。

//@Controller
@RestController
public class DemoController {

    @RequestMapping("/demo")
//    @ResponseBody
    public Map<String,Object> print() {

        Map<String,Object> map = new HashMap<>();

        map.put("id","9999");
        map.put("name","乐心湖");
        map.put("age","18");
        return map;
    }

}

多个map数据,我们就可以用List来收集。

//@Controller
@RestController
public class DemoController {

    @RequestMapping("/demo")
//    @ResponseBody
    public ArrayList<Map<String, Object>> print() {

        ArrayList<Map<String, Object>> mapArrayList = new ArrayList<>();


        Map<String,Object> map1 = new HashMap<>();
        Map<String,Object> map2 = new HashMap<>();

        map1.put("id","9999");
        map1.put("name","乐心湖");
        map1.put("age","18");

        map2.put("id","8888");
        map2.put("name","钟小湖");
        map2.put("age","19");

        mapArrayList.add(map1);
        mapArrayList.add(map2);

        return mapArrayList;
    }

}

这么优雅的数据,快点学起来吧。

数据难免要跟数据库打交道,那我们就去摸索一遍。

以 Mysql 为例,建一个 demo数据库

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for demo
-- ----------------------------
DROP TABLE IF EXISTS `demo`;
CREATE TABLE `demo`  (
  `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of demo
-- ----------------------------
INSERT INTO `demo` VALUES ('8888', '钟小湖', '19');
INSERT INTO `demo` VALUES ('9999', '乐心湖', '18');

SET FOREIGN_KEY_CHECKS = 1;

怎么把数据对接到 SpringBoot 呢,这时候持久化框架就出现了。

在查询数据之前,你需要一个类,里面带着参数跟咱数据库字段要一样的吧?

因此我们讲这个类叫做实体映射类,用于取代无数据库时采用的map类型

因此早期我们使用 model 层来封装跟数据库一一对应的参数。

现在人们习惯使用 entity 层来代替它。

package com.example.demo.entity;

import lombok.Data;

@Data
public class Demo {
    private String id;
    private String name;
    private String age;
}

这里有个 @Data 注解可能是伴随着你未来一生的。

他是 lombok 带来的,能够自动帮我们写 get set 方法

你需要在idea安装好lombok插件,然后在项目中引入依赖。

<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>mybatis-plus-boot-starter</artifactId>
   <version>3.3.2</version>
</dependency>
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <version>1.18.12</version>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>8.0.20</version>
</dependency>

这里顺便把 Mysql 连接的依赖给引入了。还有一个 mybatis-plus,这应该不用过多介绍吧。

于是我们需要去写数据库的配置

application.properties 下直接开整。

spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
#数据库用户名
spring.datasource.username=root
#数据库密码
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#配置mybatis xml文件所在位置
mybatis-plus.mapper-locations=classpath:/mapper/*.xml

配置完成之后,我们就要去写sql语句了。

因此 Mybatis 规定了使用 Mapper 层做持久化操作。

@Mapper
public interface DemoMapper {
    List<Demo> select();
}

对这个接口进行sql实现

<?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="com.example.demo.mapper.DemoMapper">

    <select id="select" resultType="com.example.demo.entity.Demo">
        SELECT * FROM demo
    </select>
</mapper>

这样工作就基本完成了。

你可以在service层测试,也可以在controller层测试。

@RestController
public class DemoController {

    @Autowired
    private DemoMapper demoMapper;


    @RequestMapping("/demo")
//    @ResponseBody
    public List<Demo> print() {
        List<Demo> select = demoMapper.select();
        return select;
    }

}

访问/demo,效果跟原来map封装的数据一模一样。

最基本的开发流程大概就如此,你学会了吗?

转载于:https://www.xn2001.com/archives/544.html

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

推荐阅读更多精彩内容

  • 第一次用简书,觉得简书有着印象笔记没有的功能,在线分享资源,并且还是富文本编辑器类型。现在项目是采用前后端分离,用...
    zhuyuansj阅读 2,961评论 0 16
  • 摘要:MVC模式早在上个世纪70年代就诞生了,直到今天它依然存在,可见生命力相当之强。MVC模式最早用于Small...
    在风口阅读 1,550评论 1 20
  • 本文首先描述 MVC 模式是什么,然后针对 MVC 的不足发表了作者的个人观点,随后引出了基于 REST 架构实现...
    java菜阅读 824评论 0 2
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,480评论 16 22
  • 创业是很多人的梦想,多少人为了理想和不甘选择了创业来实现自我价值,我就是其中一个。 创业后,我由女人变成了超人,什...
    亦宝宝阅读 1,802评论 4 1