# Notes

# Servlet

  • Let - suffix. Diminutive suffix. Smaller. 后缀。较小的后缀。小一点。
  • Little Server, Part of a Server, Server-like 小服务器,服务器的一部分,类似服务器
  • Servlets: Smaller - yes. Lesser - no!

# HttpServlet

  • Read explicit data sent by client (such as form data, request parameters)
    读取客户端发送的显式数据(例如表单数据,请求参数)
  • Read implicit data sent by client (such as request headers)
    读取客户端发送的隐式数据(例如请求标头)
  • Invoke other services and generate results
    读取客户端发送的隐式数据(例如请求标头)
  • Send explicit data back to client (HTML, etc)
    将明确的数据发送回客户端(HTML 等)
  • Send the implicit data to client (such as status codes and response headers)
    将隐式数据发送到客户端(例如状态码和响应头)

# A Typical HTTP Request 典型的 HTTP 请求

GET /search-servlet?keywords=servlets+jsp HTTP/1.1
Accept: image/gif, image/jpg, */*
Accept-Encoding: gzip
Connection: Keep-Alive
Cookie: userID=id456578
Host: www.somebookstore.com
Referer: http://www.somebookstore.com/findbooks.html
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.0)

# HTTP Request/Response

Request
GET /servlet/SomeName
HTTP/1.1
Host: ...
Header2: ...
...
HeaderN:
(Blank Line)
Response
HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
(Blank Line)
<!DOCTYPE ...>
<HTML>
<HEAD>...</HEAD>
<BODY>
...
</BODY></HTML>

# A Servlet That Generates Plain Text

生成纯文本的 Servlet

package testPackage; // Always use packages.
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;
@WebServlet("/hello")
public class HelloWorld extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("Hello World");
    }
}

# Interpreting HelloWorld Servlet

@WebServlet("/address")
This is the URL relative to your context path
这是相对路径的 URL
doGet
Code for an HTTP GET request. doPost also common.
HTTP GET 请求的代码。 doPost 也很常见。
HttpServletRequest
Contains anything that comes from the browser
包含来自浏览器的所有内容
HttpServletResponse
Used to send stuff to the browser. Most common is getWriter for a PrintWriter that points at browser.
用于向浏览器发送内容。最常见的是指向浏览器的 PrintWriter 的 getWriter。
@Override
General best practice when overriding inherited methods
覆盖继承方法时的常规最佳方式

# IDE Generated Servlet and JSP

  • NetBeans Scaffolding 脚手架
  • processRequest() method
  • Time-saver!
    • Scaffolding: Trust, but Verify
    • Note - try-with-resources

# POJO (JavaBean) Conventions and EL 约定

  • Java Classes

    Non-public fields:
    private String myVariable
    Non-private accessors:
    public String getMyVariable()
    Non-private mutators:
    public void setMyVariable(String myVar)
  • EL (given an instance of MyClass named myClass)
    ${myClass.myVariable}

What matters is the method name, not the variable name 重要的是方法名称,而不是变量名称

Here is the usual rule to turn a method into property: 以下是将方法转换为属性的常用规则

  • Drop the word get or set and change the next letter to lowercase
    • Method name: getFirstName
    • Property name: firstName
    • Example: #{customer.firstName}
  • Exception 1: boolean properties
    • If getter returns boolean or Boolean
    • Method name: getPrime or isPrime
    • Property name: prime
    • Example: #{myNumber.prime}
  • Exception 2: consecutive uppercase letters
    • If two uppercase letters in a row after get or set
    • Method name: getURL
    • Property name: URL (not uRL)
    • Example: #{webSite.URL}
Method NamesProperty NameExample EL Usage

getFirstName
setFirstName

firstName

${customer.firstName}

isExecutive
setExecutive
(boolean property)

executive

${customer.executive}

getExecutive
setExecutive
(boolean property)

executive

${customer.executive}

getZIP
setZIP

ZIP

${address.ZIP}

# Servlet as Controller

# Redirect

  • Stops processing of the request and sends HTTP status code for redirect.
  • Browser URL becomes that which you redirect
    to
  • Can be any URL
  • Client (browser) initiates a new request

# Forward

  • Passes the control of the request to another servlet or JSP
  • Includes the request and response objects
  • Client browser is unaware
  • URL does not change in client
  • URL is relative to web application context
  • Forward vs Include
    • http://docs.oracle.com/javaee/7/tutorial/servlets007.htm#BNAGI

# Reading Form Data in Servlets

request.getParameter("name")
  • Returns URL-decoded value of first occurrence of name in query string
  • Works identically for GET and POST requests
  • Returns null if no such parameter is in query data
request.getParameterValues("name")
Returns an array of the URL-decoded values of all occurrences of name in query string (or null)
request.getParameterNames()
or request.getParameterMap()
Example HTML - Form Params
<FORM ACTION="three-params">
First Parameter: <INPUT TYPE="TEXT" NAME="param1"><BR>
Second Parameter: <INPUT TYPE="TEXT" NAME="param2"><BR>
Third Parameter: <INPUT TYPE="TEXT" NAME="param3"><BR>
<CENTER><INPUT TYPE="SUBMIT"></CENTER>
</FORM>
Example Servlet - Form Params
@WebServlet("/three-params")
public class ThreeParams extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        out.println(docType +
        "<HTML>\n" +
        "<HEAD><TITLE>"+title + "</TITLE></HEAD>\n" +
        "<BODY BGCOLOR=\"#FDF5E6\">\n" +
        "<H1 ALIGN=\"CENTER\">" + title + "</H1>\n" +
        "<UL>\n" +
        " <LI><B>param1</B>: "
        + request.getParameter("param1") + "\n" +
        " <LI><B>param2</B>: "
        + request.getParameter("param2") + "\n" +
        " <LI><B>param3</B>: "
        + request.getParameter("param3") + "\n" +
        "</UL>\n" +
        "</BODY></HTML>");
    }
}

# Validation

Check for missing
  • If Field missing in form, getParameter returns null
- If Field blank when form is submitted, getParameter returns an empty string or possibly a String with whitespace depending on browser
- Must check for null before empty string!
Check for malformed
Value is present but in the wrong format

# Best Practices

  • Users do crazy things. Some are malicious. 有些是恶意的
  • Client-side vs Server-side vs Both
  • Assume user input will be bad
  • Avoid showing stack traces to users. Stack traces belong in logs. 避免向用户显示堆栈跟踪。堆栈跟踪属于日志。
    • Use default values or suggestions on forms
    • Re-display original form with submitted values and error messages. Previously entered values shouldn’t be lost
    • Show standard error pages for users, not system internals
  • Without Validation standards, it may be necessary to check for null values (for example):
    if ((param == null) || (param.trim().equals(""))) {
        doSomethingForMissingValues(...);
    } else {
        doSomethingWithParameter(param);
    }

# Web Validation

  • HTML5 Validation
  • Client-side vs Server-side vs Both
  • What do we do in the ”real world?”

Good? Bad? Ugly?

# Summary

# Servlet Basics

  • Main servlet code goes in doGet or doPost:
    • The HttpServletRequest contains the incoming information
    • The HttpServletResponse lets you set outgoing information
  • Give address with @WebServlet or web.xml
    • @WebServlet("/some-address")
    • public class SomeServlet extends HttpServlet { … }

# Forms and Servlets

  • Make a form: <form …> … </form>
    • Relative URL for action . Textfields need name . Should always have submit button.
  • Read data: request.getParameter("name")
    • Results in value as entered into form, not necessarily as sent over network. I.e., not URLencoded.
  • Check for missing or malformed data

# Scopes

Page Scope
Only available on the same page 仅在同一页面上可用
Request Scope
Interaction in a single request 单个请求中的交互
Session Scope
Interaction across multiple requests 多个请求之间的交互
Application Scope
Shared state across all interactions within a web application Web 应用程序中所有交互的共享状态

# Session Handling 会话处理

  • Use session scope judiciously 明智地使用会话范围
  • Use request scope liberally 自由地使用请求范围
  • Session identifier travels across network, not the session itself 会话标识符跨网络传播,而不是会话本身
  • Methods
    • request.getSession
    • session.getAttribute
    • session.setAttribute

# Java Server Pages

With servlets, it is easy to

  • Read form data
  • Read HTTP request headers
  • Set HTTP status codes and response headers
  • Use cookies and sessions
  • Share data among servlets
  • Remember data between requests

But, it sure is a pain to

  • Use those println statements to generate HTML
  • Maintain HTML and collaborate with Web Designers

Entire JSP page gets translated into a servlet (once), and servlet is what actually gets invoked (for each request) 整个 JSP 页面被翻译成一个 servlet(一次),而 servlet 是实际被调用的(对于每个请求)

Ideas:

  • Use regular HTML for most of page
  • Mark servlet code with special tags

Example:

<HTML>
<HEAD>
    <TITLE>Order Confirmation</TITLE>
    <LINK REL=STYLESHEET HREF="JSP-Styles.css" TYPE="text/css">
</HEAD>
<BODY>
    <H2>Order Confirmation</H2>
    Thanks for ordering
    <I><%= request.getParameter("title") %></I>!
</BODY></HTML>

# Benefits of Java Server Pages

Although JSP technically can’t do anything servlets can’t do, JSP makes it easier to:

  • Write HTML
  • Read and maintain the HTML

JSP makes it possible to:

  • Use standard HTML tools
  • Have different members of your team do the HTML layout than do the Java programming

JSP encourages you to Separate the (Java) code that creates the content from the (HTML) code that presents it

# JSP Syntax (Old Style) 语法

Still Used:

  • @taglib
  • @include
  • @page

Legacy - Don’t use on new code:

  • JSP Comment <%-- Comment --%>
  • JSP Expressions <%= expression %>
  • JSP Scriptlets <% code %>
  • JSP Declarations <%! code %>

# JSTL and EL

https://github.com/eclipse-ee4j/jsp-api
https://github.com/eclipse-ee4j/jstl-api

  • EL (Expression Language) can be accessed anywhere via ${expression} EL 表达式
  • Familiar implicit objects 熟悉的隐式对象

# EL Implicit Objects 隐式对象

Implicit ObjectDescription

pageScope

Maps page-scoped variable names to their values
将页面范围的变量名映射为其值

requestScope

Maps request-scoped variable names to their values
将请求范围的变量名映射为其值

sessionScope

Maps session-scoped variable names to their values
将会话范围的变量名映射为其值

applicationScope

Maps application-scoped variable names to their values
将应用程序范围的变量名映射为其值

param

Maps a request parameter name to a single value
将请求参数名映射到单个值

paramValues

Maps a request parameter name to an array of values
将请求参数名映射到值数组

header

Maps a request header name to a single value
将请求头名映射到单个值

headerValues

Maps a request header name to an array of values
将请求头名映射到值数组

cookie

Maps a cookie name to a single cookie
将 cookie 名映射到单个 cookie

pageContext

The context for the JSP page. Provides access to various objects:
JSP 页面的内容环境。提供对各种对象的访问:

  • servletContext: The context for the application’s servlet and web components
    应用程序的 servlet 和 Web 组件的内容环境
  • session: The session object for the client
    客户端的会话对象
  • request: The request triggering the execution of the JSP
    该请求触发 JSP 的执行
  • response: The response returned by the JSP page
    JSP 页面返回的响应

# EL Operators 运算符

OperatorDescription
.Access a bean property or Map entry
[]Access an array or List element, or Map entry () Group an expression
+Arithmetic: Addition
-Arithmetic: Subtraction or negation
*Arithmetic: Multiplication
/ or divArithmetic: Division
% or modArithmetic: Remainder
== or eq , != or neRelational: Equal and Not Equal
< or lt , <= or leRelational: Less Than and Less Than or Equal To
> or gt , >= or geRelational: Greater Than and Greater Than or Equal
&& or andLogical AND
|| or orLogical OR
! or notLogical NOT
emptyPrefix operation that can be used to determine whether a value is null or empty.
A ? B : CEvaluate B or C, depending on the result of the evaluation of A

# dot v brace 大括号中的点

${bean.map.myKey}
Resolves to bean.getMap().get("myKey");
${bean.map["myKey"]}
Resolves to bean.getMap().get("myKey");
${bean.map["my.dotted.key"]}
Resolves to bean.getMap().get("my.dotted.key");
${bean.map[bean2.someField]}
Resolves to bean.getMap().get(bean2.getSomeField());

# EL Reserved Words

andornoteq
neltgtle
getruefalsenull
instanceofemptydivmod

# EL Expression Examples

EL ExpressionResult
${!empty param.Add}False if the request parameter named Add is null or an empty string.
${pageContext.request.contextPath}The context path.
${sessionScope.cart.numberOfItems}Value of the numberOfItems property of the session-scoped attribute named cart.
${param['mycom.productId']}The value of the request parameter named mycom.productId.
${param.customerNumber}
${header["host"]} or ${header.host}The host header
${requestScope.customer}The request scoped customer bean
${header["user-agent"]}
${customer.customerNumber}

# JSTL Tag Libraries 标签库

  • Used in combination with EL
  • Replacements for older style JSP syntax 替换旧式 JSP 语法
    • Core (Variable support, flow control, URL management)
    • Formatting (Formatting and I18N)
    • SQL (Database)
    • Functions (String manipulation, Collection length)
    • XML (XML parsing and transformation)
    • https://github.com/eclipse-ee4j/jstl-api
    • http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/
    • http://docs.oracle.com/javaee/5/jstl/1.1/docs/api/

# Summary

  • Be familiar with older JSP syntax due to legacy code in the marketplace
  • For new JSP work, use EL and JSTL, but once we learn JSF you may prefer that
  • Careful with SQL and XML tags 小心使用 SQL 和 XML 标签
    • Useful for prototyping and rapid design, and perhaps for smaller, iterative applications or deadlines.
      对于原型设计和快速设计很有用,也许对较小的迭代应用程序或截止日期很有用。

# MVC

  • Model (POJO/JavaBean)
  • View (JSP/JSTL)
  • Controller (Servlets)

# Limit Code in Presentation Layer 在应用层中限制代码

  • You have two options

    • Put 25 lines of Java code directly in the JSP page
      将 25 行 Java 代码直接放在 JSP 页面中
    • Put those 25 lines in a separate Java class and put 1 line in the JSP page that invokes it
      将这 25 行放在单独的 Java 类中,并在调用它的 JSP 页面中放入 1 行
  • Why is the second option much better?
    为什么第二种选择更好?

    • Development. You write the separate class in a Java environment (editor or IDE), not an HTML environment
      开发。您在 Java 环境(编辑器或 IDE)而不是 HTML 环境中编写单独的类
    • Debugging. If you have syntax errors, you see them immediately at compile time. Simple print statements can be seen.
      调试。如果您有语法错误,则在编译时会立即看到它们。可以看到简单的打印语句。
    • Testing. You can write a test routine with a loop that does 10,000 tests and reapply it after each change.
      测试。您可以编写一个具有 10,000 个测试的循环的测试例程,并在每次更改后重新应用它。
    • Reuse. You can use the same class from multiple pages.
      重用。您可以在多个页面中使用相同的类。

# Why Combine Servlets and JSP? 为什么要结合 Servlet 和 JSP?

  • Typical picture: use JSP to make it easier to develop and maintain the HTML content
    使用 JSP 使开发和维护 HTML 内容更加容易

    • For simple dynamic code, call servlet code from scripting elements
      对于简单的动态代码,请从脚本元素中调用 servlet 代码
    • For slightly more complex applications, use custom classes called from scripting elements
      对于稍微复杂的应用程序,请使用从脚本元素调用的自定义类
    • For moderately complex applications, use beans and custom tags
      对于中等复杂的应用程序,请使用 beans 和自定义标签
  • But, that’s not enough

    • For complex processing, starting with JSP is awkward
      对于复杂的处理,以 JSP 开头很尴尬
    • Despite the ease of separating the real code into separate classes, beans, and custom tags, the assumption behind JSP is that a single page gives a single basic look
      尽管可以轻松地将实际代码分为单独的类、beans 和自定义标签,但后面的假设 JSP 是单个页面具有单个基本外观

# Possibilities for Handling Request 处理请求的可能方式

  • Servlet only. Works well when:
    仅 Servlet。在以下情况下效果很好:
    • Output is a binary type. E.g.: an image
      输出是二进制类型。例如:一张图片
    • There is no output. E.g.: you are doing forwarding or redirection as in Search Engine example.
      没有输出。例如:您正在按照搜索引擎示例进行转发或重定向。
    • Format/layout of page is highly variable. E.g.: portal.
      页面的格式 / 布局是高度可变的。例如:门户。
  • JSP only. Works well when:
    仅 JSP。在以下情况下效果很好:
    • Output is mostly character data. E.g.: HTML
      输出主要是字符数据。例如:HTML
    • Format/layout mostly fixed.
      格式 / 布局大部分固定。
  • Combination (MVC architecture). Needed when:
    组合(MVC 体系结构)。在以下情况下需要:
    • A single request will result in multiple substantially different-looking results.
      单个请求将导致多个外观完全不同的结果。
    • You have a large development team with different team members doing the Web development and the business logic.
      一个庞大的开发团队,由不同的团队成员进行 Web 开发和业务逻辑。
    • You perform complicated data processing, but have a relatively fixed layout.
      执行复杂的数据处理,但是布局相对固定。

# MVC Misconceptions MVC 的误解

  • An elaborate framework is necessary
    一个详尽的框架是必要的
    • Frameworks are often useful
      框架通常很有用
      • JSF (JavaServer Faces)
        • You should strongly consider JSF 2.x for medium/large projects!
          您应该强烈考虑将 JSF 2.x 用于大中型项目!
      • Spring MVC
      • Struts
    • They are not required!
      它们不是必需的!
      • Implementing MVC with the builtin RequestDispatcher works very well for most simple and even moderately complex applications
        使用内置的 RequestDispatcher 实现 MVC 对于大多数简单甚至中等复杂的应用程序都非常有效
  • MVC totally changes your system design
    MVC 完全改变了您的系统设计
    • You can use MVC for individual requests
      您可以将 MVC 用于单个请求
    • Think of it as the MVC approach, not the MVC architecture
      将其视为 MVC 方法,而不是 MVC 体系结构
      • Also called the Model 2 approach

# MVC Flow of Control MVC 控制流程

# Implement MVC with RequestDispatcher 使用 RequestDispatcher 实施 MVC

  • Define beans to represent result data
    定义 beans 代表结果数据

    • Ordinary Java classes with at least one getBlah method
      具有至少一个 getBlah 方法的普通 Java 类
  • Use a servlet to handle requests
    使用 Servlet 处理请求

    • Servlet reads request parameters, checks for missing and malformed data, calls business logic, etc.
      Servlet 读取请求参数,检查丢失和格式错误的数据,调用业务逻辑等。
  • Obtain bean instances
    获取 bean 实例

    • The servlet invokes business logic (application-specific code) or data-access code to obtain the results.
      Servlet 调用业务逻辑(特定于应用程序的代码)或数据访问代码以获取结果。
  • Store the bean in the request, session, or servlet context
    将 bean 存储在请求、会话或 servlet 环境中

    • The servlet calls setAttribute on the request, session, or servlet context objects to store a reference to the beans that represent the results of the request.
      Servlet 在请求、会话或 Servlet 环境对象上调用 setAttribute,以存储对表示请求结果的 bean 的引用。
  • Forward the request to a JSP page.
    将请求转发到 JSP 页面。

    • The servlet determines which JSP page is appropriate to the situation and uses the forward method of RequestDispatcher to transfer control to that page.
      Servlet 确定哪个 JSP 页面适合于这种情况,并使用 RequestDispatcher 的 forward 方法将控制权转移到该页面。
  • Extract the data from the beans.
    从 beans 中提取数据。

    • JSP 1.2 (Old!)
      • The JSP page accesses beans with jsp:useBean and a scope matching the location of step 4. The page then uses jsp:getProperty to output the bean properties.
        JSP 页面使用 jsp:useBean 和与步骤 4 的位置匹配的范围访问 bean。然后,该页面使用 jsp:getProperty 输出 bean 属性。
    • JSP 2.0 (Preferred!)
      • The JSP page uses ${nameFromServlet.property} to output bean properties
    • Either way, JSP page does not create or modify bean; it merely extracts and displays data that servlet created.
      无论哪种方式,JSP 页面都不会创建或修改 bean。它仅提取并显示 servlet 创建的数据。

# Error Pages

  • Can be done in a standard way for Java web applications with web.xml
    可以使用 web.xml,以标准方式完成 Java Web 应用程序
  • Bad practice to leave application server default error pages - and can introduce security concerns by exposing too much information about your application logic
    不当做法:保留服务器的默认错误页面 —— 可能通过暴露有关应用程序逻辑的过多信息,而引起安全问题

# More Platform Basics 更多平台基础

# JNDI and Resources

  • JNDI as defined by Java EE Tutorial:
    Java EE 教程定义的 JNDI:
    • “The Java Naming and Directory Interface (JNDI) naming service enables components to locate other components and resources.”
      “Java 命名和目录接口(JNDI)命名服务,使组件能够查找其他组件和资源。”
  • Resources, as defined by Java EE Tutorial:
    Java EE 教程定义的资源:
    • “A program object that provides connections to other systems, such as database servers and messaging systems.”
      “提供与其他系统(如数据库服务器和消息系统)连接的程序对象。”

Resources are identified by a unique and human friendly name called the JNDI name (i.e. jdbc/MyDataSource)
资源通过唯一且人性化的名称(称为 JNDI 名称)进行标识(即 jdbc / MyDataSource)

# JDBC Resource

  • Connection Pool 连接池
  • JDBC Resource
  • Creation Options 创建选项
    • NetBeans
    • glassfish-resources.xml
    • Glassfish Admin GUI
    • asadmin

# Injection 注入

  • Allows us to obtain references to resources without having to instantiate them directly.
    允许我们获得对资源的引用,而不必直接实例化它们。
  • Declare the required resources via annotations (Injection Points)
    通过注解(注入点)声明所需的资源
  • Container provides the required resources at runtime, and manages their lifecycle based on our specified scope
    容器在运行时提供所需的资源,并根据我们指定的范围管理其生命周期
  • Java EE Platform provides 2 types:
    • Resource Injection 资源注入
    • Dependency Injection 依赖注入

# Resource Injection

  • As defined in the Java EE Tutorial:
    • “Resource injection enables you to inject any resource available in the JNDI namespace into any container-managed object, such as a servlet, an enterprise bean, or a managed bean.”
      “资源注入使您能够将 JNDI 命名空间中任何可用的资源,注入到任何容器管理的对象中,例如 servlet、企业 bean 或托管 bean。”
  • Commonly used for DataSource and Validator
    常用于数据源和验证器
Java EE 5 Way
try{
    InitialContext ctx = new InitialContext();
    DataSource ds = (DataSource)ctx.lookup("jdbc/myDataSrc");
} catch (NamingException ne) {}
Java EE 7+ Way
@Resource(lookup="jdbc/myDataSource")
DataSource myDs;

# Servlet HTTP

# Request Headers

  • Use request.getHeader for arbitrary header 任意头
    • Remember to check for null 记得检查是否为空
    • Cookies, authorization info, content length, and content type have shortcut methods
      Cookies,授权信息,内容长度和内容类型具有快捷方式

# Response Headers

  • Setting response headers 设置响应头
    • In general, set with response.setHeader
    • In special cases, set with response.setContentType , response.setContentLength , response.addCookie ,and response.sendRedirect

# Response Codes

  • Setting status codes 设置状态码
    • Redirect user with response.sendRedirect(someURL) 重定向用户使用
  • If you insert user-supplied data into the URL, encode with URLEncoder.encode
    将用户提供的数据插入 URL,请使用 URLEncoder.encode
    • Send error pages with sendError 发送错误页面
    • In general, set via response.setStatus
  • Some sample status codes 一些常用状态码
    • 200 (default)
    • 302 (forwarding; set with sendRedirect ) 转发
    • 401 (unauthorized and needs authenticaton) 未经授权且需要认证
    • 403 (forbidden) 禁止
    • 404 (not found; set with sendError ) 页面未找到

# Links

Mozilla Developer Network

  • MDN - Your first HTML form
  • MDN - HTTP request methods
  • MDN - What is a URL?
  • MDN - Creating hyperlinks
  • MDN - HTTP headers
  • MDN - Response codes

# Lab

# Summary

The purpose of this assignment is to learn the basics of an MVC style approach using JSP/Servlet, and to become familiar with these technologies in order to compare their use to later frameworks.

# Requirements

# Documentation

Create a wiki page in your personal space titled Lab 4.

# Database Setup

Use your sample database and itmd4515 user from Lab 3 - Junit, JDBC and Bean Validation.

# Project Setup

Create a Java with Maven Web Application project in NetBeans with the following coordinates and configuration:

  1. Project Name: uid-fp
  2. Artifact ID: uid-fp(default is fine)
  3. Group ID: edu.itmd4515.uid
  4. Version: 1.0-SNAPSHOT (default is fine)
  5. Use a base package for your Java code of edu.itmd4515.uid
  6. Under Server, choose Payara Server and Java EE 8 Web

Accept the Lab 4 assignment to create your GitHub repository and configure your projects for source control as documented in Lab 2 - Setup and Introductory Webapp.

Deviating from the package convention given above will mean that you can not benefit from Sonar and other automated tools, and I will not be able to fix this. Please follow the specification!

We will be working in this repository from now until the end of the semester.  Please remember, I will be looking for multiple commits.  I would suggest using the lab number in your commit message as a prefix so you can also review the history throughout the semester, for example:

  • Lab 4 - Initial Commit
  • Lab 4 - POJO implementation and HTML form
  • Lab 4 - Servlet MVC Controller
  • Lab 4 - Fixed the Servlet MVC Controller RequestDispatcher logic
  • Lab 4 - Finishing touches (comments, javadoc, code style)

# Project Requirements

Implement the following within your uid-fp project:

Make sure you are following standard Java naming conventions. Please review the following if you are not sure what those naming conventions are:
确保您遵循标准的 Java 命名约定。如果您不确定这些命名约定是什么,请查看以下内容:

  • Java 8 Pocket Guide by Patricia Liguori, Robert Liguori - Chapter 1. Naming Conventions
  • Code Conventions for the Java Programming Language - 9 Naming Conventions (dated, but still correct)
  1. Use your POJO from Lab 3 - Junit, JDBC and Bean Validation for the following requirements.  Enhance it by adding or refining fields as needed.

    Important - Refactor your POJO from Lab 3 to use javax.validation packages instead of jakarta.validation packages.

    This can be as simple as changing the import statements and substituting javax for jakarta on those import lines.  For your new code in Lab 4, make sure to use javax.validation and not jakarta.validation imports.  As I mentioned in the earlier weeks, there is much still changing in the Jakarta Enterprise landscape.  Many packages will be shifting from their old namespaces to new jakarta namespaces, and things like Payara need time to "catch up" with all this change.

    Lab 3 worked fine with jakarta.validation packages because it was running outside Payara.  Lab 4 will only work with javax.validation packages because the Hibernate Validator implementation library included with Payara is using the javax.validation packages.

  2. Add an HTML form and a Servlet to your project.
    将 HTML 表单和 Servlet 添加到您的项目。

    1. The form should contain fields necessary to create a new instance of your entity.
      该表单应包含创建实体的新实例所必需的字段。
    2. The form should POST to the Servlet.
      该表单应该 POST 到 Servlet。
    3. The form should be contained within a JSP page
      该表单应包含在 JSP 页面中
  3. Process the form submission in your Servlet by overriding the doPost method as demonstrated in class
    通过覆盖类中演示的 doPost 方法,来处理 Servlet 中的表单提交

    1. Get the parameters of the form in your Servlet
      在 Servlet 中获取表单的参数

    2. Build and validate your entity using a Validator (obtain the Validator through Resource Injection as discussed in class)
      使用验证器构建和验证您的实体(如本课程中所讨论的,通过 “资源注入” 获取验证器)

    3. If the user input passes validation:
      如果用户输入通过验证:

      1. Set the validated entity as a request attribute
        将经过验证的实体,设置为请求属性
      2. Forward (using RequestDispatcher) the user to a confirmation view in the WEB-INF/views directory of your project.  You may need to create this directory.
        转发(使用 RequestDispatcher),将用户转到项目的 WEB-INF /views 目录中的确认视图。您可能需要创建此目录。
      3. As demonstrated in class, the confirmation view should display fields of your entity using Expression Language
        确认视图应使用 “表达式语言” 显示您实体的字段。
      4. Document this with a description and screenshots on your wiki page.  The screenshots should display your form (before) and your confirmation view (after).
        用描述和屏幕截图记录下来。屏幕截图应显示表单(之前)和确认视图(之后)。
    4. If the user input does not pass validation
      如果用户输入未通过验证

      1. Forward (using RequestDispatcher) the user back to the form.
        转发(使用 RequestDispatcher)将用户返回表单。
      2. Display appropriate error messages so they can fix their mistake(s).
        显示适当的错误消息,以便他们可以纠正错误。
      3. Re-populate the form with data from their prior submission.
        用他们先前提交的数据重新填充表单。
      4. Document this with a description and screenshots on your wiki page.  The screenshots should display your form with bad input (before) and your form with error messages (after).
        用描述和屏幕截图对此进行记录。屏幕截图应显示输入错误的表单(之前)和显示错误消息的表单(之后)。
  4. Write a brief summary paragraph to document:

    1. Your understanding of the difference between the forward and redirect operations.
      转发和重定向操作之间的区别。
    2. How would you be validating user submissions without the Bean Validation API standard?
      如果没有 Bean Validation API 标准,您将如何验证用户提交的内容?
    3. How do you think this approach would scale to a real application with 100's of entities?
      您认为这种方法如何扩展到具有 100 个实体的真实应用程序?
    4. Why didn't we need to include any additional dependencies (i.e. Bean Validation, JDBC) in this project?
      为什么在这个项目中我们不需要包含任何其他依赖项(即 Bean 验证,JDBC)?
  5. Use Sonar to analyze your code before submitting.  I have created Sonar projects for everyone.

  6. Submit to Blackboard

    1. Right your uid-fp project and select "Clean"
    2. Go to your NetBeans Projects directory.  Create a zip file of the uid-fp folder and submit it to the Blackboard assignment.
  7. Using JDBC, connect your webapp to the databse.

    1. Make sure you add the MySQL JDBC driver to your pom.xml.  Refer back to Lab 3 (or the lecture) if you don't remember how to do this.
    2. Create a Payara JDBC Resource for connectivity to your itmd4515 database.  There are different way to do this:
      1. Adding <data-source> configuration to web.xml
      2. Using a @DataSourceDefinition annotation
      3. Configuring a Payara JDBC Connection Pool and JDBC Resource
    3. Ensure that Payara has access to the JDBC driver for MySQL at runtime.  Which of the above options require us to do "extra steps" as system or application administrators to handle this?
    Code
    import javax.annotation.sql.DataSourceDefinition;
    import javax.enterprise.context.ApplicationScoped;
    @ApplicationScoped
    @DataSourceDefinition(
            name = "java:app/jdbc/itmd4515DS",
            className = "com.mysql.cj.jdbc.MysqlDataSource",
            serverName = "localhost",
            portNumber = 3306,
            databaseName = "Chinook",
            user = "itmd4515",
            password = "itmd4515",
            properties = {
                "zeroDateTimeBehavior=CONVERT_TO_NULL",
                "useSSL=false",
                "serverTimezone=America/Chicago"            
            }
    )
    public class Lab4DbConfig {
        
    }
  8. In your Servlet, obtain a DataSource using @Resource Injection

  9. Only on successful validation write the submitted entity to the database using JDBC.