# 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
GET /servlet/SomeName | |
HTTP/1.1 | |
Host: ... | |
Header2: ... | |
... | |
HeaderN: | |
(Blank Line) |
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
orset
and change the next letter to lowercase- Method name:
getFirstName
- Property name:
firstName
- Example:
#{customer.firstName}
- Method name:
- Exception 1: boolean properties
- If getter returns boolean or Boolean
- Method name:
getPrime
orisPrime
- Property name:
prime
- Example:
#{myNumber.prime}
- Exception 2: consecutive uppercase letters
- If two uppercase letters in a row after
get
orset
- Method name:
getURL
- Property name:
URL
(not uRL) - Example:
#{webSite.URL}
- If two uppercase letters in a row after
Method Names | Property Name | Example EL Usage |
---|---|---|
getFirstName | firstName |
|
isExecutive | executive |
|
getExecutive | executive |
|
getZIP | 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()
<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> |
@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
orweb.xml
@WebServlet("/some-address")
public class SomeServlet extends HttpServlet { … }
# Forms and Servlets
- Make a form:
<form …> … </form>
- Relative URL for
action
. Textfields needname
. Should always have submit button.
- Relative URL for
- 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 Object | Description |
---|---|
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 |
pageContext | The context for the JSP page. Provides access to various objects:
|
# EL Operators 运算符
Operator | Description |
---|---|
. | 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 div | Arithmetic: Division |
% or mod | Arithmetic: Remainder |
== or eq , != or ne | Relational: Equal and Not Equal |
< or lt , <= or le | Relational: Less Than and Less Than or Equal To |
> or gt , >= or ge | Relational: Greater Than and Greater Than or Equal |
&& or and | Logical AND |
|| or or | Logical OR |
! or not | Logical NOT |
empty | Prefix operation that can be used to determine whether a value is null or empty. |
A ? B : C | Evaluate 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
and | or | not | eq |
ne | lt | gt | le |
ge | true | false | null |
instanceof | empty | div | mod |
# EL Expression Examples
EL Expression | Result |
---|---|
${!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.
对于原型设计和快速设计很有用,也许对较小的迭代应用程序或截止日期很有用。
- 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 行
- Put 25 lines of Java code directly in the JSP page
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.
重用。您可以在多个页面中使用相同的类。
- Development. You write the separate class in a Java environment (editor or IDE), not an HTML environment
# 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 和自定义标签
- For simple dynamic code, call servlet code from scripting elements
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 是单个页面具有单个基本外观
- For complex processing, starting with JSP is awkward
# 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.
页面的格式 / 布局是高度可变的。例如:门户。
- Output is a binary type. E.g.: an image
- JSP only. Works well when:
仅 JSP。在以下情况下效果很好:- Output is mostly character data. E.g.: HTML
输出主要是字符数据。例如:HTML - Format/layout mostly fixed.
格式 / 布局大部分固定。
- Output is mostly character data. E.g.: HTML
- 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.
执行复杂的数据处理,但是布局相对固定。
- A single request will result in multiple substantially different-looking results.
# 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 用于大中型项目!
- You should strongly consider JSF 2.x for medium/large projects!
- Spring MVC
- Struts
- JSF (JavaServer Faces)
- They are not required!
它们不是必需的!- Implementing MVC with the builtin RequestDispatcher works very well for most simple and even moderately complex applications
使用内置的 RequestDispatcher 实现 MVC 对于大多数简单甚至中等复杂的应用程序都非常有效
- Implementing MVC with the builtin RequestDispatcher works very well for most simple and even moderately complex applications
- Frameworks are often useful
- 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
- You can use MVC for individual requests
# 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 类
- Ordinary Java classes with at least one
Use a servlet to handle requests
使用 Servlet 处理请求- Servlet reads request parameters, checks for missing and malformed data, calls business logic, etc.
Servlet 读取请求参数,检查丢失和格式错误的数据,调用业务逻辑等。
- Servlet reads request parameters, checks for missing and malformed data, calls business logic, etc.
Obtain bean instances
获取 bean 实例- The servlet invokes business logic (application-specific code) or data-access code to obtain the results.
Servlet 调用业务逻辑(特定于应用程序的代码)或数据访问代码以获取结果。
- The servlet invokes business logic (application-specific code) or data-access code to obtain the results.
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 的引用。
- 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.
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 方法将控制权转移到该页面。
- The servlet determines which JSP page is appropriate to the situation and uses the forward method of RequestDispatcher to transfer control to that page.
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 usesjsp:getProperty
to output the bean properties.
JSP 页面使用 jsp:useBean 和与步骤 4 的位置匹配的范围访问 bean。然后,该页面使用 jsp:getProperty 输出 bean 属性。
- The JSP page accesses beans with
- JSP 2.0 (Preferred!)
- The JSP page uses
${nameFromServlet.property}
to output bean properties
- The JSP page uses
- Either way, JSP page does not create or modify bean; it merely extracts and displays data that servlet created.
无论哪种方式,JSP 页面都不会创建或修改 bean。它仅提取并显示 servlet 创建的数据。
- JSP 1.2 (Old!)
# 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)命名服务,使组件能够查找其他组件和资源。”
- “The Java Naming and Directory Interface (JNDI) naming service enables components to locate other components and resources.”
- 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.”
“提供与其他系统(如数据库服务器和消息系统)连接的程序对象。”
- “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。”
- “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.”
- Commonly used for DataSource and Validator
常用于数据源和验证器
try{ | |
InitialContext ctx = new InitialContext(); | |
DataSource ds = (DataSource)ctx.lookup("jdbc/myDataSrc"); | |
} catch (NamingException ne) {} |
@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
,andresponse.sendRedirect
- In general, set with
# Response Codes
- Setting status codes 设置状态码
- Redirect user with
response.sendRedirect(someURL)
重定向用户使用
- Redirect user with
- 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
- Send error pages with
- 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:
- Project Name: uid-fp
- Artifact ID: uid-fp(default is fine)
- Group ID: edu.itmd4515.uid
- Version: 1.0-SNAPSHOT (default is fine)
- Use a base package for your Java code of edu.itmd4515.uid
- 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)
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 ofjakarta.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 notjakarta.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 withjavax.validation
packages because the Hibernate Validator implementation library included with Payara is using thejavax.validation
packages.Add an HTML form and a Servlet to your project.
将 HTML 表单和 Servlet 添加到您的项目。- The form should contain fields necessary to create a new instance of your entity.
该表单应包含创建实体的新实例所必需的字段。 - The form should POST to the Servlet.
该表单应该 POST 到 Servlet。 - The form should be contained within a JSP page
该表单应包含在 JSP 页面中
- The form should contain fields necessary to create a new instance of your entity.
Process the form submission in your Servlet by overriding the doPost method as demonstrated in class
通过覆盖类中演示的 doPost 方法,来处理 Servlet 中的表单提交Get the parameters of the form in your Servlet
在 Servlet 中获取表单的参数Build and validate your entity using a Validator (obtain the Validator through Resource Injection as discussed in class)
使用验证器构建和验证您的实体(如本课程中所讨论的,通过 “资源注入” 获取验证器)If the user input passes validation:
如果用户输入通过验证:- Set the validated entity as a request attribute
将经过验证的实体,设置为请求属性 - 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 目录中的确认视图。您可能需要创建此目录。 - As demonstrated in class, the confirmation view should display fields of your entity using Expression Language
确认视图应使用 “表达式语言” 显示您实体的字段。 - Document this with a description and screenshots on your wiki page. The screenshots should display your form (before) and your confirmation view (after).
用描述和屏幕截图记录下来。屏幕截图应显示表单(之前)和确认视图(之后)。
- Set the validated entity as a request attribute
If the user input does not pass validation
如果用户输入未通过验证- Forward (using RequestDispatcher) the user back to the form.
转发(使用 RequestDispatcher)将用户返回表单。 - Display appropriate error messages so they can fix their mistake(s).
显示适当的错误消息,以便他们可以纠正错误。 - Re-populate the form with data from their prior submission.
用他们先前提交的数据重新填充表单。 - 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).
用描述和屏幕截图对此进行记录。屏幕截图应显示输入错误的表单(之前)和显示错误消息的表单(之后)。
- Forward (using RequestDispatcher) the user back to the form.
Write a brief summary paragraph to document:
- Your understanding of the difference between the forward and redirect operations.
转发和重定向操作之间的区别。 - How would you be validating user submissions without the Bean Validation API standard?
如果没有 Bean Validation API 标准,您将如何验证用户提交的内容? - How do you think this approach would scale to a real application with 100's of entities?
您认为这种方法如何扩展到具有 100 个实体的真实应用程序? - Why didn't we need to include any additional dependencies (i.e. Bean Validation, JDBC) in this project?
为什么在这个项目中我们不需要包含任何其他依赖项(即 Bean 验证,JDBC)?
- Your understanding of the difference between the forward and redirect operations.
Use Sonar to analyze your code before submitting. I have created Sonar projects for everyone.
Submit to Blackboard
- Right your uid-fp project and select "Clean"
- Go to your NetBeans Projects directory. Create a zip file of the uid-fp folder and submit it to the Blackboard assignment.
Using JDBC, connect your webapp to the databse.
- 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.
- Create a Payara JDBC Resource for connectivity to your itmd4515 database. There are different way to do this:
- Adding
<data-source>
configuration to web.xml - Using a
@DataSourceDefinition
annotation - Configuring a Payara JDBC Connection Pool and JDBC Resource
- Adding
- 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 {
}
In your Servlet, obtain a DataSource using
@Resource
InjectionOnly on successful validation write the submitted entity to the database using JDBC.