SpringBoot工程
Spring Boot 下的 Spring MVC(注解)
springboot下的springMVC主要有以下注解:
(1)@Controller:Spring MVC 的注解,处理 http 请求
(2)@RestController :@Controller 与@ResponseBody 的组合注解
如果一个 Controller 类添加了@RestController,那么该 Controller 类下的所有方法都相当
于添加了@ResponseBody 注解 ,用于返回字符串或json数据。
创建 MyRestController 类,演示@RestController 替代@Controller + @ResponseBody
@RestController
public class MyRestController {
@Autowired
private StudentService studentService;
@RequestMapping("/boot/stu")
public Object stu(){
return studentService.getStudentById(1);
}
}
(3)@RequestMapping:支持 Get 请求,也支持 Post 请求 。
(4)@GetMapping :只支持 Get 请求,主要用于查询操作。
(5)@PostMapping:只支持Post请求,主要用于新增数据。
(6)@PutMapping:只支持put请求,主要用于修改数据
(7)@DeleteMapping:只支持delete请求,通常用与删除数据
(8)综合案例:
(A)创建一个 MVCController,里面使用上面介绍的各种注解接收不同的请求
//RestController 注解相当于加了给方法加了@ResponseBody 注解,所以是不能跳转页面的,只能返回字符串或者 json 数据
@RestController
public class MVCController {
@GetMapping(value = "/query")
public String get() {
return "@GetMapping 注解,通常查询时使用";
}
@PostMapping(value = "/add")
public String add() {
return "@PostMapping 注解,通常新增时使用";
}
@PutMapping(value = "/modify")
public String modify() {
return "@PutMapping 注解,通常更新数据时使用";
}
@DeleteMapping(value = "/remove")
public String remove() {
return "@DeleteMapping 注解,通常删除数据时使用";
}
}
(B)启动应用,在浏览器中输入不同的请求进行测试
-
@GetMapping
:用于处理HTTP GET请求,是@RequestMapping
的一个特化,只处理GET请求。 -
@PostMapping
:用于处理HTTP POST请求,是@RequestMapping
的一个特化,只处理POST请求。 -
@PutMapping
:用于处理HTTP PUT请求,是@RequestMapping
的一个特化,只处理PUT请求。 -
@DeleteMapping
:用于处理HTTP DELETE请求,是@RequestMapping
的一个特化,只处理DELETE请求。 -
@PatchMapping
:用于处理HTTP PATCH请求,是@RequestMapping
的一个特化,只处理PATCH请求。 -
@RequestBody
:用于指定一个方法参数应该绑定到Web请求的body上。 -
@ResponseBody
:表示该方法的返回值应该直接作为HTTP响应的body返回。 -
@RequestParam
:用于将Web请求参数区绑定到控制器方法的参数上。 -
@PathVariable
:用于将URL中的占位符参数绑定到控制器方法的参数上。 -
@RequestHeader
:用于将Web请求的header绑定到控制器方法的参数上。 -
@CookieValue
:用于将Web请求的cookie绑定到控制器方法的参数上。 -
@RestController
:组合了@Controller
和@ResponseBody
,用于定义REST风格的Web服务。 -
@Controller
:用于定义一个控制器类,其方法可以处理Web请求。 -
@RequestMapping
:用于将HTTP请求映射到控制器的处理方法上,可以指定请求类型、路径等。 -
@CrossOrigin
:用于跨源资源共享(CORS)的配置。
1.@GetMapping
java
@GetMapping("/users")
public List<User> getAllUsers() {
return userDAO.findAll();
}
这个例子中,@GetMapping
注解将HTTP GET请求映射到/users
路径上,当访问这个路径时,会调用getAllUsers
方法。
2.@PostMapping
java
@PostMapping("/users")
public User createUser(@RequestBody User user) {
userDAO.save(user);
return user;
}
这个例子中,@PostMapping
注解将HTTP POST请求映射到/users
路径上,并且使用@RequestBody
注解将请求体中的JSON数据绑定到User
对象上。
@PutMapping
java
@PutMapping("/users/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
userDAO.save(user);
return user;
}
这个例子中,@PutMapping
注解将HTTP PUT请求映射到/users/{id}
路径上,其中{id}
是一个路径变量,使用@PathVariable
注解将其绑定到方法参数上。
@DeleteMapping
java
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
userDAO.deleteById(id);
}
这个例子中,@DeleteMapping
注解将HTTP DELETE请求映射到/users/{id}
路径上,使用@PathVariable
注解将路径变量{id}
绑定到方法参数上。
@PatchMapping
java
@PatchMapping("/users/{id}")
public User updateUserPartial(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
userDAO.save(user);
return user;
}
这个例子中,@PatchMapping
注解将HTTP PATCH请求映射到/users/{id}
路径上,用于部分更新资源。
@RequestBody
java
@PostMapping("/messages")
public Message createMessage(@RequestBody Message message) {
messageRepository.save(message);
return message;
}
这个例子中,@RequestBody
注解用于将请求体中的JSON数据绑定到Message
对象上。
@ResponseBody
java
@Controller
public class MyController {
@ResponseBody
@GetMapping("/greeting")
public String sayHello() {
return "Hello, World!";
}
}
这个例子中,@ResponseBody
注解用于将方法的返回值直接作为HTTP响应的body返回。
@RequestParam
java
@GetMapping("/search")
public String search(@RequestParam String query) {
// 使用query参数进行搜索
return "Search Results";
}
这个例子中,@RequestParam
注解用于将请求参数query
绑定到方法参数上。
@PathVariable
java
@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
return userRepository.findById(id);
}
这个例子中,@PathVariable
注解用于将URL中的{id}
占位符参数绑定到方法参数上。
@RequestHeader
java
@GetMapping("/header")
public String getHeader(@RequestHeader String header) {
return header;
}
这个例子中,@RequestHeader
注解用于将请求的header绑定到方法参数上。
@CookieValue
java
@GetMapping("/cookie")
public String getCookie(@CookieValue String cookieName) {
return cookieName;
}
这个例子中,@CookieValue
注解用于将请求的cookie绑定到方法参数上。
@RestController
java
@RestController
public class UserController {
@GetMapping("/users")
public List<User> getAllUsers() {
return userDAO.findAll();
}
}
这个例子中,@RestController
注解组合了@Controller
和@ResponseBody
,使得所有方法的返回值都自动作为HTTP响应的body返回。
@Controller
java
@Controller
public class MyController {
@GetMapping("/greeting")
public String sayHello(Model model) {
model.addAttribute("message", "Hello, World!");
return "greeting";
}
}
这个例子中,@Controller
注解定义了一个控制器类,其方法可以返回视图名称,而不是直接返回响应体。
@RequestMapping
java
@RequestMapping(value = "/users", method = RequestMethod.GET)
public List<User> getAllUsers() {
return userDAO.findAll();
}
这个例子中,@RequestMapping
注解用于映射HTTP GET请求到/users
路径上。
@CrossOrigin
java
@CrossOrigin
@GetMapping("/users")
public List<User> getAllUsers() {
return userDAO.findAll();
}
这个例子中,@CrossOrigin
注解用于允许跨域请求访问该方法。
注释
-
@GetMapping
:用于处理HTTP GET请求,是@RequestMapping
的一个特化,只处理GET请求。 -
@PostMapping
:用于处理HTTP POST请求,是@RequestMapping
的一个特化,只处理POST请求。 -
@PutMapping
:用于处理HTTP PUT请求,是@RequestMapping
的一个特化,只处理PUT请求。 -
@DeleteMapping
:用于处理HTTP DELETE请求,是@RequestMapping
的一个特化,只处理DELETE请求。
@RestController
是 Spring Framework 5 中引入的一个新的注解,它是 @Controller
和 @ResponseBody
注解的组合。@RestController
注解表明该类是一个控制器,并且其方法的返回值会自动作为HTTP响应的正文返回,这使得它非常适合用于构建RESTful Web服务。
使用
@Controller
public class MyController {
// 映射到 /users 路径上的 GET 请求
@RequestMapping(value = "/users", method = RequestMethod.GET)
public String listUsers() {
return "users";
}
// 映射到 /users/{id} 路径上的 GET 请求,其中 {id} 是一个路径变量
@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
public String getUser(@PathVariable("id") Long id) {
return "user";
}
// 映射到 /admin 路径上的 POST 请求,并且只接受 Content-Type 为 application/json 的请求体
@RequestMapping(value = "/admin", method = RequestMethod.POST, consumes = "application/json")
public String createAdmin(@RequestBody Admin admin) {
return "admin";
}
// 映射到 /api 路径上的请求,响应类型为 application/json
@RequestMapping(value = "/api", produces = "application/json")
public ResponseEntity<MyObject> getApi() {
return ResponseEntity.ok(new MyObject());
}
// 映射到 /search 路径上的 GET 请求,只有当请求参数包含 q 时才处理
@RequestMapping(value = "/search", params = "q")
public String search(@RequestParam("q") String query) {
return "search";
}
// 映射到 /download 路径上的 GET 请求,只有当请求头包含 X-Request-Id 时才处理
@RequestMapping(value = "/download", headers = "X-Request-Id")
public String download() {
return "download";
}
}
@RequestMapping("/simpleParam")
public String simpleParam(@RequestParam(name = "name", required = false) String username, Integer age){
System.out.println(username+ ":" + age);
return "OK";
}
@RequestParam(name = "name", required = false) String username:这个参数使用了 @RequestParam 注解来指定从请求中获取名为 name 的参数,并且设置 required 属性为 false,表示这个参数是可选的。如果请求中包含了 name 参数,它的值将被赋给 username 变量;如果请求中没有 name 参数,username 将默认为 null。
Integer age:这个参数没有使用 @RequestParam 注解标注,因此 Spring 会尝试从请求参数中获取名为 age 的参数,并将其转换为 Integer 类型。如果请求中没有提供 age 参数,将会出现一个问题,因为 Integer 是一个必须的参数,没有默认值,这将导致方法调用失败,并返回错误响应。
@RestController
public class RequestController {
//数组集合参数
@RequestMapping("/listParam")
//默认情况下,请求中参数名相同的多个值,是封装到数组。如果要封装到集合,要使用@RequestParam绑定参数关系
public String listParam(@RequestParam List<String> hobby){
System.out.println(hobby);
return "OK";
}
}
日期参数
@RestController
public class RequestController {
//日期时间参数
@RequestMapping("/dateParam")
public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime){
System.out.println(updateTime);
return "OK";
}
}
JSON参数
@RequestBody注解:将JSON数据映射到形参的实体类对象中(JSON中的key和实体类中的属性名保持一致)
@RestController
public class RequestController {
//JSON参数
@RequestMapping("/jsonParam")
public String jsonParam(@RequestBody User user){
System.out.println(user);
return "OK";
}
}
响应
下面我们来测试下响应数据:
@RestController
public class ResponseController {
//响应字符串
@RequestMapping("/hello")
public String hello(){
System.out.println("Hello World ~");
return "Hello World ~";
}
//响应实体对象
@RequestMapping("/getAddr")
public Address getAddr(){
Address addr = new Address();//创建实体类对象
addr.setProvince("广东");
addr.setCity("深圳");
return addr;
}
//响应集合数据
@RequestMapping("/listAddr")
public List<Address> listAddr(){
List<Address> list = new ArrayList<>();//集合对象
Address addr = new Address();
addr.setProvince("广东");
addr.setCity("深圳");
Address addr2 = new Address();
addr2.setProvince("陕西");
addr2.setCity("西安");
list.add(addr);
list.add(addr2);
return list;
}
}
在服务端响应了一个对象或者集合,那私前端获取到的数据是什么样子的呢?我们使用postman发送请求来测试下。测试效果如下:
3. 分层解耦
三层架构
单一职责原则:一个类或一个方法,就只做一件事情,只管一块功能。
这样就可以让类、接口、方法的复杂度更低,可读性更强,扩展性更好,也更利用后期的维护。
**控制层:**接收前端发送的请求,对请求进行处理,并响应数据
@RestController
public class EmpController {
//业务层对象
private EmpService empService = new EmpServiceA();
@RequestMapping("/listEmp")
public Result list(){
//1. 调用service层, 获取数据
List<Emp> empList = empService.listEmp();
//3. 响应数据
return Result.success(empList);
}
}
**业务逻辑层:**处理具体的业务逻辑
- 业务接口
//业务逻辑接口(制定业务标准)
public interface EmpService {
//获取员工列表
public List<Emp> listEmp();
}
- 业务实现类
//业务逻辑实现类(按照业务标准实现)
public class EmpServiceA implements EmpService {
//dao层对象
private EmpDao empDao = new EmpDaoA();
@Override
public List<Emp> listEmp() {
//1. 调用dao, 获取数据
List<Emp> empList = empDao.listEmp();
//2. 对数据进行转换处理 - gender, job
empList.stream().forEach(emp -> {
//处理 gender 1: 男, 2: 女
String gender = emp.getGender();
if("1".equals(gender)){
emp.setGender("男");
}else if("2".equals(gender)){
emp.setGender("女");
}
//处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
String job = emp.getJob();
if("1".equals(job)){
emp.setJob("讲师");
}else if("2".equals(job)){
emp.setJob("班主任");
}else if("3".equals(job)){
emp.setJob("就业指导");
}
});
return empList;
}
}
**数据访问层:**负责数据的访问操作,包含数据的增、删、改、查
- 数据访问接口
//数据访问层接口(制定标准)
public interface EmpDao {
//获取员工列表数据
public List<Emp> listEmp();
}
- 数据访问实现类
//数据访问实现类
public class EmpDaoA implements EmpDao {
@Override
public List<Emp> listEmp() {
//1. 加载并解析emp.xml
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
System.out.println(file);
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
return empList;
}
}
三层架构的好处:
- 复用性强
- 便于维护
- 利用扩展
//Controller层:
@RestController
public class EmpController {
@Autowired //运行时,从IOC容器中获取该类型对象,赋值给该变量
private EmpService empService ; //第一个是接口 定义出来这样一个类似于结构体
@RequestMapping("/listEmp")
public Result list(){
//1. 调用service, 获取数据
List<Emp> empList = empService.listEmp();
//3. 响应数据
return Result.success(empList);
}
}
//Service层:
@Component //将当前对象交给IOC容器管理,成为IOC容器的bean
public class EmpServiceA implements EmpService {
@Autowired //运行时,从IOC容器中获取该类型对象,赋值给该变量
private EmpDao empDao ; //第一个是接口
@Override
public List<Emp> listEmp() {
//1. 调用dao, 获取数据
List<Emp> empList = empDao.listEmp();
//2. 对数据进行转换处理 - gender, job
empList.stream().forEach(emp -> {
//处理 gender 1: 男, 2: 女
String gender = emp.getGender();
if("1".equals(gender)){
emp.setGender("男");
}else if("2".equals(gender)){
emp.setGender("女");
}
//处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
String job = emp.getJob();
if("1".equals(job)){
emp.setJob("讲师");
}else if("2".equals(job)){
emp.setJob("班主任");
}else if("3".equals(job)){
emp.setJob("就业指导");
}
});
return empList;
}
}
//Dao层:
@Component //将当前对象交给IOC容器管理,成为IOC容器的bean
public class EmpDaoA implements EmpDao { //重写EmpDao
@Override
public List<Emp> listEmp() {
//1. 加载并解析emp.xml
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
System.out.println(file);
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
return empList;
}
}
项目实战
- application.properties (直接把之前项目中的复制过来)
#数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/tlias
spring.datasource.username=root
spring.datasource.password=1234
#开启mybatis的日志输出
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启数据库表字段 到 实体类属性的驼峰映射
mybatis.configuration.map-underscore-to-camel-case=true
- 实体类
/*部门类*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
private Integer id;
private String name;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
/*员工类*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
private Integer id;
private String username;
private String password;
private String name;
private Short gender;
private String image;
private Short job;
private LocalDate entrydate;
private Integer deptId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
第4步:准备对应的Mapper、Service(接口、实现类)、Controller基础结构
数据访问层:
- DeptMapper
package com.itheima.mapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DeptMapper {
}
- EmpMapper
package com.itheima.mapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EmpMapper {
}
业务层:
- DeptService
package com.itheima.service;
//部门业务规则
public interface DeptService {
}
- DeptServiceImpl
package com.itheima.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
//部门业务实现类
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
}
- EmpService
package com.itheima.service;
//员工业务规则
public interface EmpService {
}
- EmpServiceImpl
package com.itheima.service.impl;
import com.itheima.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
//员工业务实现类
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {
}
控制层:
- DeptController
package com.itheima.controller;
import org.springframework.web.bind.annotation.RestController;
//部门管理控制器
@RestController
public class DeptController {
}
- EmpController
package com.itheima.controller;
import org.springframework.web.bind.annotation.RestController;
//员工管理控制器
@RestController
public class EmpController {
}
项目工程结构:
查询回显
3.1.3 代码实现
- EmpMapper
@Mapper
public interface EmpMapper {
//根据ID查询员工信息
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time " +
"from emp " +
"where id = #{id}")
public Emp findById(Integer id);
//省略...
}
- EmpService
public interface EmpService {
/**
* 根据ID查询员工
* @param id
* @return
*/
public Emp getById(Integer id);
//省略...
}
- EmpServiceImpl
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Override
public Emp getById(Integer id) {
return empMapper.findById(id);
}
//省略...
}
- EmpController
@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {
@Autowired
private EmpService empService;
//根据id查询
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id){
Emp emp = empService.getById(id);
return Result.success(emp);
}
//省略...
}