基础12-Restful风格的Web应用

历史

2011年毕业,在山东济南工作,当时学习HTTP请求,也知道HTTP请求的方法,但在实际开发中,就用2个:GET与POST;POST一般用于新增、更新,毕竟这2种业务一次性提交的数据量比较大,这种情况下,后台方法完全根据method的名字来判断到底是新增,还是修改,删除,更新等操作,没办法,毕竟method就取那2个值;

当时是公司UI工程师用PS切图,然后再画出HTML文件,交给开发者;开发者再把css、jpg放到指定目录下,而把html源码复制到模板文件中,再写入freemarker语法来展示后台数据;

这种模式下,对开发者要求熟悉java、数据库、js、jquery等要求,开发者确实挺累的;

后来,随着HTML5+CSS3+JQUERY、IOS、Android等各种不同平台上的Client端的不断兴起,后台开发人员越来越麻烦,原因就是:

后台开发人员,既要完成后台的业务开发,还要紧跟H5、Android、IOS的技术发展;问题是,你作为一个后台开发人员,Android还好说,IOS不是说跟就能跟进的;

面对这种情况,越来越多的公司希望前后分离,前段专业人员开发Client,后台人员开发Server,个人负责各自的的模块,专业的时候交给专业的人员来处理,这个想法是好,问题在于你如何统一H5、Android、IOS等不同Client的访问规则?

我们需要作出一个约定,然后让大家遵守,这样才能解决这个问题,这就是REST;

RESTful

REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力, 更好地使用现有Web标准中的一些准则和约束。

REST指的是一组架构约束条件和原则。如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。

通俗来讲:利用现有的技术和应用,但使用新的约定,来扩展应用,即RESTful是一种约定;

个人感想:其实一个Client端,就3个作用:展示后台数据、展示后台资源(图片、样式、视频等)、Client自身特效;其中的展示后台数据和展示后台资源都涉及到HTTP/HTTPS请求,后台动不了,那就只能针对URI进行改进了;

REST约定如下:

①资源与URI:使用_或-来让URI可读性更好、使用/来表示资源的层级关系、使用?用来过滤资源、,或;可以用来表示同级资源的关系;

②统一资源接口:RESTful架构应该遵循统一接口原则,统一接口包含了一组受限的预定义的操作,不论什么样的资源,都是通过使用相同的接口进行资源的访问。接口应该使用标准的HTTP方法如GET,PUT和POST,并遵循这些方法的语义;统一资源接口要求使用标准的HTTP方法对资源进行操作,所以URI只应该来表示资源的名称,而不应该包括资源的操作。通俗来说,URI不应该使用动作来描述;

③客户端与服务端的交互必须是无状态的,并在每一次请求中包含处理该请求所需的一切信息;服务端不需要在请求间保留应用状态,只有在接受到实际请求的时候,服务端才会关注应用状态;

统一资源接口,可以理解为如下的表现形式:

 

普通增删改查

(通过URI来区分)

Restful风格增删改查

查询

getOrgInfo

orginfo---GET

新增

addOrgInfo

orginfo---POST

更新

updateOrgInfo

orginfo/{XXX}---PUT

删除

deleteOrgInfo

orginfo/{XXX}---DELETE

代码示例

@PostMapping(value = "/cfcc/login")
public String login(
        @RequestParam("username")
        String username,
        @RequestParam("password")
        String password,
        Map<String,Object> map){
    logger.error(username + "," + password);
    map.put("name","张三");
    return "welcome";
}

@GetMapping("/cfcc/orgs")
public String list(Model model){
    List<OrgInfo> orgs = OrgInfoDao.getInstance().getOrgInfos();
    model.addAttribute("orgs",orgs);
    return "list";
}

@GetMapping("/cfcc/org")
public String addOrg(){
    return "add";
}

@PostMapping("/cfcc/org")
public String add(OrgInfo orgInfo){
    logger.error(orgInfo.toString());
    return "success";
}

@GetMapping("/cfcc/org/{id}")
public String toEdit(
        @PathVariable
        Integer id,
        Model model){
    return "add";
}

这里看一下/cfcc/org请求,一个是GET,还有一个是POST,这对后台开发而言,通过HTTP的METHOD来判断不同的业务,而对于Client端开发人员来讲,也更加简单、明了;

<form/>表单

通过w3school来查看<form/>标签,发现其method属性只能是get,或者是post,而REST则是有很多种的,那么,怎么处理这个问题呢?

打开WebMvcAutoConfiguration类,找到hiddenHttpMethodFilter方法,下面是该方法的源码:

@Bean
@ConditionalOnMissingBean({HiddenHttpMethodFilter.class})
@ConditionalOnProperty(
    prefix = "spring.mvc.hiddenmethod.filter",
    name = {"enabled"},
    matchIfMissing = false
)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
    return new OrderedHiddenHttpMethodFilter();
}

继续跟踪OrderedHiddenHttpMethodFilter类,该类继承了HiddenHttpMethodFilter类,然后看一下父类的关键方法源码:

private String methodParam = "_method";

private static final List<String> ALLOWED_METHODS;

 

static {
    ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
}

 

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        HttpServletRequest requestToUse = request;

        if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {

            String paramValue = request.getParameter(this.methodParam);

            if (StringUtils.hasLength(paramValue)) {

                String method = paramValue.toUpperCase(Locale.ENGLISH);

                if (ALLOWED_METHODS.contains(method)) {

                    requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);

                }

            }

        }

 

        filterChain.doFilter((ServletRequest)requestToUse, response);

    }

doFilterInternal首先判断是不是POST提交,如果是POST提交则从HttpRequest中获取_method属性值,如果_method属性值不为空且ALLOWED_METHODS中包含了该属性值,则把HttpRequest的method属性值设置为_method属性值;

而ALLOWED_METHODS则通过static静态代码块初始化,包含了PUT、DELETE、PATCH;

再来看看spring.mvc.hiddenmethod.filter属性,打开官网链接

最后,总结,其<form/>最后则是这么编写:

<form action = “XXX” method = ”POST”>

<input type=”hidden” name=”_method”  value=”delete”/>
</form>

最后,POST提交模式下,_method属性值会把method属性值替换掉;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值