请求响应
请求响应
请求响应类
- 请求(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);
}
}
获取员工数据案列
获取员工数据,返回统一响应结果,在页面渲染展示
- 在pom.xml文件中引入dom4j的依赖,用于解析XML文件
- 引入资料中提供的解析XML的工具类XMLParserUtils
- 引入资料中提供的静态页面文件,放在resources下的static目录下
- 编写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装配机制:
- 默认按类型装配:
Spring会查找与字段类型匹配的bean - 如果找到多个相同类型的
bean,会根据字段名与bean名称匹配 - 可以配合
@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字段的构造方法*。
注意
- 字段需明确标记: 只有 final 或 @NonNull 字段会被包含在构造方法中。
- 与显式构造方法冲突:如果类中已存在构造方法,Lombok 不会生成。
- IDE 支持:需安装 Lombok 插件(如 IntelliJ 的 Lombok Plugin),否则 IDE 可能报错(实际编译可通过)。
@Service
@RequiredArgsConstructor
public class DeptService {
private final DeptRepository repository; // 自动通过构造方法注入
}
SpringBoot 为什么不建议使用@Autowired进行字段注入
- 破坏不变性:字段注入无法使用
final修饰符 - 不利于单元测试:测试时需依赖
Spring容器,字段注入的类在测试中必须通过Spring容器初始化(如@SpringBootTest),否则依赖为null - 容器耦合性:字段注入的类必须由
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");
}
}
配置公共的请求路径
一个完整的请求路径,应该是类上的 @RequestMapping 的value属性+方法上的 @RequestMapping的value属性
@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;
}
}