项目实战(SpringMVC接收请求参数、RESTful设计风格、响应正文结果、前后端交互)

15. 在Spring MVC中接收请求参数

如果客户端提交的请求参数数量较少,且参数之间没有相关性,则可以选择将各请求参数声明为处理请求的方法的参数,并且,参数的类型可以按需设计。

如果客户端提交的请求参数略多(达到2个或以上),且参数之间存在相关性,则应该将这些参数封装到自定义的POJO类型中,并且,使用此POJO类型作为处理请求的方法的参数,同样,POJO类中的属性的类型可以按需设计。

关于请求参数的值:

  • 如果客户端没有提交对应名称的请求参数,则方法的参数值为null

  • 如果客户端提交了对应名称的请求参数,但是没有值,则方法的参数值为空字符串(""),如果方法的参数是需要将字符串转换为别的格式,但无法转换,则参数值为null,例如声明为Long类型时

  • 如果客户端提交对应名称的请求参数,且参数有正确的值,则方法的参数值为就是请求参数值,如果方法的参数是需要将字符串转换为别的格式,但无法转换,则会抛出异常

另外,还推荐将某些**具有唯一性的(且不涉及隐私)**参数设计到URL中,使得这些参数值是URL的一部分!例如:

https://blog.csdn.net/weixin_407563/article/details/854745877
https://blog.csdn.net/qq_3654243299/article/details/847462823

Spring MVC框架支持在设计URL时,使用{名称}格式的占位符,实际处理请求时,此占位符位置是任意值都可以匹配得到!

例如,将URL设计为:

@RequestMapping("/delete/{id}")

在处理请求的方法的参数列表中,用于接收占位符的参数,需要添加@PathVariable注解,例如:

public String delete(@PathVariable Long id) {
	// 暂不关心方法内部的实现   
}

如果{}占位符中的名称,与处理请求的方法的参数名称不匹配,则需要在@PathVariable注解上配置占位符中的名称,例如:

@RequestMapping("/delete/{albumId}")
public String delete(@PathVariable("albumId") Long id) {
	// 暂不关心方法内部的实现   
}

在配置占位符时,可以在占位符名称的右侧,可以添加冒号,再加上正则表达式,对占位符的值的格式进行限制,例如:

@RequestMapping("/delete/{id:[0-9]+}")

如果按照以上配置,仅当占位符位置的值是纯数字才可以匹配到此URL!

并且,多个不冲突有正则表达式的占位符配置的URL是可以共存的!例如:

@RequestMapping("/delete/{id:[a-z]+}")

以上表示的是“占位符的值是纯字母的”,是可以与以上“占位符的值是纯数字的”共存!

另外,某个URL的设计没有使用占位符,与使用了占位符的,是允许共存的!例如:

@RequestMapping("/delete/test")

Spring MVC会优先匹配没有使用占位符的URL,再尝试匹配使用了占位符的URL。

16. 关于RESTful

RESTful也可以简称为REST,是一种设计软件的风格。

RESTful既不是规定,也不是规范。

RESTful风格的典型表现主要有:

  • 处理请求后是响应正文的
  • 将具有唯一性的参数值设计在URL中
  • 根据请求访问数据的方式,使用不用的请求方式
    • 如果尝试添加数据,使用POST请求方式
    • 如果尝试删除数据,使用DELETE请求方式
    • 如果尝试修改数据,使用PUT请求方式
    • 如果尝试查询数据,使用GET请求方式
    • 这种做法在复杂的业务系统中并不适用

在设计RESTful风格的URL时,建议的做法是:

  • 查询某数据的列表:/数据类型的复数,并使用GET请求方式,例如/albums
  • 查询某1个数据(通常根据id):/数据类型的复数/id值,并使用GET请求方式,例如/albums/9527
  • 对某1个数据进行操作(增、删、改):/数据类型的复数/id值/操作,并使用POST请求方式,,例如/albums/9527/delete

17. 关于响应正文的结果

通常需要使用自定义类,作为处理请求的方法、处理异常的方法的返回值类型。

响应到客户端的数据中,应该包含“业务状态码”,以便于客户端迅速判断操作成功与否,为了规范的管理业务状态码的值,在根包下创建web.ServiceCode枚举类型:

package cn.tedu.csmall.product.web;

/**
 * 业务状态码的枚举
 * 
 * @author java@tedu.cn
 * @version 0.0.1
 */
public enum ServiceCode {

    OK(20000),
    ERR_NOT_FOUND(40400),
    ERR_CONFLICT(40900);

    private Integer value;

    ServiceCode(Integer value) {
        this.value = value;
    }

    public Integer getValue() {
        return value;
    }

}

并且,修改ServiceException异常类的代码,要求此类异常的对象中包含业务状态码,可以通过构造方法进行限制:

package cn.tedu.csmall.product.ex;

import cn.tedu.csmall.product.web.ServiceCode;

/**
 * 业务异常
 *
 * @author java@tedu.cn
 * @version 0.0.1
 */
public class ServiceException extends RuntimeException {

    private ServiceCode serviceCode;

    public ServiceException(ServiceCode serviceCode, String message) {
        super(message);
        this.serviceCode = serviceCode;
    }

    public ServiceCode getServiceCode() {
        return serviceCode;
    }
}

然后,原本业务逻辑层中抛出异常的代码将报错,需要在创建异常对象时传入业务状态码参数,例如:

throw new ServiceException(ServiceCode.ERR_CONFLICT,
                    "添加相册失败,尝试添加的相册名称已经被占用!");

接下来,还需要使用自定义类型,表示响应到客户端的数据,则在根包下创建web.JsonResult类:

package cn.tedu.csmall.product.web;

import lombok.Data;

import java.io.Serializable;

@Data
public class JsonResult implements Serializable {

    /**
     * 业务状态码的值
     */
    private Integer state;
    /**
     * 操作失败时的提示文本
     */
    private String message;

    public static JsonResult ok() {
        JsonResult jsonResult = new JsonResult();
        jsonResult.state = ServiceCode.OK.getValue();
        return jsonResult;
    }

    public static JsonResult fail(ServiceCode serviceCode, String message) {
        JsonResult jsonResult = new JsonResult();
        jsonResult.state = serviceCode.getValue();
        jsonResult.message = message;
        return jsonResult;
    }

}

在实际处理请求和异常时,Spring MVC框架会将方法返回的JsonResult对象转换成JSON格式的字符串。

例如:处理请求的代码:

@RequestMapping("/add-new")
public JsonResult addNew(AlbumAddNewDTO albumAddNewDTO) {
    log.debug("开始处理【添加相册】的请求,参数:{}", albumAddNewDTO);
    albumService.addNew(albumAddNewDTO);
    return JsonResult.ok();
}

例如:处理异常的代码:

@ExceptionHandler
public JsonResult handleServiceException(ServiceException e) {
    log.debug("捕获到ServiceException:{}", e.getMessage());
    return JsonResult.fail(e.getServiceCode(), e.getMessage());
}

通常,不需要在JSON结果中包含为null的属性,所以,可以在application.properties / application.yml中进行配置:

application.properties配置示例

# JSON结果中将不包含为null的属性
spring.jackson.default-property-inclusion=non_nul

application.yml配置示例

# Spring相关配置
spring:
  # Jackson框架相关配置
  jackson:
    # JSON结果中是否包含为null的属性的默认配置
    default-property-inclusion: non_null

18. 实现前后端交互

目前,后端(服务器端)项目使用默认端口8080,建议调整,可以通过配置文件中的server.port属性来指定。

例如,在application-dev.yml中添加配置:

# 服务端口
server:
  port: 9080

再次启动项目,通过启动时的日志,可以看到后端项目启动在9080端口。

然后,还需要在后端项目中配置允许跨域访问,则需要在实现了WebMvcConfigurer接口的配置类中,通过重写addCorsMappings()方法进行配置!

则在根包下创建config.WebMvcConfiguration类,实现WebMvcConfigurer接口,添加@Configuration注解,并重写方法配置允许跨域访问:

package cn.tedu.csmall.product.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Spring MVC的配置类
 *
 * @author java@tedu.cn
 * @version 0.0.1
 */
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    public WebMvcConfiguration() {
        System.out.println("创建配置类:WebMvcConfiguration");
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("*")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(3600);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专注摸鱼的汪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值