Eclipse Krazo(Jakarta MVC)的使用

news2024/11/16 11:58:30

文章目录

  • 背景
  • Jakarta MVC规范
  • Eclipse Krazo
  • 使用前的思考
  • 全局配置
  • Controller示例
    • 返回View的三种写法
    • View中用到的Model如何设值?
    • View中如何获取Model中的值?
  • 参数校验
  • 防止CSRF
    • Krazo是如何实现的呢?
      • 如何生成csrf的token?
      • 如何校验csrf呢?
      • 自定义失败页面
  • 其他用法以及配置
  • 备注

背景

在N年以前,我估计在零几年?对我等95后开发者来说,可能意味着上古时代?提起MVC那时候还是Struts的时代,后来随着Spring的出现,SpringMVC开始渐渐被越来越多的开发者使用。Struts走向没落,中间还出现Vraptor,后来Struts2发布,Struts的生命彻底走到尽头。因为Spring不是Jakarta EE的规范,所以对于Jakarta EE来说一直缺少MVC规范,终于在近几年,社区开始建立MVC规范。

目前MVC框架大概是三家,SpringMVC, Struts2, Eclipse Krazo(Jakarta MVC规范的实现)。

Jakarta MVC规范

最新的规范是2.1.规范内容非常少,不复杂。建议阅读一遍规范,基本就知道怎么用了。Jakarta MVC是建立在Jakarta Restful Web Services(jakarta.ws.rs)之上的,并支持CDI

来自官方规范1.4节
Most of the terminology used in this specification is borrowed from other specifications such as Jakarta RESTful Web Services and Jakarta Contexts and Dependency Injection

关于Jakarta Restful Web Services的实现RestEasy已经在RestEasy的入门与使用这篇文章里做过详细的介绍,这里不做过多展开。

Eclipse Krazo

krazo官方网站,文档入口如下图
在这里插入图片描述
文档内容同样不多,估计几分钟就看完了。在一开始的时候,可以和上面的规范文档一起看。

使用前的思考

有使用过MVC框架的同学对MVC整体的开发流程是很清楚的,基本一个典型的业务流程是如下:

  1. 访问A页面,A.jsp/A.xhtml(jsf)。请求相应的Controller里的方法accessPageA(),将A页面用到的model设置进去,然后在A页面使用EL表达式进行取值。
  2. 进入A页面,进行一些操作,提交表单。请求相应的Controller里的submit()方法,对参数进行校验,处理业务,根据不同的结果跳转到不同的页面。

下面的例子就以这两步为例,给出一些简单的示例代码

全局配置

@ApplicationPath("mvc")
public class MvcApplication extends Application {
    
    /**
     * 配置文件 https://eclipse-ee4j.github.io/krazo/documentation/latest/index.html#_properties_default_view_file_extension_org_eclipse_krazo_defaultviewfileextension
     * @return
     */
    @Override
    public Map<String, Object> getProperties() {
        final Map<String, Object> properties = new HashMap<>();
        // 设置页面(View)文件夹
        properties.put(ViewEngine.DEFAULT_VIEW_FOLDER, "/WEB-INF/views/");
        properties.put(Properties.DEFAULT_VIEW_FILE_EXTENSION, "jsp");
        // 设置form表单的method属性,允许除了get和post之外的其他请求
        properties.put(FormMethodOverwriter.FORM_METHOD_OVERWRITE, Options.ENABLED);
        properties.put(FormMethodOverwriter.HIDDEN_FIELD_NAME, FormMethodOverwriter.DEFAULT_HIDDEN_FIELD_NAME);
        return properties;
    }
}

Controller示例

主要注解就是@Controller, 注意这里我的注解是放在class上的,代表该类下所有的方法都是返回到页面(View)。如果你只需要某个方法返回页面,其他方法是Restful的,那么只需要把Controller注解放到相应的方法上即可。

@RequestScoped
@Controller
@Path("test")
public class MvcController {

    @Inject
    private Models models;
    
    /**
     * 获得校验结果
     */
    @Inject
    private BindingResult bindingResult;

    @GET
    @Path("helloMvc/{path}")
    public Response helloMvc(@PathParam("path") String path) {
        models.put("message", "Hello MVC, " + path);
        return Response.ok("helloMvc.jsp").build();
    }
    
    @DELETE
    @Path("deleteMvc")
    public String deleteMvc(@FormParam("message") @MvcBinding @NotBlank String message) {
        if (bindingResult.isFailed()) {
            models.put("errors", bindingResult.getAllMessages());
            return "deleteMvcResult.jsp";
        }
        models.put("message", message);
        return "deleteMvcResult.jsp";
    }
    
    @POST
    @Path("csrf")
    @CsrfProtected
    @View("csrf.jsp")
    public void csrf() {
        models.put("message", "csrf");
    }
}

返回View的三种写法

如上述代码所示

  1. 通过Response对象设置页面路径
  2. 返回String,String内容是页面路径
  3. 使用@View注解,注解内容是页面路径

View中用到的Model如何设值?

This specification supports two kinds of models: the first is based on CDI @Named beans, and the second on the Models interface which defines a map between names and objects. Jakarta MVC provides view engines for Jakarta Server Pages and Facelets out of the box, which support both types.

官方文档提供了Model设值两种方式,这里示例代码使用Models这个接口,直接通过CDI注入进来。

View中如何获取Model中的值?

以JSP为例,可以使用EL表达式或者request.getAttribute()方法

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--jstl 3.0的uri已经改变了--%>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
    <title>helloMvc</title>
</head>
<body>
<div>
    这是返回给页面的信息:${message}<br>
    这是使用jstl标签库的信息:<c:out value="${message}"/><br>
<%--    https://jakarta.ee/specifications/mvc/2.1/jakarta-mvc-spec-2.1.html#view_engines--%>
    这是使用request.getAttribute()方法获取的信息:<%=request.getAttribute("message")%><br>
</div>
<div>
    <form action="${pageContext.request.contextPath}/mvc/test/deleteMvc" method="POST">
        <input type="hidden" name="_method" value="DELETE"/>
        <input type="text" name="message" value="${message}"/>
        <input type="submit" value="提交"/>
    </form>
</div>
<div>
    <form action="${pageContext.request.contextPath}/mvc/test/csrf" method="post">
<%--       https://jakarta.ee/specifications/mvc/2.1/jakarta-mvc-spec-2.1.html#mvc_context --%>
        <input type="hidden" name="${mvc.csrf.name}" value="${mvc.csrf.token}"/>
        <input type="submit" value="测试csrf"/>
    </form>
</div>
</body>
</html>

为什么request.getAttribute能够获取到model的值呢?这是因为规范要求,实现此规范时,需要将model通过setAttribute的方式设置进去
在这里插入图片描述
在Krazo源码ServletViewEngine中也可以看到这一步
在这里插入图片描述

参数校验

使用@MvcBinding注解.使用方法如上述代码所示,关于各种校验注解可以直接使用Jakarta Bean Validation 相关注解。如果想要了解更多可以参考Hibernate-Validator使用这篇博文。

当校验失败时,我们这里的处理方式是,把校验失败的信息放到errors中,并返回一个页面,在页面中展示。

防止CSRF

要集成防止CSRF攻击,官方也提供了具体的规范要求和实现。如上述代码所示,只要在表单里添加一个隐藏域,隐藏域的name和value是EL表达式,在进入JSP页面时,通过EL表达式获得token,和在后端方法上加上@CsrfProtected注解即可

Krazo是如何实现的呢?

如何生成csrf的token?

上述所述,

${mvc.csrf.name}和${mvc.csrf.token}

这两个EL表达式完成了name和value的生成.关键源码如下
入口点是CsrfProtectFilter
在这里插入图片描述
最终放到session里。

这里你可能会疑惑,为什么这里的EL表达式是mvc呢,那是因为
规范规定
在这里插入图片描述
规范实现
在这里插入图片描述

如何校验csrf呢?

入口点是CsrfValidateFilter
在这里插入图片描述
在这里插入图片描述
很简单,就是去session里拿一下,验证一下。如果校验不通过则抛出异常

自定义失败页面

虽然官方提供了一个默认的实现CsrfExceptionMapper,但是我们想CSRF校验失败时,自己控制跳到自己项目里的页面

@Provider
@Priority(Priorities.USER)
public class MvcExceptionHandler implements ExceptionMapper<CsrfValidationException> {
    
    @Context
    private HttpServletResponse response;
    
    @Context
    public HttpServletRequest request;
    
    @Context
    private ServletContext servletContext;
    
    @SneakyThrows
    @Override
    public Response toResponse(final CsrfValidationException e) {
        request.setAttribute("errors", e.getMessage());
//        两种写法都可以
//        servletContext.getRequestDispatcher("/WEB-INF/views/csrf.jsp").forward(request, response);
        request.getServletContext().getRequestDispatcher("/WEB-INF/views/csrf.jsp").forward(request, response);
        return null;
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
    <title>csrf</title>
</head>
<body>
<c:if test="${not empty errors}">
    csrf校验失败:<br>
    <ul>
        <c:forEach items="${errors}" var="error">
            <li>${error}</li>
        </c:forEach>
    </ul>
    <br>
</c:if>
<c:if test="${not empty message}">
    ${message} 校验成功
</c:if>
</body>
</html>

其他用法以及配置

关于本篇博文中没有提到的其他配置以及用法,可以参考Krazo官方文档 Configuration一节

备注

  • 示例代码仓库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/656938.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开源赋能,决胜未来 — 参加原子全球开源峰会有感

目录 文章目录 目录前言开源决胜未来&#xff1a;闭源摧毁 UNIX&#xff0c;开源成就 Linux开源创新&#xff1a;软硬件协同&#xff0c;共建开源生态 前言 开源原子基金会作为国内首家开源基金会组织&#xff0c;由其主办的首届 “开放原子全球开源峰会” 也是第一次被冠以 “…

干货文:Mac 中 .bash_profile 和 .zshrc 的区别

如果你想在 Mac OS 中配置 MySQL 的环境变量&#xff0c;在 .zshrc 文件中添加如下内容&#xff1a; # 设置 mysql 的路径 export MYSQL_HOME/usr/local/mysql/bin# 将 MYSQL_HOME 添加到 PATH 中 export PATH$HOME/bin:/usr/local/bin:$MYSQL_HOME:$PATH# 解决需要 source 才…

硬件【9】详解二极管钳位电路

文章目录 1 概述1.1 正向钳位电路1.2 偏置正向钳位电路 1 概述 在之前的 二极管限幅电路 一文中&#xff0c;我们学习了二极管限幅电路&#xff0c;该电路可以削掉一部分信号&#xff0c;但不会影响剩余信号。今天&#xff0c;我们将学习另一种基于二极管的电路&#xff0c;该…

搭建环境【2】windows主机和ubuntu互传文件的4种方法

我的ubuntu系统是安装在 VMware 虚拟机中的&#xff0c;两者之间经常要互传文件&#xff0c;下面介绍4种常用的互传文件方法。 1. 共享文件夹方式互传 在虚拟机中需要开启共享文件夹的功能。首先虚拟机中的ubuntu要求是已经开机了的状态&#xff0c;然后进行设置&#xff1a;…

Vue2封装一个全局通知组件并发布到NPM

✍&#x1f3fc;作者&#xff1a;周棋洛&#xff0c;计算机学生 ♉星座&#xff1a;金牛座 &#x1f3e0;主页&#xff1a;点击查看更多 &#x1f310;关键&#xff1a;vue2 组件封装 npm发包 文章目录 1. 前言 &#x1f343;2. 我为什么要封装通知插件 ❓3. 初始化vue空项目 &…

B047-cms02-高级查询 删除 添加 修改

目录 高级查询页面准备下拉框显示文章类型ArticleController用jstl和el表达式取值展示 高级查询参数ArticleQuery 高级查询页面发送请求导入jquery.jdirk.js在jquery下引用绑定按钮发送请求高级查询sql 绑定删除事件绑定事件拿到标签id值准备模态框来自xmind弹出删除模态框绑定…

matlab不显示子图刻度并调整子图间距

matlab中在使用subplot函数画图时&#xff0c;尤其是做emd分解查看IMF时&#xff0c; 正常画图的代码及结果如下&#xff1a; figure for i 1:size(imf_norm,1)subplot(7,1,i)plot(imf_norm(i,:))ylabel(IMFstring(i)) end其中imf_norm为分解得到的imfs 效果图&#xff1a; …

python里apply用法_Python apply函数的用法

Python编程语言Python 是一种面向对象、解释型计算机程序设计语言&#xff0c;由Guido van Rossum于1989年底发明&#xff0c;第一个公开发行版发行于1991年。Python语法简洁而清晰&#xff0c;具有丰富和强大的类库。它常被昵称为胶水语言&#xff0c;它能够把用其他语言制作的…

HDL抽象等级 仿真模型 网表 delay speicfy与sdf

1.HDL 硬件描述语言 抽象分级 HDL这里主要说verilog 在描述硬件电路时分为三个抽象级别 行为级模型&#xff1a;主要用于test bench&#xff0c;着重系统行为和算法&#xff0c;不在于电路实现&#xff0c;不可综合&#xff08;常用描述有initial&#xff0c;fork/join&#…

【MYSQL】MYSQL应用环境,系统特征,储存引擎,应用框架和索引功能的详细讲解

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

DINO-DETR匈牙利匹配与加噪过程学习记录

今天再来回顾一下DINO中匈牙利匹配与损失函数部分&#xff0c;该部分大致与DETR相似&#xff0c;却又略有不同。 为了查看数据方便&#xff0c;博主将num_query改为20&#xff0c;max_select值也为20。 匈牙利匹配过程 首先是数据送入匈牙利匹配中进行标签匹配过程了。 获取…

qt.qpa.plugin: Could not load the Qt platform plugin “xcb“ in

兄弟们看看是不是这个错&#xff1a; QObject::moveToThread: Current thread (0xe5205f0) is not the objects thread (0xa14d0f0). Cannot move to target thread (0xe5205f0)qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/xxx/python3.…

Esp32+Blynk实现云端控制LED开灭

目录 环境配置依赖库安装blynk 基础设置 GPIO 点灯实验 环境配置 依赖库安装 参考 blynk 官方快速上手文档 如果要使用 blynk 提供的环境&#xff0c;我们就必须安装对应的库 选择基于 blynk 且适用于 ESP32 的库并安装到 arduino 上&#xff1a; blynk 基础设置 进入官网并且…

Question1:harbor登录成功,推送镜像失败

denied: requested access to the resource is denied 解决方案 查看用户的权限 Harbor 用户角色权限速查 系统级角色&#xff1a; Harbor 系统管理员&#xff1a;“Harbor 系统管理员”拥有最多的权限。除了上述权限外&#xff0c;“Harbor 系统管理员”还可以列出所有项目、…

一种令人拍案叫绝的 ChatGPT 攻击手段!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 最近看到一个非常巧妙的 ChatGPT 攻击手段&#xff0c;跟大家分享一下&#xff0c;也算是做个提醒。 不论你是否懂技术&#xff0c;我都建议你了解一下这种攻击手段&#xff0c;有备无患。…

Golang的trace性能分析

文章目录 一、trace概述二、trace的使用方式代码中trace采集通过pprof采集 三、trace分析细节trace的web界面trace中需要关注的关注GC的频率关注goroutine调度情况关注goroutine的数量理想情况 四、GC分析当前服务GC情况设置GOGC设置GOMEMLIMITGC阈值的讨论GC的特点 五、gorout…

【每日挠头算法题(8)】最后一个单词的长度|重新排列字符串

文章目录 一、最后一个单词的长度思路1&#xff1a;从后往前遍历具体代码如下&#xff1a; 思路2&#xff1a;具体代码如下&#xff1a; 二、重新排列字符串思路具体代码如下&#xff1a; 一、最后一个单词的长度 点我直达~ 思路1&#xff1a;从后往前遍历 从后往前遍历&…

Stable DiffusionAI绘画一键启动整合包

点击"仙网攻城狮”关注我们哦~ 不当想研发的渗透人不是好运维 让我们每天进步一点点 简介 搞了个Stable DiffusionAI绘画整合包&#xff0c;里面有二次元风格、3D风格、真人模型&#xff0c;需要的后台回复“AI绘画”即可获取下载链接,放几个用SD生成的图。 实战 1.下载好…

调用万维易源API实现图像性别转换

目录 1、作者介绍2、调用万维易源API2.1 API介绍2.2 API调用过程 3、代码实现3.1 实现步骤3.2 完整代码 4、问题与分析 1、作者介绍 梁随欣&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研究生 研究方向&#xff1a;模式识别与人工智能 电子邮箱&…

【Java技术专题】「入门到精通系列教程」深入探索Java特性中并发编程体系的原理和实战开发指南( 线程基础技术专题)

深入探索Java特性中并发编程体系的原理和实战开发指南 并发编程介绍什么是并发编程并发编程的好处是什么并发编程的挑战是什么并发编程模型有哪些如何学习并发编程本系列专题文章大全 实战原理计算的问题简单的方法&#xff1a;更快的CPU来遍历靠谱的方法&#xff1a;分而治之来…