首页 > 编程语言 >JAVA_WEB复习之请求响应

JAVA_WEB复习之请求响应

时间:2024-05-09 17:46:23浏览次数:20  
标签:WEB return 复习 请求 参数 注解 JAVA public String

  1. 简单参数请求:原始的方法,我们需要通过servlet中提供的api,HttpServletRequest(请求对象),获取请求的相关信息。比如获取请求参数:当tomcat接收到请求时,它会把请求的信息封装httpservletrequest到对象中。
  2. 而在Springboot的环境,原始的API进行了封装,接收参数的形式更加简单。 如果是简单参数,参数名与形参变量名相同,定义同名的形参即可接收参数。
点击查看代码
@RestController
public class RequestController {
    // http://localhost:8080/simpleParam?name=Tom&age=10
    // 第1个请求参数: name=Tom   参数名:name,参数值:Tom
    // 第2个请求参数: age=10     参数名:age , 参数值:10
    
    //springboot方式
    @RequestMapping("/simpleParam")
    public String simpleParam(String name , Integer age ){//形参名和请求参数名保持一致
        System.out.println(name+"  :  "+age);
        return "OK";
    }
}
3.如果形参名与请求参数名不一致,则可以使用spring提供的@RequestParam注解来完成映射,也就是在方法前面加上@RequestParam 然后通过value属性执行请求参数名,从而完成映射。
点击查看代码
@RestController
public class RequestController {
    // http://localhost:8080/simpleParam?name=Tom&age=20
    // 请求参数名:name

    //springboot方式
    @RequestMapping("/simpleParam")
    public String simpleParam(@RequestParam("name") String username , Integer age ){
        System.out.println(username+"  :  "+age);
        return "OK";
    }
}
值得注意的是,该注解中的required属性默认为true的,代表该请求参数必须传递,如果不传递就会报错的,如果该参数是可选的,那么可以将required属性设置为false。
点击查看代码
@RequestMapping("/simpleParam")
public String simpleParam(@RequestParam(name = "name", required = false) String username, Integer age){
System.out.println(username+ ":" + age);
return "OK";
}
4.如果前端传入的参数过多,此时我们就可以引入实体类,将请求的数据封装到实体类中,值得注意的是,要想完成数据的封装,必须要得将请求参数名与实体类的属性名相同,必须对应, 5.下面则是比较复杂的实体类对象。指的即是,在一个实体类中有一个或多个属性,一个实体类中还嵌套其他的实体类,如下所示: ![](/i/l/?n=24&i=blog/3280652/202405/3280652-20240509104627798-110414460.png) 复杂实体类需要注意的是:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套实体类属性参数。 6.数组集合参数,当我们在前端页面表单进行多选情况时,可以提交多个值,那么就用到了数组集合了。那么多个值如何去提交,其实也是去一个一个提交的,后端接受的方式有两种,要么是数组,要么就是集合了。 定义数组时,只需注意参数名和形参数组名相同,且请求参数有多个,即可满足接受参数。
点击查看代码
@RestController
public class RequestController {
    //数组集合参数
    @RequestMapping("/arrayParam")
    public String arrayParam(String[] hobby){
        System.out.println(Arrays.toString(hobby));
        return "OK";
    }
}
7.集合参数: 当请求参数名与形参的集合对象名相同且请求参数为多个,@RequestParam 绑定参数关系,为什么要加注解呢,因为默认情况下,请求参数名相同的多个值,默认封装到数组中去的,如果要封装到集合中,就要使用该注解绑定参数关系。
点击查看代码
@RestController
public class RequestController {
    //数组集合参数
    @RequestMapping("/listParam")
    public String listParam(@RequestParam List<String> hobby){
        System.out.println(hobby);
        return "OK";
    }
}
8.那么这两个的区别在哪里呢,显而易见的,数组参数只能接受基本数据类型的数据传入,而集合不同,它既可以传入基本数据类型,还可以传入引用数据类型,可根据具体开发文档进行使用。 9.日期参数:在一些特殊情况下,有可能会涉及到日期类型的数据分装。 因为日期的格式多种多样(如:2022-12-12 10:05:45 、2022/12/12 10:05:45),那么对于日期类型的参数在进行封装的时候,需要通过@DateTimeFormat注解,以及其pattern属性来设置日期的格式。 这个注解的pattern属性指定了什么格式,前端的日期参数就必须按照什么格式传递,在后端的controller方法中,需要使用date类型或localdatetime类型,来封装传递的参数。
点击查看代码
@RestController
public class RequestController {
    //日期时间参数
   @RequestMapping("/dateParam")
    public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime){
        System.out.println(updateTime);
        return "OK";
    }
}
10.当我们开发时,如果需要传输比较复杂的参数时,前后端交互则会通过json格式的数据的传输。主要说明的就是,服务端在接受json数据时,需要使用实体类进行封装,json数据键名必须与形参对象属性名一致,定义对应的pojo数据即可接受参数,需要使用requestbody注解进行标识,该注解的作用就是,将json数据映射到形参的实体类中去,参数属性名必须保持一致啊!!
点击查看代码
@RestController
public class RequestController {
    //JSON参数
    @RequestMapping("/jsonParam")
    public String jsonParam(@RequestBody User user){
        System.out.println(user);
        return "OK";
    }
}
11.路径参数,什么是路径参数,传统意义上,即是请求参数放在请求体上传递,(这是post请求),或者跟在url后面,通过key=vlaue的形式传递,(这是get请求) 这是我们现在的开发,经常还是会直接使用url:
点击查看代码
xxxxxxxxxx http://localhost:8080/user/1        http://localhost:880/user/1/0
这被称为是路径参数,那么在springboot下,后端如何去接收数据呢? 前端:通过请求url直接传递参数 后端:使用{....}来标识该路径参数,需要使用@PathVariable获取路径参数
点击查看代码
xxxxxxxxxx @RestControllerpublic class RequestController {    //路径参数    @RequestMapping("/path/{id}")    public String pathParam(@PathVariable Integer id){        System.out.println(id);        return "OK";    }}
因为前端传递的路径是可变的,所以后端在接收参数时,使用“{key}”的方式来标记路径参数 该注解:1.获取到路径参数{id}2.把路径参数绑定到形参变量id上

那么如果需要传递多个路径参数该怎么办,很简单,前端正常输入路径参数{id},后端接收的时候/{id}/{id},然后在方法形参里面加上注解@pathvariable,每个形参前都需要加上,这样就可以自动绑定。

点击查看代码
@RestController
public class RequestController {
    //路径参数
    @RequestMapping("/path/{id}/{name}")
    public String pathParam2(@PathVariable Integer id, @PathVariable String name){
        System.out.println(id+ " : " +name);
        return "OK";
    }
}

12.响应
所谓有得必有失,那么有请求就有响应。Controller程序不仅可以接收数据,还可以进行响应数据。

在控制层中方法的返回值,return结果,它是如何响应给浏览器的呢?这个时候我们就用到了注解>** @ResponseBody。**
下面介绍一下这个注解的功能。
类型:方法注解、类注解
作用:将方法的返回值直接去响应给浏览器,如果范围值类型是实体对象或是集合的话,将会直接转换给json格式返回给浏览器。
但是我们所写的Controller方法中,只在类上添加了@RestController注解,方法添加了Requestmapping注解,并没有使用@ResponseBody注解,那么如何给浏览器进行响应呢?

点击查看代码
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        System.out.println("Hello World ~");
        return "Hello World ~";
    }
}
原因就是@RestController是一个组合注解: @RestController = @Controller + @ResponseBody
点击查看代码
@Target({ElementType.TYPE})   //元注解(修饰注解的注解)
@Retention(RetentionPolicy.RUNTIME)  //元注解
@Documented    //元注解
@Controller   
@ResponseBody 
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}
结论:当在类上添加@RestController就相当于添加了@ResponseBody注解。 当类上有@RestController注解或者@ResponseBody注解时,表示当前类下所有的方法返回值做为响应数据。 方法的返回值,如果是一个POJO或者是一个集合时,会先转换为JSON数据,再响应给浏览器。
点击查看代码
@RestController
public class ResponseController {
    //响应字符串
    @RequestMapping("/hello")
    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;
    }
}

以上这些控制层里的方法,返回值比较杂乱,没有任何规范,当进行大型代码的开发时,多人合并开发的情况下,你所写的接口,别人看起来是不是不那么方便,项目就会变得难以维护,那么接下来就为大家介绍一下:

13.统一的响应结果
有了统一的响应结果,前端只需要按照统一的返回结果进行解析,就可以拿到比较规范的数据。
使用类来描述即是:

  • 响应状态码:当前返回的数据是否正确
  • 状态码信息:给页面进行反馈的提示信息
  • 返回来的数据:给前端响应的数据(字符串,对象,集合)

定义一个标准化的实体类,return的时候可以直接返回它。

点击查看代码
public class Result {
    private Integer code;//响应码,1 代表成功; 0 代表失败
    private String msg;  //响应码 描述字符串
    private Object data; //返回的数据

    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(){
        return new Result(1,"success",null);
    }
    //查询 成功响应(把查询结果做为返回数据响应给前端)
    public static Result success(Object data){
        return new Result(1,"success",data);
    }
    //失败响应
    public static Result error(String msg){
        return new Result(0,msg,null);
    }
}
在控制层的方法中,只需return Result.success(),调用这个标准化实体类的方法,实体类有方法的空参和全参构造,可以根据需要进行返回。
点击查看代码
@RestController
public class ResponseController { 
    //响应统一格式的结果
    @RequestMapping("/hello")
    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);
    }
}

14.分层解耦
三层架构的引入,当我们在Controller层进行代码开发时,不论是XML数据,获取数据的代码,处理数据的逻辑的代码,给页面响应的代码全部都放在一起,都是控制层的方法中实现,小型项目开发还行,但是如果涉及到大型的开发时,就会变得非常臃肿,这个时候就引入了三层架构的拆分。
一般的项目进行开发时,会有如下的几种处理逻辑:

  • Controller :接受请求,响应数据,接受前端的所发送的请求,对请求进行处理,并且响应数据
  • Service : 进行逻辑处理;处理具体的业务逻辑,一般在它的实现类中实现。
  • Dao: 数据访问;也可以成为持久层,即时通过对数据库进行访问操作,包括数据的增、删、改、查。

基于以上三层架构的工作流程如下:

  • 首先则是前端发起请求,后端这边先由Controller层出来接受,再响应回去。
  • 此时控制层干什么,它就开始调用服务层来进行业务逻辑处理了,它处理完之后,把结果再返回给控制层。服务层再调用Dao层,在进行逻辑处理的过程中,需要使用Dao层中的数据,即就是从Dao层获取,Dao层操作文件中的数据,通过crud获得数据再给service层返回回去。

到这里了,相比已经知道了三层架构的优势了
即为以下几点:复用性强,便于维护,利于拓展。
15.耦合问题
什么是耦合问题?什么是内聚?什么是耦合?
内聚就是软件中各个功能模块中内部之间的关联
耦合即是衡量软件中各个层/模块之间的依赖程度,简而言之就是紧密程度。

高内聚指的是:一个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间的联系程度越高,则内聚性越高,即 "高内聚"。
低耦合指的是:软件中各个层、模块之间的依赖关联程序越低越好。
这是程序开发的最优目的。
16.如何解耦
之前的时候,我们需要什么对象,new就行,但是如果要低耦合,让程序重用性更好,移植性更好,就不能再new一个实体类的对象。
那该怎么办呢,不能new对象,这很难受啊。此时,我们提供的解决思路就是:

  • 首先提供一个容器,容器中提供一对象(例如:EmpService对象)
  • Controller程序从容器中获取EmpService的对象
    要想实现解耦,就关联到Spring中的两个核心相关概念了
    首先则是控制反转,IOC。对象的创建控制权由程序自身转移到外部,这就是控制反转。也称为Spring容器。
    另外一个核心的概念即是依赖注入了,DI。当容器为程序提供运行时,所依赖的资源,称之为依赖注入。大白话来说,就是例如控制层在运行的时候需要EmpService层的对象了,那么Spring容器,也就是IOC容器就会为其提供并且注入EmpService对象。
    重点!!! IOC容器中创建、管理的对象,称之为bean对象。
    说了这么多,那么在实际开发过程中,如何去实现呢?
  • 首先删除Controller层、Service层中new对象的代码
  • Service层及Dao层的实现类,交给IOC容器管理
  • 为Controller及Service注入运行时依赖的对象
  • Controller程序中注入依赖的Service层对象
  • Service程序中注入依赖的Dao层对象
    删除了new对象的代码后,在Service层,以及Dao层的实现类中,使用@Component 注解,即可实现交给IOC容器管理。

然后就是在Controller以及Service注入运行时所需的依赖对象了。
@Autowired 注解,有了它,- 就可以实现程序运行时IOC容器自动注入需要的依赖对象。

面试题 : @Autowird 与 @Resource的区别

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

以上所有都依据黑马java理解总结。

标签:WEB,return,复习,请求,参数,注解,JAVA,public,String
From: https://www.cnblogs.com/wzyzq/p/18181709

相关文章

  • Springboot项目的jar包的运行方式以及使用yum安装java后忘记了位置
    SpringBoot项目打包后的jar的部署方式这里我写了五种部署方式1.直接启动java-jarxxx.jar这种方式就只适合自己在测试时用一下,关闭会话就能停止运行属实是方便。2.后台启动java-jarxxx.jar&在后台静默启动,同样关闭会话也会停止,优点是和上面一样,日志是打印在窗口的3......
  • java9
    小练习:publicclasstest1{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);System.out.println("请输入当前机票的原价");intticket=sc.nextInt();System.out.println("请输入月份");int......
  • Java根据数学公式计算出结果
    importjavax.script.ScriptEngine;importjavax.script.ScriptEngineManager;importjavax.script.ScriptException;publicclassTest{publicstaticvoidmain(String[]args){//年均充放电量=(E2*H4*G4*0.95*0.86)*0.871/10000Stringexpressi......
  • 【java】Java之关于基本数据类型和引用数据类型的存放位置
    1、基本数据类型存放在哪?基本类型的变量存在栈里或者堆里不是由"大小可知,生存期可知"就能确定了。关键是上下文。比如:123voidmethod(){    inta=3;}这自然是存在栈里的。局部方法嘛。而:123classTest{    inta=3;}......
  • Java学设计模式之桥接模式
    一、桥接模式概念1.1什么是桥接模式桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化。桥接模式通过将抽象部分和实现部分分离来解决多维度变化的问题,从而提高了系统的灵活性和可扩展性。结构桥接模式通常由以下几个部分组成:Abstraction(抽象类......
  • 第二届数信杯南区wp-easyJava
    writeupeasyJava用EclipseMemoryAnalyzer进行分析,利用OQL查找字符串这里要写正则表达式:我写了\\u.*意思是找unicode字符串,因为这里的中文都做了unicode编码搜索到这么一个字符串列表,转码——红色框框里的是还原后的内容。如下:想跟你说一个小秘密:我把码表修改成了......
  • Java-线程-线程池
    0.背景参考资料:Java线程池实现原理及其在美团业务中的实践在Java早期,每次创建线程时,都要涉及到线程的创建、销毁以及资源管理,这对于系统的性能和资源利用率是一种浪费。因此,Java提供了线程池的概念,以提高线程的管理效率和性能。资源管理优化:传统的线程创建和销毁需要涉......
  • Java学设计模式之装饰器模式
    一、模式概念1.1什么是模式装饰模式是一种结构型设计模式,它允许向现有对象动态添加新功能,同时又不改变其结构。装饰模式通过将对象放置在包装器类中,然后在运行时动态地向对象添加新的行为或责任,从而实现这一目的。结构装饰模式通常由以下几个部分组成:Component(组件):定义一......
  • Java学设计模式之适配器模式
    一、适配器模式概念1.1什么是适配器模式适配器模式是一种结构型设计模式,它提供了一种将不兼容的接口转化为兼容的接口的方式,从而使原本无法一起工作的类可以协同工作。适配器模式可以分为两种:对象适配器和类适配器。1.2对象适配器对象适配器通过组合的方式,将不兼容的接口适......
  • Java学设计模式之原型模式
    一、原型模式概念原型模式是一种创建型设计模式,其核心思想是通过复制现有对象来创建新对象,而不是通过实例化类来创建。这种方式可以提高创建对象的效率,特别是当对象的创建过程比较昂贵或复杂时。在原型模式中,原型对象是一个已经存在的对象,它作为新对象的模板。新对象通过复制原......