请求响应

请求响应

请求响应类

  • 请求(HttpServletRequest):获取请求数据
  • 响应(HttpServletResponse):设置响应数据
  • BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。
  • CS架构:Client/Server,客户端(软件)/服务器架构模式。

获取Get请求参数

使用原始方式获取参数HttpServetRequest

  • 需要通过HttpServetRequest 对象手动获取

    注意

    使用HttpServetRequest获取的所有参数都是字符串,类型需要我们手动转换

package com.springboot.Controller;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    //get请求获取参数
    @RequestMapping("/getList")
    public String getList(HttpServletRequest request) {
        System.out.println(request.toString());
        String name = request.getParameter("name");
        System.out.println(name);
        int age = Integer.parseInt(request.getParameter("age"));
        System.out.println(age);
        return "success";
    }
}

使用springBoot方式请求

package com.springboot.Controller;

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

@RestController
public class HelloController {

    //get请求SpringBoot方式获取参数
    @RequestMapping("/getList2")
    public String getList2(String name, int age) {
        System.out.println(name);
        System.out.println(age);
        return "success";
    }
}

属性映射

package com.springboot.Controller;

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

@RestController
public class HelloController {
    @RequestMapping("/getList3")
//    如果方法形参名称与请求参数名称不匹配,获取的参数为空,不会报错
    //需要加入@RequestParam(name = "请求参数名")注解
    //RequestParam注解required属性默认为true,如果请求参数没有传,会报错
    //如果该参数是可选的,则required属性设置为false
    //defaultValue 属性,如果请求参数没有传,则使用默认值
    public String getList3(@RequestParam(name = "nameValue", required = false, defaultValue = "张三") String name, @RequestParam(name = "ageValue", required = false) int age) {
        System.out.println(name);
        System.out.println(age);
        return "success";
    }
}

实体参数

package com.springboot.Controller;

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

@RestController
public class HelloController {
    //实体参数
    //将请求的参数封装到一个实体类当中
    @RequestMapping("/getList4")
    public String getList4(User user) {
        System.out.println(user.getName());
        System.out.println(user.getAge());
        return "success";
    }
}

复杂实体参数

package com.springboot.Controller;

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

@RestController
public class HelloController {
    //复杂实体参数
    //@url http://localhost:8081/getList5?name=张三&age=35&address.city=昆明&address.street=五华
    @RequestMapping("/getList5")
    public String getList5(User user) {
        System.out.println(user);//User{name='张三', age=35, address=Address{city='昆明', street='五华'}}
        return "success";
    }
}

//用户实体类
package com.springboot.pojo;

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


public class User {
    private String name;
    private int age;
    private Address address;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

数组集合参数

  • 数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数

数组参数

package com.springboot.Controller;

import org.springframework.web.bind

@RestController
public class HelloController {
    /**
     * 数组集合参数 将参数加入到数组中
     * http://localhost:8081/getList6?name=张三&name=李四&name=王五
     */
    @RequestMapping("/getList6")
    public String getList6(String[] name) {
        System.out.println(Arrays.toString(name));//[张三, 李四, 王五]
        return "success";
    }
}

集合参数

需使用@RequestParam注解来绑定参数关系

package com.springboot.Controller;

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

@RestController
public class HelloController {
    /**
     * 集合参数
     * http://localhost:8081/getList7?name=张三&name=李四&name=王五
     */
    @RequestMapping("/getList7")
    public String getList7(@RequestParam List<String> name) {
        System.out.println(name.toString());//[张三, 李四, 王五]
        return "success";
    }
}

日期类型参数

  • 日期参数:使用@DateTimeFormat注解来完成日期参数格式的转换
package com.springboot.Controller;

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

@RestController
public class HelloController {
    /**
     * 日期参数
     * http://localhost:8081/getList8?date=1999-07-31 12:25:12
     */
    @RequestMapping("/getList8")
    public String getList8(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime date) {
        System.out.println(date);//1999-07-31T12:25:12
        return "success";
    }
}

Json类型参数

package com.springboot.Controller;

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

@RestController
public class HelloController {
    /**
     *json参数
     * method=POST
     * http://localhost:8081/getList9
     * data:{
     *     "name":"张三",
     *     "age":18,
     *     "address":{
     *         "city":"北京",
     *         "street":"黑林铺"
     *     }
     * }
     */
    @RequestMapping("/getList9")
    public String getList9(@RequestBody User user) {
        System.out.println(user.toString());//{name='张三', age=18, address=Address{city='北京', street='黑林铺'}}
        return "success";
    }
}
package com.springboot.pojo;


//用户实体类
public class User {
    private String name;
    private int age;
    private Address address;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
package com.springboot.pojo;

public class Address {
    private String city;//城市
    private String street;//街道

    @Override
    public String toString() {
        return "Address{" +
                "city='" + city + '\'' +
                ", street='" + street + '\'' +
                '}';
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }
}

路径参数

  • 路径参数:通过请求URL直接传递参数
  • 使用{...}来标识该路径参数,需要使用 @PathVariable 获取路径参数

注意

路径中不能使用中文

package com.springboot.Controller;

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

@RestController
public class HelloController {
    /**
     * 路径参数
     * http://localhost:8081/getList10/path/1/ton
     */
    @RequestMapping("/getList10/path/{id}/{name}")
    public String getList10(@PathVariable Integer id, @PathVariable String name) {
        System.out.println(id);//1
        System.out.println(name);
        return "success";
    }
}

响应结果

  • @ResponseBody注解
  • 类型:方法注解、类注解
  • 位置:Controller方法上/类上
  • 作用将方法返回值直接响应,如果返回值类型是实体对象/集合,将会转换为JSON格式响应
  • 说明:@RestController=@Controller+@ResponseBod

统一响应结果

构造一个统一的响应类,将响应结果封装到该类中,然后返回该类即可

package com.springboot.pojo;

//响应返回类
public class Result {
    private int code;
    private String msg;
    private Object data;

    public Result() {

    }

    public Result(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    //静态方法 用于快速构建一个返回类
    //请求成功
    public static Result success(Object data) {
        return new Result(200, "请求成功", data);
    }

    //请求失败
    public static Result err(String msg) {
        return new Result(0, msg, null);
    }

    //请求失败
    public static Result err(int code, String msg) {
        return new Result(code, msg, null);
    }

    public int getCode() {
        return code;
    }

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

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

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

    @Override
    public String toString() {
        return "Result{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
}

使用返回类对象返回数据

package com.springboot.Controller;

import com.springboot.pojo.Result;

@RestController
public class HelloController {
    /**
     * 日期参数
     * http://localhost:8081/getList8?date=1999-07-31 12:25:12
     */
    @RequestMapping("/getList8")
    public Result getList8(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime date) {
        System.out.println(date);//1999-07-31T12:25:12
        return Result.success(date);
    }

    /**
     *json参数
     * method=POST
     * http://localhost:8081/getList9
     * data:{
     *     "name":"张三",
     *     "age":18,
     *     "address":{
     *         "city":"北京",
     *         "street":"黑林铺"
     *     }
     * }
     */
    @RequestMapping("/getList9")
    public Result getList9(@RequestBody User user) {
        System.out.println(user.toString());//{name='张三', age=18, address=Address{city='北京', street='黑林铺'}}
        return Result.success(user);
    }

    /**
     * 路径参数
     * http://localhost:8081/getList10/path/1/ton
     */
    @RequestMapping("/getList10/path/{id}/{name}")
    public Result getList10(@PathVariable Integer id, @PathVariable String name) {
        System.out.println(id);//1
        System.out.println(name);
        return Result.success(new String[]{String.valueOf(id), name});
    }
}

日期响应处理

不处理日期时 后端响应给前端的日期个格式为一个数组,如:[2023, 7, 31, 12, 25, 12],需要在后端进行日期格式化后统一响应给前端

方法一:在属性上加入日期格式化注解(不推荐)


@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime date;

方法二 :在WebMvcConfiguration中扩展Spring MVC的消息转换器,统一对日期进行处理

对象转换器

package com.sky.json;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;

/**
 * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
 * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
 * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
 */
public class JacksonObjectMapper extends ObjectMapper {

    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    //public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}

在配置类中使用消息转换器

package com.sky.config;

import java.util.List;

/**
 * 配置类,注册web层相关组件
 */
@RequiredArgsConstructor
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    /**
     * 拓展MVC框架消息转换器
     * @param converters
     */
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("拓展消息转换器...");
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //为消息转换器设置一个对象转换器, 对象转换器可以将java对象序列化为JSON数据
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //将上面的消息转换器对象追加到MVC框架的容器中 索引为0 覆盖默认的消息转换器
        converters.add(0, messageConverter);
    }
}

获取员工数据案列

获取员工数据,返回统一响应结果,在页面渲染展示

  1. 在pom.xml文件中引入dom4j的依赖,用于解析XML文件
  2. 引入资料中提供的解析XML的工具类XMLParserUtils
  3. 引入资料中提供的静态页面文件,放在resources下的static目录下
  4. 编写Controller程序,处理请求,响应数据

引入dom4j的依赖

<!--/pom.xml-->
<dependencies>
    <dependency>
        <groupId>org.dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>2.1.3</version>
    </dependency>
    <dependency>
</dependencies>

引入XMLParserUtils解析工具类

package com.springboot.Utils;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

public class XMLParserUtils {
    public static <T> List<T> parseXml(String fileUrl, Class<T> targetClass) throws Exception {
        //封装解析出来的数据
        ArrayList<T> list = new ArrayList<>();
        //1.获取一个解析器对象
        SAXReader saxReader = new SAXReader();
        //2.利用解析器把xml文件加载到内存中,返回一个Document对象
        Document document = saxReader.read(new File(fileUrl));
        //3.获取根节点
        Element rootElement = document.getRootElement();
        //通过根标签获取user标签
        List<Element> userElements = rootElement.elements("emp");
        //遍历集合获取每一个user标签
        for (Element userElement : userElements) {
            //获取name属性
            String name = userElement.elementText("name");
            //获取age属性
            Integer age = Integer.parseInt(userElement.elementText("age"));
            //获取性别
            String sex = userElement.elementText("sex");
            //获取职业
            String job = userElement.elementText("job");
            //获取地址属性
            Element address = userElement.element("address");
            //获取省市
            String city = address.elementText("city");
            //获取街道
            String street = address.elementText("street");
            //组装数据
            Constructor<T> constructor = targetClass.getConstructor(String.class, Integer.class, String.class, String.class, String.class, String.class);
            T object = constructor.newInstance(name, age, sex, job, city, street);
            list.add(object);
        }
        return list;
    }
}

引入静态文件

<?xml version="1.0" encoding="UTF-8"?>
<emps>
    <emp>
        <name>张三</name>
        <age>18</age>
        <sex>1</sex>
        <job>1</job>
        <address>
            <city>北京</city>
            <street>北京街道</street>
        </address>
    </emp>
    <emp>
        <name>李四</name>
        <age>19</age>
        <sex>2</sex>
        <job>2</job>
        <address>
            <city>上海</city>
            <street>上海街道</street>
        </address>
    </emp>
    <emp>
        <name>王五</name>
        <age>20</age>
        <sex>2</sex>
        <job>3</job>
        <address>
            <city>深圳</city>
            <street>深圳街道</street>
        </address>
    </emp>
</emps>

编写请求

package com.springboot.Controller;

import com.springboot.Pojo.People;
import com.springboot.Pojo.Result;
import com.springboot.Utils.XMLParserUtils;

@RestController
public class HelloController {
    /**
     * 读取xml文件
     */
    @RequestMapping("/getXML")
    public Result getList11() {
        try {
            //获取文件路径
            String fileUrl = Objects.requireNonNull(this.getClass().getClassLoader().getResource("user.xml")).getFile();
            if (fileUrl.isEmpty()) return Result.err("获取文件失败");
            System.out.println(fileUrl);
            List<People> userList = XMLParserUtils.parseXml(fileUrl, People.class);
            return Result.success(userList);
        } catch (Exception e) {
            return Result.err(e.getMessage());
        }

    }
}

分层解耦

三层架构

  • Controller(控制层):接收前端发送的请求,对请求进行处理,并响应数据
  • Service(业务逻辑层):处理具体的业务逻辑
  • dao(数据访问层(Data Access Object)(持久层)):负责数据的访问操作,包括数据的增删查改

Controller层 前端交互,接收前端请求参数,返回数据

package com.springboot.Controller;

public class HelloController {
    /**
     * 读取xml文件
     */
    @RequestMapping("/getXML")
    public Result getList11() {
        try {
            //获取文件路径
            PeopleServerA peopleServerA = new PeopleServerA();
            List<People> peopleList = peopleServerA.peopleList();
            return Result.success(peopleList);
        } catch (Exception e) {
            return Result.err(e.getMessage());
        }
    }
}

server层 处理业务逻辑

package com.springboot.Server.Imp;

import com.springboot.Dao.Impl.PeopleDaoA;
import com.springboot.Dao.PeopleDao;
import com.springboot.Pojo.People;
import com.springboot.Server.PeopleServer;

import java.util.List;

public class PeopleServerA implements PeopleServer {
    private final PeopleDao peopleDao = new PeopleDaoA();

    @Override
    public List<People> peopleList() throws Exception {
        List<People> list = peopleDao.listPeople();
        for (People people : list) {
            //设置性别
            //1男  2女
            if ("1".equals(people.getSex())) people.setSex("男");
            else if ("2".equals(people.getSex())) people.setSex("女");
            if ("1".equals(people.getJob())) people.setJob("学生");
            else if ("2".equals(people.getJob())) people.setJob("老师");
            else if ("3".equals(people.getJob())) people.setJob("程序员");
        }
        return list;
    }
}

dao层 读取数据

package com.springboot.Dao.Impl;

import com.springboot.Dao.PeopleDao;
import com.springboot.Pojo.People;
import com.springboot.Utils.XMLParserUtils;

import java.util.List;
import java.util.Objects;

public class PeopleDaoA implements PeopleDao {
    @Override
    public List<People> listPeople() throws Exception {
        String fileUrl = Objects.requireNonNull(this.getClass().getClassLoader().getResource("user.xml")).getFile();
        if (fileUrl.isEmpty()) throw new Exception("文件加载失败");
        System.out.println(fileUrl);
        return XMLParserUtils.parseXml(fileUrl, People.class);
    }
}

分层解耦

  • 内聚:软件中各个功能模块内部的功能联系。
  • 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
  • 软件设计原则:高内聚低耦合

spring中具有依赖注入和控制反转的概念

  • 控制反转:Inversion Of Control,简称**I0C**。对象的创建控制由程序自身转移到外部(容器),这种思想称为控制反转。
  • 依赖注入: Dependency Injection,简称**Dl**。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。
  • Bean对象:I0C容器中创建、管理的对象,称之为**bean**

IOC控制反转

  • @Component注解(控制反转) 用在类上,该类一但使用了@Component注解,就代表将当前类交给IOC容器进行管理,成为IOC 容器中的bean
  • @Autowired注解(依赖注入) 用在属性上,在运行时,Ioc容器会提供该类型的bean对象,并赋值给该变量

@Component注解与其他注解的区别

@Component:通用的组件注解,适用于任何 Spring 管理的类。

@Service:用于标识服务层的类,强调业务逻辑。

@Repository:用于标识数据访问层(DAO)的类,通常与数据库操作相关。

@Controller:用于标识控制器层,处理 HTTP 请求。

注意

在三层架构中推荐使用@Service@Repository@Controller代替@Component

在一些工具类中,@Component注解可以作为通用的组件注解使用。

在控制器中通常使用@RestController注解,它相当于@Controller@ResponseBody 的组合。因此我们在控制器层中无需加入@Controller注解

  • 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写。一般不指定
  • 使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller
package com.springboot.Controller;

public class HelloController {
    /**
     * 读取xml文件
     */
    @Autowired
    private PeopleServer peopleServerA;

    @RequestMapping("/getXML")
    public Result getList11() {
    ....
    }
}

package com.springboot.Server.Imp;

@Service
public class PeopleServerA implements PeopleServer {
    @Autowired
    private PeopleDao peopleDao;
  ...
}

package com.springboot.Dao.Impl;

@Repository(value = "daoA")//类重命名
public class PeopleDaoA implements PeopleDao {
  ...
}

bean组件扫描

  • 前面声明bean的四大注解,要想生效,还需要被件扫描注解@Componentscan扫描
  • @Componentscan注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解 @SpringBootApplication中,默认扫描的范围是* *启动类所在包及其子包**。

其他位置需在启动类中手动配置需要扫描的包 使用@Componentscan注解


@ComponentScan({"com.springboot", "dao"})
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

DI依赖注入

@@Autowired 依赖注入

  • Spring框架提供的注解

  • 默认按类型装配

  • 只支持一个属性 required:指定是否必须装配,默认为true 否则可以允许装配null

  • @Autowired装配机制:

  1. 默认按类型装配:Spring会查找与字段类型匹配的bean
  2. 如果找到多个相同类型的bean,会根据字段名与bean名称匹配
  3. 可以配合@Qualifier注解指定具体的bean名

注意

@Autowired注解是根据变量类型进行注入的,如果变量类型不匹配,则注入失败。如果容器中具有多个相同类型的bean ,则会直接报required a single bean, but 2 were found:错误。

解决方法

使用@Autowired+@Qualifier注解指定注入的bean的名字。

package com.springboot.Controller;

public class HelloController {
    @Autowired
    @Qualifier("daoA")//默认注入名字为daoA的bean
    private PeopleServer peopleServerA;
}

使用@Primary注解指定默认的bean,当有多个相同类型的bean时,默认注入该注解的bean

package com.springboot.Server.Imp;

@Primary //无论具有多个相同类型的bean,都注入该bean
@Service
public class PeopleServerA implements PeopleServer {
    @Autowired
    private PeopleDao peopleDao;
  ...
}

使用@Resource注解,根据bean的名字进行注入。

package com.springboot.Controller;

public class HelloController {
    @Resource(name = "daoA")//默认注入名字为daoA的bean
    private PeopleServer peopleServerA;
}

SpringBoot 推荐使用的依赖注入方式

  • SpringBoot中,不推荐使用@Autowired注解
  • 推荐使用构造函数在创建bean时注入依赖

@Service
public class DeptServerImp() {
    private PeopleDao peopleDao;

    //使用构造函数的方式注入依赖
    public DeptServerImp(PeopleDao peopleDao) {
        this.peopleDao = peopleDao;
    }
}

使用构造函数的方式写法相对繁琐 我们可以在需要注入的Bean前使用final关键字修饰 从而使用@RequiredArgsConstructor 注解自动将带有final关键字的变量自动创建构造函数

  • 功能作用
  • 自动生成一个包含所有 final 字段 标记为 @NonNull 字段的构造方法*。

注意

  1. 字段需明确标记: 只有 final 或 @NonNull 字段会被包含在构造方法中。
  2. 与显式构造方法冲突:如果类中已存在构造方法,Lombok 不会生成。
  3. IDE 支持:需安装 Lombok 插件(如 IntelliJ 的 Lombok Plugin),否则 IDE 可能报错(实际编译可通过)。

@Service
@RequiredArgsConstructor
public class DeptService {
    private final DeptRepository repository; // 自动通过构造方法注入
}

SpringBoot 为什么不建议使用@Autowired进行字段注入

  1. 破坏不变性:字段注入无法使用final修饰符
  2. 不利于单元测试:测试时需依赖Spring容器,字段注入的类在测试中必须通过Spring容器初始化(如@SpringBootTest ),否则依赖为null
  3. 容器耦合性:字段注入的类必须由Spring容器管理(反射实现注入)。脱离容器时(如手动new对象),依赖为null,破坏POJO的独立性。

使用Sl4j记录日志

//日志注解
@Slf4j
@RestController
public class DeptController {
    //此种方式太过繁琐 slf4j 提供了@Slf4j注解用以简化此行代码的编写
//    private static Logger log = (Logger) LoggerFactory.getLogger(DeptController.class);
    @GetMapping("/depts")
    public Result getDeps() {
        log.info("查询全部部门数据");
        return Result.success("null");
    }
}

@RequestMapping的衍生注释

在不使用衍生注释之前,@RequestMapping的请求类型需要写成@RequestMapping(value = "/depts", method = RequestMethod.GET) ,使用衍生注释之后,可以简化为@GetMapping("/depts")

public class DeptController {
    // @GetMapping("/depts")
// @PostMapping("/depts")
// @PutMapping("/depts")
// @DeleteMapping("/depts")
// @PatchMapping("/depts")
    @GetMapping("/depts")
    public Result getDeps() {
        log.info("查询全部部门数据");
        return Result.success("null");
    }
}

配置公共的请求路径

一个完整的请求路径,应该是类上的 @RequestMappingvalue属性+方法上的 @RequestMappingvalue属性


@RestController
//配置跨域注解
@CrossOrigin
//配置公共请求路径 @RequestMapping("/depts")
@RequestMapping("/depts")
public class DeptController {
    @Autowired
    private DeptServer DeptServer;

    @GetMapping
    public Result getDeps() {
        log.info("查询全部部门数据");

        //调用Server层查询部门数据
        List<Dept> list = DeptServer.list();
        return Result.success(list);
    }
}

前端请求默认值

Controller中,使用@RequestParam注解,可以设置前端请求的默认值。

public class EmpController {
    //    员工查询接口(分页)
    @Autowired
    private EmpServer empServer;

    @GetMapping
    public Result emp(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {
        log.info("查询员工数据{}{}", pageNum, pageSize);
        PageBean<Emp> empByPage = empServer.findEmpByPage(pageNum, pageSize);
        return Result.success(empByPage);
    }

}

分页插件PageHelper的使用

分页查询原始


@Service
public class EmpServerImp implements EmpServer {
    @Override
    public PageBean<Emp> findEmpByPage(Integer pageNum, Integer pageSize) {
        //获取员工信息总记录条数
        Long total = empMapper.countEmp();
        //获取起始索引
        Integer start = (pageNum - 1) * pageSize;
        //获取分页查询结果
        List<Emp> list = empMapper.findEmpByPage(start, pageSize);
        //将结果封装到pagesBean中
        PageBean<Emp> pageBean = new PageBean<>(list, pageNum, pageSize, total);
        return pageBean;
    }
}

导入依赖坐标

<!--pom.xml-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.6</version>
</dependency>

使用

只需要将查询全部的结果传递给doSelectPage方法即可。


@Service
public class EmpServerImp implements EmpServer {
    @Autowired
    private EmpMapper empMapper;

    @Override
    public PageBean<Emp> findEmpByPageUsePageHelper(Integer pageNum, Integer pageSize) {
        //将查询结果放入PageInfo对象中进行封装
        Page<Emp> pageInfo = PageHelper.startPage(pageNum, pageSize).doSelectPage(() -> empMapper.findAllEmp());
        //将封装完毕的数据放入PageBean对象中
        PageBean<Emp> pageBean = new PageBean(pageInfo.getResult(), pageNum, pageSize, pageInfo.getTotal());
        return pageBean;
    }
}
上次更新 2025/9/9 20:40:32