JavaWeb - 8 - 请求响应 & 分层解耦

请求响应

请求(HttpServletRequest):获取请求数据

响应(HttpServletResponse):设置响应数据

BS架构 :Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端(维护方便,体验一般)

CS架构 :Client/Server,客户端/服务器架构模式(开发维护麻烦、体验不错)

一.请求

1.1 Postman

Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件

作用:常用于进行接口测试

1.2 简单参数

原始方式

在原始的web程序中,获取请求参数,需要通过HttpServletRequest对象手动获取

**·**Controller方法形参中声明HttpServletRequest对象

**·**调用对象的getParameter(参数名)

SpringBoot方式

**·**简单参数:参数名与形参变量名相同,定义形参即可接收参数(会自动进行类型转换)

**·**简单参数:如果方法形参名称与请求参数名称不匹配,可以使用@RequestParam完成映射

注意事项:@RequestParam中的required属性默认为true,代表该请求参数必须传递,如果不传递将报错。如果该参数是可选的,可以将required属性设置为false

1.3 实体参数

简单实体对象:请求参数名与形参对象属性名相同,定义POJO接收即可

复杂实体对象:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数

1.4 数组集合参数

数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数

集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam绑定参数关系

1.5 日期参数

日期参数:使用@DateTimeFormat注解完成日期参数格式转换

1.6 JSON参数

JSON参数:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数,需要使用@RequestBody标识

1.7 路径参数

路径参数:通过请求URL直接传递参数,使用{...}来标识该路径参数,需要使用@PathVariable获取路径参数

java 复制代码
/**
 * 测试请求参数接收
 */
@RestController
public class RequestController {
    //原始方式
//    @RequestMapping("/simpleParam")
//    public String simpleParam(HttpServletRequest request){
//        //获取请求参数
//        String name = request.getParameter("name");
//        String ageStr = request.getParameter("age");
//
//        int age = Integer.parseInt(ageStr);
//
//        System.out.println(name + ":" + age);
//
//        return "OK";
//    }

    //springboot方式
    //简单参数GET
//    @RequestMapping("/simpleParam")
//    public String simpleParam(String name, Integer age){
//        System.out.println(name + ":" + age);
//        return "OK";
//    }

    //简单参数POST
    @RequestMapping("/simpleParam")
    public String simpleParam(@RequestParam(name="name", required = false) String username, Integer age){
        System.out.println(username + ":" + age);
        return "OK";
    }

    //简单实体参数
    @RequestMapping("/simplePojo")
    public String simplePojo(User user){
        System.out.println(user);
        return "OK";
    }

    //复杂实体参数
    @RequestMapping("/complexPojo")
    public String complexPojo(User user){
        System.out.println(user);
        return "OK";
    }

    //数组参数
    @RequestMapping("/arrayParam")
    public String arrayParam(String[] hobby){
        System.out.println(Arrays.toString(hobby));
        return "OK";
    }

    //集合参数
    @RequestMapping("/listParam")
    public String listParam(@RequestParam List<String> hobby){
        System.out.println(hobby);
        return "OK";
    }

    //日期时间参数
    @RequestMapping("/dateParam")
    public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime){
        System.out.println(updateTime);
        return "OK";
    }

    //json参数
    @RequestMapping("/jsonParam")
    public String jsonParam(@RequestBody User user){
        System.out.println(user);
        return "OK";
    }

    //路径参数
    @RequestMapping("/path/{id}")
    public String pathParam(@PathVariable Integer id){
        System.out.println(id);
        return "OK";
    }

    @RequestMapping("/path/{id}/{name}")
    public String pathParam2(@PathVariable Integer id, @PathVariable String name){
        System.out.println(id + ":" + name);
        return "OK";
    }
}

二.响应

2.1 @ResponseBody

类型:方法注解、类注解

位置:Controller方法上/类上

作用:方法返回值直接响应,如果返回值类型是实体对象/集合,将会转换为JSON格式响应

说明:@RestController = @Controller + @ResponseBody

2.2 统一响应结果

Result(code、msg、data)

java 复制代码
/**
 * 测试响应数据
 */
@RestController
public class ResponseController {

//    @RequestMapping("/hellohello")
//    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;
//    }


    @RequestMapping("/hello1")
    public Result hello(){
        System.out.println("Hello World ~");
        //return new Result(1,"success","Hello World ~");
        return Result.success("Hello World ~");
    }

    @RequestMapping("/getAddr")
    public Result getAddr(){
        Address addr = new Address();
        addr.setProvince("广东");
        addr.setCity("深圳");
        return Result.success(addr);
    }

    @RequestMapping("/listAddr")
    public Result 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 Result.success(list); 
    }
}

/**
 * 统一响应结果封装类
 */
public class Result {
    private Integer code ;//1 成功 , 0 失败
    private String msg; //提示信息
    private Object data; //数据 date

    public Result() {
    }
    public Result(Integer code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer 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;
    }

    public static Result success(Object data){
        return new Result(1, "success", data);
    }
    public static Result success(){
        return new Result(1, "success", null);
    }
    public static Result error(String msg){
        return new Result(0, msg, null);
    }

    @Override
    public String toString() {
        return "Result{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
}

2.3 案例

java 复制代码
//Controller.EmpController.java

@RestController
public class EmpController {
    @RequestMapping("/listEmp")
    public Result list(){
        //1.加载并解析emp.xml
        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
        System.out.println(file);
        List<Emp> empList = XmlParserUtils.parse(file, Emp.class);

        //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("就业指导");
            }
        });

        //3.响应数据
        return Result.success(empList);
    }
}

三.分层解耦

3.1 三层架构

Controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据

Service:业务逻辑层,处理具体的业务逻辑

Dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增删改查

3.2 分层解耦

**·**内聚:软件中各个功能模块内部的功能联系

**·**耦合:衡量软件中各个层/模块之间的依赖、关联的程度

**·**软件设计原则:高内聚低耦合

控制反转 :Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转

依赖注入 :Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入

Bean对象 :IOC容器中创建、管理的对象,称之为bean

3.3 IOC & DI入门

如果有多个实现类(A、B),需要切换实现类,通过注释@Component实现切换(用A的时候在A中加入@Component,用B的时候在B中加入@Component)

3.4 IOC详解

Bean的声明

要把某个对象交给IOC容器管理,需要在对应的类上加上如下注解之一(@Component @Controller @Service @Repository)

注意事项

**·**声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写

**·**使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller

Bean组件扫描

**·**前面声明bean的四大注解,想要生效,还需要被组件扫描注解@ComponentScan扫描

·@ComponentScan注解虽然没有显式配置,但实际上已经包含在了启动类声明注解@SpringBootApplication中,默认扫描的范围是启动类所在包及其子包

3.5 DI详解

·@Autowired注解,默认是按照类型自动装配,如果存在多个相同类型的bean,将会报出如下错误:

通过以下几种方案来解决:@Primary、@Autowired+@Qualifier("bean的名称")、@Resource(name = "bean的名称")

注意:@Resource与@Autowired区别

· @Autowired是spring框架提供的注解,而@Resource是JDK提供的注解

· @Autowired默认是按照类型注入,而@Resource默认是按照名称注入

相关推荐
winks34 分钟前
Spring Task的使用
java·后端·spring
秋意钟15 分钟前
Spring新版本
java·后端·spring
椰椰椰耶17 分钟前
【文档搜索引擎】缓冲区优化和索引模块小结
java·spring·搜索引擎
mubeibeinv18 分钟前
项目搭建+图片(添加+图片)
java·服务器·前端
青莳吖20 分钟前
Java通过Map实现与SQL中的group by相同的逻辑
java·开发语言·sql
Buleall27 分钟前
期末考学C
java·开发语言
重生之绝世牛码29 分钟前
Java设计模式 —— 【结构型模式】外观模式详解
java·大数据·开发语言·设计模式·设计原则·外观模式
小蜗牛慢慢爬行35 分钟前
有关异步场景的 10 大 Spring Boot 面试问题
java·开发语言·网络·spring boot·后端·spring·面试
新手小袁_J1 小时前
JDK11下载安装和配置超详细过程
java·spring cloud·jdk·maven·mybatis·jdk11
呆呆小雅1 小时前
C#关键字volatile
java·redis·c#