【问题标题】:Converting a servlet to JSF将 servlet 转换为 JSF
【发布时间】:2013-10-31 21:54:08
【问题描述】:

大家好,我被要求将旧的 Java EE Web 应用程序(JSP/Servlet、EJB、JPA)转换为现代 JSF 应用程序,除了 servlet 之外,我所做的最多,

当前的 servlet 是:

@WebServlet(name = "StudentServlet", urlPatterns = {"/StudentServlet"})
public class StudentServlet extends HttpServlet {
    @EJB
    private StudentDaoLocal studentDao;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String action = request.getParameter("action");
        String studentIdStr = request.getParameter("studentId");
        int studentId=0;
        if(studentIdStr!=null && !studentIdStr.equals("")){
            studentId=Integer.parseInt(studentIdStr);    
        }
        String firstname = request.getParameter("firstname");
        String lastname = request.getParameter("lastname");
        String yearLevelStr = request.getParameter("yearLevel");
        int yearLevel=0;
        if(yearLevelStr!=null && !yearLevelStr.equals("")){
            yearLevel=Integer.parseInt(yearLevelStr);
        }
        Student student = new Student(studentId, firstname, lastname, yearLevel);

        if("Add".equalsIgnoreCase(action)){
            studentDao.addStudent(student);
        }else if("Edit".equalsIgnoreCase(action)){
            studentDao.editStudent(student);
        }else if("Delete".equalsIgnoreCase(action)){
            studentDao.deleteStudent(studentId);
        }else if("Search".equalsIgnoreCase(action)){
            student = studentDao.getStudent(studentId);
        }
        request.setAttribute("student", student);
        request.setAttribute("allStudents", studentDao.getAllStudents());
        request.getRequestDispatcher("studentinfo.jsp").forward(request, response);
    }

如何将其修改为 JSF bean ?我需要添加和删除哪些部分

该应用程序是一个将学生详细信息添加到数据库的简单应用程序,它只是一些东西,因此我可以更好地了解数据库如何与 jsf 一起使用

谢谢

【问题讨论】:

    标签: jsp jsf servlets


    【解决方案1】:

    如您所见,在您的 servlet 的服务方法中,所有内容都在一处混乱:获取请求参数、转换、验证、执行逻辑和执行数据库操作。在 JSF 中有特殊的组件来执行这些任务:

    • 请求参数 (request.getParameter(...)) 的收集由 Faces Servlet 透明地完成,因此您通常根本不需要弄乱它;
    • 通过将转换器类引入特定组件 (@FacesConverter) 或使用标准组件来完成转换;
    • 通过将一个或多个验证器附加到特定组件 (@FacesValidator) 或使用标准组件来执行验证;
    • 执行逻辑是通过调用支持 bean 的方法完成的:根据组件/情况,您可以附加操作方法、操作侦听器方法、值更改侦听器方法或 ajax 侦听器方法。在您的情况下,您拥有返回导航案例结果的操作方法 (public void action(String action));
    • 执行数据库操作由注入服务(通常由@EJB 类)管理,就像在 servlet 中完成的那样。

    接下来,JSF 提供了一组 UI 组件(如 <h:inputText>),其状态绑定到一个模型,该模型又由具有已知生命周期的支持 bean(如 @ManagedBean)表示。 JSF 生命周期由六个阶段组成(这里不再赘述):

    • 恢复视图(从 HTTP 请求构建或恢复视图,包括 JSF 组件树);
    • 应用请求值(收集提交的请求参数,必要时转换它们的值并在本地以组件状态存储它们);
    • 流程验证(根据定义的规则集验证组件值);
    • 更新模型值(更新组件绑定的模型值);
    • 调用应用程序(调用方法,包括动作/动作监听器/值更改监听器/ajax监听器方法);
    • 呈现响应(呈现 HTML 并在 HTTP 响应中发送)。

    所有这些阶段都可以链接到您的 servlet 处理的操作并进行分解。我现在想添加一些关于 JSF 对应于您的经典 Servlet+JSP 组合的 cmets。

    1. String action = request.getParameter("action");

      在 JSF 中,您无需执行任何操作即可收集这些参数,因为此作业由 Faces Servlet 透明处理。

    2. studentId=Integer.parseInt(studentIdStr);

      在 JSF 中,转换(将请求参数作为字符串获取并将它们转换为其他 java 类)由 UI 组件的指定转换器处理。 JSF 有一些内置转换器(如DateTimeConverter),但您可以通过实现Converter 接口来提供自己的转换器。您可以通过指定converter 属性(如converter="myConverter")、嵌套<f:converter> 标签(<f:converter converterId="myConverter" /> 或嵌套标准标签(如<f:convertDateTime ... />)将其附加到给定组件。值得知道的是一些值会自动为您强制转换。

    3. if(studentIdStr!=null && !studentIdStr.equals(""))

      这可能是您说明创建响应需要某些请求参数的方式。在 JSF 中,您可以通过指定 UI 组件的 required 属性(如 <h:inputText required="true" />)来做到这一点。

    4. if("Add".equalsIgnoreCase(action)){ doThis(); } else { doThat() }

      执行业务方法通常在绑定到命令组件(如<h:commandButton>)的操作方法(如public String action())中完成:<h:commandButton action="#{yourBean.someAction}" />。最常见的情况是,每个命令按钮都有一个业务操作。 Action 方法是 JSF 知道的托管 bean 中的方法,但是,您可以将具体的操作传递给操作方法(例如 <h:commandButton action="#{yourBean.action('someAction)}" />public String action(String action))。

    5. studentDao.addStudent(student)

      数据库操作在操作方法中以相同的方式处理:通过在注入的服务上调用必要的方法。

    6. Student student = new Student(studentId, firstname, lastname, yearLevel)

      您通过指定 UI 输入组件的值绑定将提交的参数绑定到模型。因此,首先您要预先准备一个模型,以便在您的支持 bean 中您有一个非空的 Student student,然后您将 JSF 组件绑定到模型值(如 <h:inputText value="#{studentBean.student.studentId}" />)。这部分在noone's answer to this question中有完美的解释。

    7. request.getRequestDispatcher("studentinfo.jsp").forward(request, response);

      动作方法可以返回一个字符串。此字符串是要转发到的导航案例结果(视图 ID)。所以,这基本上等同于public void action() { ... return "studentinfo"; }。此外,request.setAttribute("student", student) 也由 JSF 在将 bean 与视图/请求/会话/应用程序相关联时透明地处理。当然,您也可以随意绑定您自己的其他对象。出于这个原因,JSF 在 EL 范围内公开了一些变量,并提供了对对象(视图/请求/会话/应用程序)的访问,以将您的参数与之关联。

    【讨论】:

    • 也很好的解释。我认为您的答案应该是公认的答案,因为它更通用,并且还涵盖了一些进一步的主题,例如验证和转换器。连同我对示例代码的回答,应该很好地涵盖了从纯 servlet 到 JSF 的转换。
    • 谢谢。这就是发布后续答案的想法。
    • @skuntsel,很好的回答人。需要更正的提示:在第一个列表的第四点和最后一个列表的第七点:当您谈论导航案例结果时,您应该使用 String 而不是 void。另外,如果您可以在答案中添加有关 JSP 的 facelets 的提示。
    • @Omar action 方法应该返回一个字符串,所以这是一个很好的发现,谢谢。第二点也值得补充!
    【解决方案2】:

    这种转变并不容易。我假设您已经拥有“基础设施”,因为这对于一篇帖子来说显然太多了。基础设施是指所有必要的库、正确配置的 web.xml 等等。

    以下内容与您的 servlet 并不完全相同,但它涵盖了基础知识,我将让您猜测如何进行编辑和搜索。

    Student 类:

    public class Student {
        private long studentId;
        private String firstName;
        private String lastName;
        // getters+setters
    }
    

    我们转换后的 servlet:

    // this is how we make the bean known to JSF
    @ManagedBean(name="studentBean")
    @ViewScoped
    public class StudentServlet implements Serializable {
        @EJB
        private StudentDaoLocal studentDao;
    
        // this object will be "automatically" filled with the values from our inputform on the xhtml page
        private Student student; // getter+setter
    
        // we have unique actions for everything... they are referenced from the xhtml page
        public String add() {
            // do your yearLevel logic here
            studentDao.addStudent(student);
    
            return "studentInfo.xhtml"; // forward to the next page
        }
    
        public String delete() {
            studentDao.deleteStudent(student.getStudentId());
    
            return "studentInfo.xhtml";
        }
    }
    

    我们需要一个用于 bean 的“GUI”的 xthml 页面,并将其命名为“student.xhtml”。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html">
    
    <h:head />
    <h:body>
    
        <h:form>
            <h:inputText value="#{studentBean.student.studentId}" />
            <h:inputText value="#{studentBean.student.firstName}" />
            <h:inputText value="#{studentBean.student.lastName}" />
            <h:commandButton value="Add" action="#{studentBean.add()}" />
            <h:commandButton value="Delete" action="#{studentBean.delete()}" />
        </h:form>
    
    </h:body>
    </html>
    

    【讨论】:

    • 你得到了一个很好的实用答案 (+1),但我决定再添加一个更通用的答案。
    猜你喜欢
    • 2012-09-27
    • 1970-01-01
    • 2019-02-23
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    相关资源
    最近更新 更多