请求响应和分层解耦(四)
请求
简单参数
- 原始方式获取请求参数
- SpringBoot中接收简单参数
- @RequestParam注解
原始方式
Controller方法形参中声明HttpServletRequest对象,调用对象的getParameter(参数名)
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| //项目内位置src/main/java/com.ljsblog/controller/RequestController.java package com.ljsblog.controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController public class RequestController { @RequestMapping("/test") public String test(HttpServletRequest request){ String name=request.getParameter("name"); String pass=request.getParameter("pass"); System.out.println(name+":"+pass); return "ok"; } }
|
Springboot方式
请求参数名与方法形参变量名相同,会自动进行类型转换。
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| //项目内位置src/main/java/com.ljsblog/controller/RequestController.java package com.ljsblog.controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController public class RequestController { @RequestMapping("/test") public String test(String name,Integer pass){ System.out.println(name+":"+pass); return "ok"; } }
|
@RequestParam注解
方法形参名称与请求参数名称不匹配,通过该注解完成映射,该注解的require属性值默认是true,代表请求参数必须传递。
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.ljsblog.controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController public class RequestController { //postman里设置的参数名为username,password @RequestMapping("/test") public String test(@RequestParam(name = "username") String name, @RequestParam(name="password") Integer pass){ System.out.println(name+":"+pass); return "ok"; } }
|
实体参数
简单实体对象
简单实体对象:请求参数名与形参对象属性名相同,定义POJO接收即可。
范例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| //User.java package com.ljsblog.pojo;
public class User { private String name; private Integer age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } } //RequestController.java package com.ljsblog.controller;
import com.ljsblog.pojo.User; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
@RestController public class RequestController { @RequestMapping("/pojotest") public String test(User user){ System.out.println(user); return "ok"; } } //postman里的数据为 //name //age
|
复杂实体对象
复杂实体对象:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数。
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| //User.java package com.ljsblog.pojo;
public class User { private String name; private Integer age; private Address address;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
@Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", address=" + address + '}'; } } //Address.java package com.ljsblog.pojo;
public class Address { private String province; private String city;
public String getProvince() { return province; }
public void setProvince(String province) { this.province = province; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
@Override public String toString() { return "Address{" + "province='" + province + '\'' + ", city='" + city + '\'' + '}'; } } //RequestController.java package com.ljsblog.controller;
import com.ljsblog.pojo.User; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
@RestController public class RequestController { @RequestMapping("/pojotest") public String test(User user){ System.out.println(user); return "ok"; } } //postman里的数据为 //name //age //address.province //address.city
|
数组参数
数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参可接收参数。
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.ljsblog.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList; import java.util.Arrays;
@RestController public class RequestController { @RequestMapping("/arrTest") public String arrTest(String[] arr){ System.out.println(Arrays.toString(arr)); return "ok"; } } //postman参数 //arr //arr //arr
|
集合参数
集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam绑定参数关系,若不用该注解,数据默认封装到数组。
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.ljsblog.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList; import java.util.Arrays;
@RestController public class RequestController { @RequestMapping("/listTest") public String listTest(@RequestParam ArrayList<String> list){ System.out.println(list); return "ok"; } } //postman参数 //list //list //list
|
日期参数
使用@DateTimeFormat注解完成日期参数格式转换。
范例:
1 2 3 4 5 6 7
| @RequestMapping("/datetimeTest") public String dateTimeTest(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")LocalDateTime dateTime){ System.out.println(dateTime); return "ok"; } //postman参数 //dateTime 2019-11-30 12:06:54
|
JSON参数
JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数,需使用@RequestBody标识。
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @RequestMapping("/jsonTest") public String jsonTest(@RequestBody User user){ System.out.println(user); return "ok"; } //postman参数 //选择post方式,因为Json存放在存储体中 //数据类型选择postman /* { "name":"zhangsan", "age":18, "address":{ "province":"河北", "city":"廊坊" } } */
|
路径参数
通过请求URL直接传递参数,使用{…}来标识该路径参数,需使用@PathVariable获取路径参数。
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @RequestMapping("/pathTest/{id}") public String pathTest(@PathVariable Integer id){ System.out.println(id); return "ok"; } @RequestMapping("/pathTest/{id}/{name}") public String pathTest(@PathVariable Integer id,@PathVariable String name){ System.out.println(id+":"+name); return "ok"; } //postman的url //单http://localhost:8080/pathTest/5 //多http://localhost:8080/pathTest/3/zhangsan
|
响应
@Responsebody
类型:方法注解,类注解
位置:Controller方法/类上
作用:将方法返回值直接响应,若返回值类型是实体对象/集合,将会转换成JSON格式响应。
说明:@RestController=@Controller+@ResponseBody
统一响应结果
Result(code,msg,data)
分层耦合
三层架构
- controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据
- service:业务逻辑层,处理具体的业务逻辑
- dao:数据访问层(Data Access Object)(持久层),负责数据的访问操作,包括数据的增删改查
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| //controller //EmpController package com.ljsblog.controller; import com.ljsblog.pojo.Emp; import com.ljsblog.pojo.Result; import com.ljsblog.service.EmpService; import com.ljsblog.service.impl.EmpServiceA; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class EmpController { private EmpService empService=new EmpServiceA(); @RequestMapping("/listEmp") public Result list(){ List<Emp> empList=empService.empList(); return Result.success(empList); } }
//service package com.ljsblog.service.impl; import com.ljsblog.dao.EmpDao; import com.ljsblog.dao.impl.EmpDaoA; import com.ljsblog.pojo.Emp; import com.ljsblog.service.EmpService; import java.util.List; public class EmpServiceA implements EmpService { private EmpDao empDao=new EmpDaoA(); @Override public List<Emp> empList() { List<Emp> empList=empDao.listEmp(); empList.stream().forEach(emp -> { String gender=emp.getGender(); if(gender.equals("1")){ emp.setGender("男"); }else { emp.setGender("女"); } String job=emp.getJob(); if(job.equals("1")){ emp.setJob("讲师"); }else if(job.equals("2")){ emp.setJob("班主任"); } else { emp.setJob("就业指导"); } }); return empList; } } package com.ljsblog.service; import com.ljsblog.pojo.Emp; import java.util.List; public interface EmpService { public List<Emp> empList(); }
//dao package com.ljsblog.dao.impl; import com.ljsblog.dao.EmpDao; import com.ljsblog.pojo.Emp; import com.ljsblog.utils.XmlParserUtils;
import java.util.List; public class EmpDaoA implements EmpDao { @Override public List<Emp> listEmp() { String file=this.getClass().getClassLoader().getResource("emp.xml").getFile(); System.out.println(file); List<Emp> empList= XmlParserUtils.parse(file,Emp.class); return empList; } } package com.ljsblog.dao; import com.ljsblog.pojo.Emp; import java.util.List; public interface EmpDao { public List<Emp> listEmp(); }
|
分层解耦
内聚:软件各个功能模块内部的功能联系。
耦合:衡量软件中各个层/模块之间的依赖,关联的程度。
软件设计原则:高内聚低耦合。
控制反转:Inversion Of Control,简称IOC,对象的创建控制权由程序自身转移到外部(容器),这种思想成为控制反转。
依赖注入:Dependency Injection,简称DI,容器为应用程序提供运行时所依赖的资源,称之为依赖注入。
Bean对象:IOC容器中创建,管理的对象,称之为bean。
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| //controller package com.ljsblog.controller; import com.ljsblog.pojo.Emp; import com.ljsblog.pojo.Result; import com.ljsblog.service.EmpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class EmpController { @Autowired private EmpService empService; @RequestMapping("/listEmp") public Result list(){ List<Emp> empList=empService.empList(); return Result.success(empList); } }
//dao package com.ljsblog.dao.impl; import com.ljsblog.dao.EmpDao; import com.ljsblog.pojo.Emp; import com.ljsblog.utils.XmlParserUtils; import org.springframework.stereotype.Component;
import java.util.List; @Component public class EmpDaoA implements EmpDao { @Override public List<Emp> listEmp() { String file=this.getClass().getClassLoader().getResource("emp.xml").getFile(); System.out.println(file); List<Emp> empList= XmlParserUtils.parse(file,Emp.class); return empList; } }
package com.ljsblog.dao; import com.ljsblog.pojo.Emp; import java.util.List; public interface EmpDao { public List<Emp> listEmp(); }
//service package com.ljsblog.service.impl; import com.ljsblog.dao.EmpDao; import com.ljsblog.pojo.Emp; import com.ljsblog.service.EmpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;
import java.util.List; @Component public class EmpServiceA implements EmpService { @Autowired//依赖注入 private EmpDao empDao; @Override public List<Emp> empList() { List<Emp> empList=empDao.listEmp(); empList.stream().forEach(emp -> { String gender=emp.getGender(); if(gender.equals("1")){ emp.setGender("男"); }else { emp.setGender("女"); } String job=emp.getJob(); if(job.equals("1")){ emp.setJob("讲师"); }else if(job.equals("2")){ emp.setJob("班主任"); } else { emp.setJob("就业指导"); } }); return empList; } } package com.ljsblog.service; import com.ljsblog.pojo.Emp; import java.util.List; public interface EmpService { public List<Emp> empList(); }
|
IOC
Bean的声明:若要将某个对象交给IOC容器管理,需在对应的类上加上如下注解之一:
- @Component:声明bean的基础注解,不属于以下三类时,用此注解
- @Controller:@Component的衍生注解,标注在控制器类上,(@RestController包括@Controller)
- @Service:@Component的衍生注解,标注在业务类上
- @Repository:@Component的衍生注解,标注在数据访问类上(由于与mybatis整合,用得少)
注意事项:
- 声明bean的时候,可通过value属性指定bean的名字,若未指定,默认为类名首字母小写。
- 使用以上四个注解都可以声明bean,但在springboot集成web开发中,声明控制器bean只能用@Controller
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| //controller package com.ljsblog.controller; import com.ljsblog.pojo.Emp; import com.ljsblog.pojo.Result; import com.ljsblog.service.EmpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class EmpController { @Autowired private EmpService empService; @RequestMapping("/listEmp") public Result list(){ List<Emp> empList=empService.empList(); return Result.success(empList); } }
//dao package com.ljsblog.dao.impl; import com.ljsblog.dao.EmpDao; import com.ljsblog.pojo.Emp; import com.ljsblog.utils.XmlParserUtils; import org.springframework.stereotype.Repository;
import java.util.List; @Repository public class EmpDaoA implements EmpDao { @Override public List<Emp> listEmp() { String file=this.getClass().getClassLoader().getResource("emp.xml").getFile(); System.out.println(file); List<Emp> empList= XmlParserUtils.parse(file,Emp.class); return empList; } } package com.ljsblog.dao; import com.ljsblog.pojo.Emp; import java.util.List; public interface EmpDao { public List<Emp> listEmp(); }
//Service package com.ljsblog.service.impl; import com.ljsblog.dao.EmpDao; import com.ljsblog.pojo.Emp; import com.ljsblog.service.EmpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service;
import java.util.List; @Service public class EmpServiceA implements EmpService { @Autowired private EmpDao empDao; @Override public List<Emp> empList() { List<Emp> empList=empDao.listEmp(); empList.stream().forEach(emp -> { String gender=emp.getGender(); if(gender.equals("1")){ emp.setGender("男"); }else { emp.setGender("女"); } String job=emp.getJob(); if(job.equals("1")){ emp.setJob("讲师"); }else if(job.equals("2")){ emp.setJob("班主任"); } else { emp.setJob("就业指导"); } }); return empList; } } package com.ljsblog.service; import com.ljsblog.pojo.Emp; import java.util.List; public interface EmpService { public List<Emp> empList(); }
|
Bean组建扫描:前面声明bean的四大注解,想要生效,需被组建扫描注解@ComponentScan扫描。
@ComponentScan注解虽然没有显式配置,却已包含在启动类声明注解@SpringBootApplication中,默认扫描的范围是启动类所在包及其子包。
DI
依赖注入的注解:
- @Autowired:默认按照类型自动装配
- 若同类型的bean存在多个
- @Primary
- @Autowired+@Qualifier(“bean的名称,bean默认是类的首字母小写”)
- @Resource(name=”bean的名称”)
@Resource和@Autowired的区别:
- @Autowired是spring框架提供的注释,@Resource是JDK提供的注解
- @Autowired默认是按照类型注入,而@Resource默认是按照名称注入。