我想创建一个servlet,允许我将图像文件从客户端上传到服务器。我正在帮助自己在apache网站上找到的教程: http://commons.apache.org/fileupload/using.html
在我的路上,我发现了一些并发症和疑惑:
问题1
我希望我的servlet使用请求中的所有值(包含图像为byte [])准备一个对象,并将其传递给将在数据库中插入所有值的@EJB。 那可能吗?你能否提供一些关于如何改进当前servlet的伪代码技巧?
@WebServlet(name="uploadServlet")
public class FileUpload extends HttpServlet {
@EJB
private DBAccessEJB ejb;
private static final long serialVersionUID = -1062753489906645120L;
// Will be triggered when a post method is sent by the user(Example: Form
// submit)
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// Check if the request is multipart
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
// Create the object that willBe passed to the EJB
Thing thing = new Thing();
if (isMultipart) {
// If it is multipart, save the items in a FileItemfactory
FileItemFactory factory = new DiskFileItemFactory();
// Create an upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
try {
// Get the files out of the request
List items = upload.parseRequest(req);
Iterator iterator = items.iterator();
while (iterator.hasNext()) {
// Get each of the items inside the items list
FileItem item = (FileItem) iterator.next();
// If the item does not come from a field
if (!item.isFormField()) {
//transform the uploaded images to byte[]
//setTheImageValues of the object
}
else {
//set the text values of the object
}
}
//Pass the prepared object to the EJB to be inserted in DB
ejb.save(thing)
} catch (FileUploadException fue) {
fue.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
问题2
我考虑过通过管理bean将请求传递给servlet,而不是从JSF页面传递,但我真的不知道该怎么做。你能给我一些提示吗?我也不知道如何以正常的方式做到这一点,从页面上看,你认为最好的方法是什么? 这就是我到目前为止对托管bean所做的事情:
public void save() {
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletRequest req = (HttpServletRequest)fc.getExternalContext().getRequest();
//我还需要将请求传递给服务器吗? }
这将位于多部分表单中的页面:
<h:commandButton value="Submit" action="myBackingBean.save"/>
问题3
在我的JSF页面中,我或多或少有10个值几乎都是字符串。我从JSF中获取它们并将它们临时存储在JSF页面中。如果servlet可以从请求中获取所有值,那么在backing bean中就不需要这个属性。你认为这种做法是一件好事吗?这是流程交易安全,还是存在风险?
答案 0 :(得分:1)
看起来您在此处使用EJB作为包含使用EJB注释注释的DAO的服务层,以使其成为会话bean。我不喜欢这种方法,你会遇到由EJB世界和HTTP请求世界的差异引起的问题。
值得注意的是,使用EJB的最大原因之一是管理事务,事务必须保持简短,大小为ms。这有很多原因,例如数据库上的锁。但是,在处理带有上传的http请求时,这不再有效。
从另一个角度来看,服务层应该代表数据库模型的抽象,并且应该从用户角度展示您可以对模型执行的操作。用户不想将图像保存到数据库,用户想要将肖像添加到他的个人资料中。
而不是
ejb.save(thing)
我更喜欢像
这样的功能profileService.addPortrait(uid, byte[] image);
这明确说明了它的作用,也满足了短交易的要求。这意味着配置文件实体可用于可能同时出现的其他请求(如某些状态图像或收件箱状态,......)
怀疑#2:
在罗马时,像罗马人一样......
首先要学习一些语言基础知识。在这种情况下,从一些教程中学习JSF。
怀疑#3:
在浏览器和JSF组件之间拦截飞行中的请求参数会破坏组件体系结构和数据隐藏原则。它还将绕过在JSF组件的服务器端部分中实现的任何安全措施和验证。
如果您使用JSF组件框架,那么只询问组件中的值而不是请求本身是有意义的。
从你的3个疑问中我觉得你有更大的疑问:我应该使用JSF吗?
如果你的雇主强制要求:搞砸了,开始上书...了解哪些问题JSF和EJB解决了这些问题并根据这些问题构建了你的工作。
如果您有自由选择:选择较轻的框架,例如Spring + Spring MVC。您将获得经验并按自己的进度遇到这些问题。
答案 1 :(得分:0)
问题1 -
你的文件肯定需要唯一标识符,但是如果按照日期/用户名等方式将文件存储在文件夹中,则会变得不那么复杂......
根据您目前所显示的内容,以下是您可以使用的基本工作流程:
客户端计算机 - &gt; FileUploadServlet(利用Apache Commons文件上传)
进入FileUploadServlet:
a)通过EJB将请求中的信息保存到数据库,包括文件名,Mime类型,信息等......
b)仍然在servlet内部,将文件上传到您的服务器,或者如果您需要,使用商业解决方案,如Amazon S3或Google Storage(通过Java API,如JetS3t)
然后,将任何必要的信息返回给客户。
问题2 -
你通过Bean请求的原因是什么,为什么不只是将Servlet作为动作,并从请求中收集信息?我不会在JSF上提供Bean的保存方法,因为这听起来不安全且未经过身份验证。
问题3 -
与上述相同,为什么存储信息,即使是暂时的,也可以在其他地方获得?