Web后端开发——请求响应

一、请求

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默认是按照名称注入。

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值