请求响应和分层解耦(四)


请求响应和分层解耦(四)

请求

简单参数

  1. 原始方式获取请求参数
  2. SpringBoot中接收简单参数
  3. @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的区别

  1. @Autowired是spring框架提供的注释,@Resource是JDK提供的注解
  2. @Autowired默认是按照类型注入,而@Resource默认是按照名称注入。

Author: ljs
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source ljs !
评论
  TOC