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封装的数据一模一样。

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


腾讯云社区邀请各位技术博主加入,福利多多噢!
Last modification:August 11th, 2020 at 02:35 pm
如果觉得我的文章对你有用,请随意赞赏