一、请求
1.简单参数
1)在原始的web程序中,获取请求参数,需要通过HttpServletRequest 对象手动获取。
@RequestMapping("/simpleParam")
public String simpleParam(HttpServletRequest request){
//getParameter为红色需要引入tomcat 的lib文件夹下的jsp-api.jar和servlet-api.jar
String name = request.getParameter("name");
String ageStr = request.getParameter("age");
int age = Integer.parseInt(ageStr);
System.out.println(name+" : "+age); return "OK";
}
2)SpringBoot简单参数:参数名与形参变量名相同,定义形参即可接收参数
@RequestMapping("/simpleParam")
public String simpleParam(String name , Integer age){
System.out.println(name+" : "+age);
return "OK";
}
如果方法形参名称与请求参数名称不匹配,可以使用 @RequestParam 完成映射。
@RequestMapping("/simpleParam")
public String simpleParam(
//@RequestParam 完成映射
@RequestParam (name="name") String userName, Integer age
){
System.out.println(userName+" : "+age);
return "OK";
}
注:@RequestParam中的required属性默认为true,代表该请求参数必须传递,如果不传递
将报错。 如果该参数是可选的,可以将required属性设置为false。
@RequestParam (name="name",required = false)
2.实体参数
1)简单实体对象:请求参数名与形参对象属性名相同
@RequestMapping("/simpleParam")
public String simpleParam(User user){
System.out.println(user);
return "ok";
}
public class User {
private String name;
private Integer age;
}
2)复杂实体对象:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套参
数。
@RequestMapping("/simpleParam")
public String simpleParam(User user){
System.out.println(user);
return "ok";
}
public class User {
private String name;
private Integer age;
private Address address;
}
public class Address {
private String province;
private String city;
}
3.数组集合参数
1)数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参
数
@RequestMapping("/arryParam")
public String arrayParam(String[] hobby){
System.out.println(Arrays.toString(hobby));
return "OK";
}
2)集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam 绑定参数关
系
@RequestMapping("/listParam")
public String listParam(@RequestParam List<String> hobby){
System.out.println(hobby);
return "OK";
}
4.日期参数
使用 @DateTimeFormat 注解完成日期参数格式转换
public String dateParam(
//pattern指定日期格式
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime
){
System.out.println(updateTime);
return "OK";
}
5.Json参数
JSON数据键名与形参对象属性名相同,需要使用 @RequestBody 标识
@RequestMapping("/jsonParam")
public String jsonParam(@RequestBody User user){
System.out.println(user);
return "OK";
}
注:JSON格式在postMan中发送请求时应注意上图红色标识位置
6.路径参数
通过请求URL直接传递参数,使用{…}来标识该路径参数,需要使用 @PathVariable 获取路径参数
二、响应
1.@ResponseBody
类型:方法注解、类注解
位置:Controller方法上/类上
作用:将方法返回值直接响应,如果返回值类型是 实体对象/集合 ,将会转换为JSON格式响
应
说明:@RestController = @Controller + @ResponseBody ;
2.统一响应结果
在实际开发中由于String,list等相应结果的不同,为了前端便于判断,统一相应格式如下:
public class Result {
//响应码,1 代表成功; 0 代表失败 ,可根据自己公司进行统一设定
private Integer code;
//提示信息
private String msg;
//返回的数据
private Object data;
//…….
}
3.案例(不建议看,没有源文件)
获取员工数据,返回统一响应结果,在页面渲染展示
@RequestMapping("/listEmp")
public Result list(){
//1.加载并解析emp.xml
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
final List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
//2.对数据进行转换处理-gender,job
empList.stream().forEach(emp -> {
//处理gender:1: 男, 2: 女
final String gender = emp.getGender();
if("1".equals(gender)){
emp.setGender("男");
}else if("2".equals(gender)){
emp.setGender("女");
}
//处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
final String job = emp.getJob();
if("1".equals(job)){
emp.setJob("讲师");
}else if("2".equals(job)){
emp.setJob("班主任");
}else if("3".equals(job)){
emp.setJob("就业指导");
}
});
//3.响应数据
return Result.success(empList);
}
三、分层解耦
1.三层架构
通过上面的案例可以知道第一个注释的位置是数据访问,第二个注释的位置是逻辑处理,第三个注释位置是接收请求、响应数据。但是在一个大的需求中我们将三个部分放在一起就特别乱,为了使代码逻辑更清晰,更便于维护,我们会将三部分放到不同的代码块中,这样的做法遵从的就是单一职责原则。
三层架构:
第一层:controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据。
private EmpService empService = new EmpServiceA();
@RequestMapping("/listEmp")
public Result list(){
//1.调用service层,获取数据
final List<Emp> empList = empService.empList();
//3.响应数据
return Result.success(empList);
}
第二层:service:业务逻辑层,处理具体的业务逻辑。
private EmpDao empDao = new EmpDaoA();
@Override
public List<Emp> empList() {
//1.获取到中的数据
final List<Emp> empList = empDao.empList();
//2.对数据进行转换处理-gender,job
empList.stream().forEach(emp -> {
//处理gender:1: 男, 2: 女
final String gender = emp.getGender();
if("1".equals(gender)){
emp.setGender("男");
}else if("2".equals(gender)){
emp.setGender("女");
}
//处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
final 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:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、
删、改、查。
@Override
public List<Emp> empList() {
//1.加载并解析emp.xml
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
final List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
return empList;
}
采用三层架构之后代码的复用性强、便于维护、利于拓展
2.分层解耦
内聚:软件中各个功能模块内部的功能联系。
耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
软件设计原则:高内聚低耦合。
为了根据软件设计原则来实现功能,我们需要借助容器进行管理对象,尽量解除层与层之间的依赖。这事我们需要引入领个概念:控制翻转(IOC)和依赖注入(DI)
3.IOC & DI入门
控制反转: Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),
这种思想称为控制反转。
依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为
依赖注入。
Bean对象:IOC容器中创建、管理的对象,称之为bean。
①. Service层 及 Dao层的实现类,交给IOC容器管理。
需要借助@Component注解
@Component //将当前对象交给IOC容器管理,成为IOC容器的bean
public class EmpServiceA implements EmpService {
}
}
②. 为Controller及Service注入运行时,依赖的对象。
需要借助@Autowired注解
@RestController
public class EmpController {
@Autowired //运行时,需要从IOC容器中获取该类型对象,赋值给该变量
private EmpService empService ;
}
③. 运行测试。
当有两个及以上的实现类的时候,我们确定好要用的实现类,将其他实现类的注解@Component注释掉来完成更换实现类
4.IOC详解
注解 | 说明 | 位置 |
@Component | 声明bean的基础注解 | 不属于以下三类时,用此注解 |
@Controller | @Component的衍生注解 | 标注在控制器类上 |
@Service | @Component的衍生注解 | 标注在业务类上 |
@Repository | @Component的衍生注解 | 标注在数据访问类上(由于与mybatis整合,用的少) |
注意:
① 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小
写。
② 使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能
用@Controller。
Bean组件扫描:
① 前面声明bean的四大注解,要想生效,还需要被组件扫描注解@ComponentScan扫描。
② @ComponentScan注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解 @SpringBootApplication 中,默认扫描的范围是启动类所在包及其子包。
5.DI详解
@Autowired注解,默认是按照类型进行,如果存在多个相同类型的bean,将会报出如下错误:
通过以下几种方案来解决:
① @Primary 加在服务类上面,确定类的优先级
@Primary
@Service
public class EmpServiceA implements EmpService {
}
② @Qualifier 通过value值指定bean类的名字,来确定注入的类
@RestController
public class EmpController {
@Autowired
@Qualifier("empServiceA")
private EmpService empService ;
③ @Resource 通过name值指定bean的名字,来确定注入的类
@RestController
public class EmpController {
@Resource(name = "empServiceB")
private EmpService empService ;
面试题:@Resource 与 @Autowired区别
答:
① @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解。
② @Autowired 默认是按照类型注入,而@Resource默认是按照名称注入。