我想创建一个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而不是从JSF页面将请求传递给servlet,但我真的不知道该怎么做。你能给我一些提示吗?我也不知道如何以正常的方式来做,从页面上看,你认为什么是最好的方式?到目前为止,这就是我对托管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可以从请求中获取所有值,那么在backingbean中就不需要这些属性了。你认为这样做是件好事吗?这将是流程交易的安全性,还是存在任何风险?
怀疑#1:
看起来您在这里使用EJB作为服务层,其中包含用EJB注释注释的DAO,使其成为会话bean。我不喜欢这种方法,您会遇到EJB世界和HTTP请求世界的差异所引起的问题。
需要注意的是,使用EJB的最大原因之一是管理事务,并且事务必须保持短时间(以毫秒为单位)。这有很多原因,例如数据库上的锁。但是,当处理带有上载的http请求时,这将不再有效。
从另一个角度来看,服务层应该表示数据库模型的抽象,并且应该从用户的角度展示您可以对模型做什么。用户不想将图像保存到数据库中,用户想将肖像添加到他的个人资料中。
而不是
ejb.save(thing)
我更喜欢这样的功能
profileService.addPortrait(uid, byte[] image);
这明确说明了它的作用,也满足了短交易的要求。这意味着配置文件实体可用于其他可能同时出现的请求(如某些状态图像或收件箱状态…)
怀疑#2:
入乡随俗…
从学习一些基本的语言开始。在本例中,从一些教程中学习JSF。
怀疑#3:
拦截浏览器和JSF组件之间的请求参数会破坏组件架构和数据隐藏原则。它还将绕过JSF组件的服务器端部分中实现的任何安全措施和验证。
如果您使用JSF组件框架,那么只从组件而不是从请求本身询问值是有意义的。
从你的三个疑虑中,我觉得你有一个更大的疑虑:我应该使用JSF吗?
如果这是你的雇主强制要求的:接受它,开始记录。。。了解JSF和EJB解决了哪些问题,并根据这些问题构建工作框架。
如果你可以自由选择:选择一个更轻的框架,例如Spring+SpringMVC。你会积累经验,并按照自己的节奏遇到这些问题。
问题1-
当然,你的文件需要唯一标识符,但如果你按照日期/用户名等将文件存储在文件夹中,这就不那么复杂了
以下是您可以使用的程序的基本工作流程,基于您迄今为止所展示的内容:
客户端计算机->FileUploadServlet(利用Apache Commons文件上传)
一旦进入FileUploadServlet:
a) 通过EJB将请求中的信息保存到数据库中,包括文件名、Mime类型、信息等
b) 当仍然在servlet中时,将文件上传到服务器,或者如果需要,使用商业解决方案,如Amazon S3或Google Storage(通过Java API,如JetS3t)
之后,将任何必要的信息返回给客户。
问题2-
您通过Bean请求的理由是什么?为什么不让Servlet作为操作,并从请求中收集信息呢?我不会让Bean的保存方法在JSF上可用,因为这听起来不安全并且没有经过身份验证。
问题3-
和上面一样,当信息在其他地方可用时,为什么要存储信息,即使是暂时的?