【问题标题】:how to update a bean from user input如何从用户输入更新 bean
【发布时间】:2015-12-17 10:30:48
【问题描述】:

我的基本问题是关于 JavaEE、JSP 和 JSTL,如何获取用户更新的信息来更新控制器端的 bean(即在 serlvet 中)?

我对 Web 应用程序相当陌生,并且我已经阅读了几种不同的方法,但我觉得我的方法确实过时了,或者有一些我忽略的重大缺陷。我的解决方案如下:

我的特定 bean 是一个具有 taskID、标题和说明属性的任务 bean。它实际上还有更多属性,但为了这个问题,我将其缩小了。

public class Task {
    private int taskID;
    private String title;
    private String instructions;

    constructor here...

    getters and setters defined here...

在 servlet 中,我从 DAO 获取 bean 并将其放入请求中:

Task task = dao.getTaskByID(taskID);
request.setAttribute("task", task);

在 JSP 页面中,我为 bean 属性设置了相应的输入,使用了 taskID 的隐藏输入。用户查看数据,对其进行更改并提交:

<form action="./UpdateTask" method="POST">
    <input type="hidden" name="taskID" value="${task.taskID }">
    <input type="text" id="taskTitle" name="taskTitle" value="${task.title }">
    <input type="text" id="taskInstructions" name="taskInstructions" value="${task.instructions}">
    <button type="submit">Submit</button>
</form>

回到控制器,我从请求中获取所有参数并使用更新的数据构建一个 bean,然后将其发送回 DAO 以在数据库中更新。

int taskID = Integer.parseInt(request.getParameter("taskID));
String title = request.getParameter("taskTitle");
String instructions = request.getParameter("taskInstructions");

Task updatedTask = new Task(taskID, title, instructions);

dao.updateTaskInfo(updatedTask );

有几个具体问题:

  • 我是否误解了 JSTL 和 bean 是如何一起使用的?
  • 有没有办法只从请求中获取整个 bean 而不必像我一样重建它?
  • 如果我最终从请求数据重建 bean,如果我不想向用户公开某些属性值(例如外键 ID)怎么办?

我知道询问最佳做法是不受欢迎的,所以我并不是在要求“最佳”方式,而只是要求我所描述的是一种偏离标准做法的非正统方式。或者,如果有什么我没有做的事情会让它变得更简单,或者更符合当前的做法。

我还考虑将任务 bean 设为会话变量以维护对象的状态,然后在请求后从会话中取回它并更新可能根据用户输入更改的字段,但我担心并发问题用这种方法。

感谢您的帮助。 SO在帮助新手方面非常出色。那里的信息太多了,而且变化如此之快,肯定会让人不知所措地想知道要学习什么方法。

【问题讨论】:

    标签: java jsp jakarta-ee web-applications jstl


    【解决方案1】:

    我是不是误解了 JSTL 和 bean 是如何一起使用的?

    除了XSS attack hole,你做得很好,因为这是一个“普通的”JSP/Servlet Web 应用程序。

    您刚刚意识到这一切都是样板代码。需要收集请求参数、转换和验证它们、更新模型值和调用业务逻辑的代码。您几乎可以在每个“普通的普通”servlet 中看到这一点。你需要一遍又一遍地重复同样的代码逻辑。

    这正是 JSF、Spring MVC、Wicket、Play!、Struts 等 MVC 框架存在的原因。它们提供了一个单一的“控制器”servlet/过滤器,它接管了(大部分)样板代码,因此您最终可以只得到一个 JSP 或 Facelets 文件作为“视图”,一个 Javabean 类作为“模型”。根据 MVC 框架的性质,它将为您透明地更新引用的实体(如您的示例中的Task),使用转换后的、经过验证的和/或原始提交的值。


    有没有办法只从请求中获取整个 bean 而不必像我一样重建它?

    我还考虑过将任务 bean 设为会话变量以维护对象的状态,然后在请求后从会话中取回它并更新可能根据用户输入更改的字段,但我担心关于这种方法的并发问题。

    当最终用户在多个浏览器选项卡/窗口中打开相同的视图时,将其放在会话范围内确实可能会导致麻烦。例如,Java EE 的 MVC 框架 JSF 提供了“视图范围”,只要您在第一次初始化支持 bean 的表单上回发,它就可以保持支持 bean 的活动。 JSF 中的“主从”示例可以在此问答中找到:Creating master-detail pages for entities, how to link them and which bean scope to choose


    如果我最终从请求数据重建 bean,如果我不想向用户公开某些属性值(例如外键 ID)怎么办?

    您将始终需要传递一些标识符,例如 taskID 在您的 dao.getTaskByID(taskID) 示例中。系统还应该如何知道最终用户想要查看/编辑哪个实体?您只不需要传递所有其他标识符或未使用的属性。您只需使用 taskID 从 DAO 获取 Task 实体,然后更新其属性,而不是从头开始重新创建 Task

    【讨论】:

    • 哇,这是一个绝妙的答案。谢谢。我没有使用框架,因为我想很好地学习基础知识,我想我是!您的最后评论是我正在考虑做的事情,但担心会导致过多的 DOA 调用。很高兴知道它不是,所以我会这样做!将 taskID 存储在隐藏输入中是从请求中获取它的标准还是有更安全的方法?
    • 如果您担心“数据库调用过多”,那么问题应该通过后端的 DB 和 DAO 之间的二级实体缓存来解决,而不是通过在前端的所有会话中复制实体来解决。 Java EE 的 ORM 框架 JPA 支持这一点。回到基础知识(我总是支持先学习基础知识,这样你会更好地理解为什么所有这些抽象框架存在;)),我可以假设你很了解我们的 servlets wiki 页面stackoverflow.com/tags/servlets/info 和这个关于幂等性的问答stackoverflow.com/q/2349633?如果没有,也通过它们。
    • 我没有那些参考资料,它们很棒。我不知道 XSS 攻击。非常有帮助。回复:将 taskID 存储在隐藏的输入中;可以吗?我在那些页面上没有看到任何关于此的内容。我现在就不再打扰你了:)再次感谢!
    • 答案取决于您首先获得任务 ID 的方式(对于 dao.getTaskByID(taskID))。如果它已经像 /edittask?taskID=42 这样作为 URL 查询字符串参数传递,那么混淆隐藏的输入值是没有意义的。最终用户已经知道确切的值。
    • 对。我应该澄清一下。我将从使用用户 ID 的查询中获取 taskID,因此他们永远不会看到它。我想我要求更多地概括如何最安全地处理暴露的 id。对于这个特定的示例,taskID 可能不需要太多保护,但我认为在安全方面犯错并且不公开 id 并没有什么坏处。好的,我真的不再打扰你了!你的时间非常慷慨。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    • 1970-01-01
    相关资源
    最近更新 更多