280 likes | 527 Views
MVC for Servlets. MVC. One of the most common Design Patterns is Model-View-Controller ( MVC ) The model does all the computational work It is input/output free All communication with the model is via methods The controller tells the model what to do User input goes to the controller
E N D
MVC • One of the most common Design Patterns is Model-View-Controller (MVC) • The model does all the computational work • It is input/output free • All communication with the model is via methods • The controller tells the model what to do • User input goes to the controller • The view shows results; it is a “window” into the model • The view can get results from the controller, or • The view can get results directly from the model
MVC for servlets • The model, as usual, does all the computational work, and no I/O • The model can consist of multiple classes • The servlet class (the one that extends HttpServlet) acts as the controller • The servlet gives any relevant information from the user request to the model • The servlet takes the results and passes them on to the view • The view—that is, the HTML page that is returned to the user—is frequently created by JSP
Web applications • A web application typically consists of: • Some (Java) class, acting as the controller, that extends HttpServlet • The model code (also Java) • The view code (ultimately Java, but we write it as JSP) • Plus, of course, the web.xml file • All these parts need to communicate with one another • That’s what the rest of this lecture is (mostly) about
Servlet life-cycle methods • public void init() • Called after the servlet is constructed but before the servlet is placed into service • As the name implies, a good place to do initializations • public void service(ServletRequest request, ServletResponse response) • Called when a servlet request is made • The HttpServletservice method will dispatch the request to doGet, doPost, or one of the other service methods • public void destroy() • Called when a servlet is terminated • Can be used to clean up any resources (files, databases, threads, etc.)
ServletConfig • You can overridepublic void init() • Servlet has the methods: • public ServletConfig getServletConfig() • You will probably use this if you override init() • public String getServletInfo() • By default, returns an empty string; override to make it useful • The main purpose of ServletConfig is to provide initialization information to the servlet • ServletConfig has these methods: • public java.lang.String getServletName() • public ServletContext getServletContext() • public Enumeration getInitParameterNames() • public String getInitParameter(String name) • Our interest will be in getting initialization parameters
Servlet init parameters • Where does a servlet get its initialization information? • From the web.xml file, of course! • Inside <servlet>: • <init-param> <param-name>myName</param-name> <param-value>myValue</param-value></init-param> • In the servlet code: • String myValue = getServletConfig().getInitParameter("myName");
Multiple servlets • A web application can consist of multiple servlets • We just saw how to send configuration information to a single servlet • Context init parameters can send configuration information to all servlets in a web application • Not inside a particular <servlet> tag: • <context-param> <param-name>myName</param-name> <param-value>myValue</param-value></context-param> • In any servlet: • String myValue = getServletContext().getInitParameter("myName");
Servlet init parameters are: Defined within a <servlet> tag Written within an<init-param> tag Retrieved from a ServletConfig object, which you get by calling getServletConfig() Read from the ServletConfig object by calling getInitParameter(name) Context init parameters are: Defined outside all <servlet> tags Written within a<context-param> tag Retrieved from a ServletContext object, which you get by calling getServletContext() Read from the ServletContext object by calling getInitParameter(name) Servlet vs. context init parameters
Public ServletContext methods • String getInitParameter(String name) • Enumeration getInitParameterNames() • Object getAttribute(String name) • Enumeration getAttributeNames() • void setAttribute(String name, Object object) • void removeAttribute(String name) • String getRealPath(String path) • RequestDispatcher getRequestDispatcher(String path)
The ServletRequest object • You’ve seen these methods of the ServletRequest object: • public Enumeration getParameterNames() • public String getParameter(String name) • public String[] getParameterValues(String name) • ServletRequest also has these methods: • public Enumeration getAttributeNames() • public Object getAttribute(String name) • public void setAttribute(String name, Object object) • You can use attributes to send information to the JSP
Dispatching to the JSP • request.setAttribute(name, object) • Notice that we put the information on the request • RequestDispatcher view = request.getRequestDispatcher("result.jsp"); • We ask the request object for a dispatcher • We supply, as a String, a path to the JSP file • If the path begins with a slash, it is relative to the current context root • Otherwise, it is relative to the servlet location • view.forward(request, response); • Having added the result information to the HttpRequest object, we forward the whole thing to the JSP • The JSP does the rest—it will send out the HTML page
Aside: redirect vs. forward • The previous slide showed how a servlet could forward a request to JSP (or to another servlet) • This is all done on the server side • response.sendRedirect(URL) sends a response back to the browser that says, in effect, “I can’t handle this request; you should go to this URL instead.” • You cannot use this method if you have already written something to the response • The URL can be relative to the location of this servlet
Parameters are not attributes • You can get parameters from the Deployment Descriptor: • getServletConfig().getInitParameter(name); • getServletContext().getInitParameter(name); • You cannot set these parameters • You can get request parameters • request.getParameter(String name) • Parameter values are always Strings • Attribute values are always Objects • When you get an attribute, you have to cast it to the type you want
Attribute scopes • Servlets can access three scopes: • Application scope • All servlets in the web application have access • Attributes are stored in the ServletContext object • Available for the lifetime of the servlet • Session scope • Available to servlets that have access to this specific session • Attributes are stored in the HttpSession object • Available for the life of the session • Request scope • Available to servlets that have access to this specific request • Attributes are stored in the ServletRequest object • Available for the life of the request (until your doGet or doPost method completes)
Attribute methods • ServletContext objects, ServletRequest objects, and HttpSession objects all have the following methods: • Object getAttribute(String name) • void setAttribute(String name, Object object) • void removeAttribute(String name) • Enumeration getAttributeNames()
Thread safety • Thread problems can occur when: • One Thread is writing to (modifying) an object at the same time another Thread is reading it • Two (or more) Threads are trying to write to the same object at the same time • Thread problems cannot (in general) be detected by the Java runtime system • Instead, thread problems cause random, mysterious, non-replicable corruption of data • There are simple steps that you can take to avoid many threading problems • However, threading is very error-prone and can be extremely difficult to ensure that you have it right
Thread safety in servlets • Tomcat starts a new Thread for every new request • Each request, and therefore each Thread, has its own request and response objects • Therefore, these are inherently Thread-safe • Local variables (including parameters) of your service methods are also thread-safe • Instance variables are not thread-safe • You don’t have multiple servlet objects—you have multiple Threads using the same servlet object • Application (context) scope is shared by all servlets • Therefore, context attributes are inherently Thread-unsafe • Session attributes are not completely Thread-safe • It is possible to have multiple simultaneous requests from the same session
Thread safety in class assignments • In reality, the servlets you write for this course are not going to service thousands of requests per second • You (and my TA) will enter a few requests manually, with billions of nanoseconds in between • You are not going to have threading problems • However... • I’m trying to teach “real world” programming • Therefore, you have to pretend that thread safety is a real issue in your programming assignments • If I had lots of spare time (which I don’t!), I could write a program to send your servlet thousands of requests per second • Even if I did that, my program could not reliably catch problems • Bottom line: Try your best to make your servlets thread-safe, even though we can’t test them for thread safety
Protecting context attributes • To protect context attributes, synchronize on the ServletContext object • Example (from Head First Servlets & JSP):synchronized(getServletContext()) { getServletContext().setAttribute("foo", "22"); getServletContext().setAttribute("bar", "42"); out.println(getServletContext().getAttribute("foo")); out.println(getServletContext().getAttribute("bar"));} • This will protect you from any other code that also synchronizes on the ServletContext • It will not protect you from code that doesn’t so synchronize • But this is the best we can do
Protecting session attributes • To protect session attributes, synchronize on the HttpSession object • Example (from Head First Servlets & JSP):HttpSession session = request.getSession();synchronized(session) { session.setAttribute("foo", "22"); session.setAttribute("bar", "42"); out.println(session.getAttribute("foo")); out.println(session.getAttribute("bar"));} • This will protect you from any other code that also synchronizes on the HttpSession
Getting init parameters in JSP • You can get servlet and context init parameters in your JSP • Step 1: Specify in your DD that you want them: • <servlet> <servlet-name>SomeServletName</servlet-name> <jsp-file>/UseServletInit.jsp</jsp-file> <init-param> ... </init-param> <init-param> ... </init-param> ...</servlet> • Step 2: Override jspInit() (must be done in a JSP declaration): • <%! public void jspInit() {// use getServletConfig() and getServletContext() as usual }%>
PageContext • In JSP, pageContext is an implicit object (like request and response) of type PageContext • PageContext has these methods (among others): • Object getAttribute(String name) // uses page scope • Object getAttribute(String name, int scope) • Enumeration getAttributeNamesInScope(int scope) • Object findAttribute(String name) • Searches in the order: page context, request scope, session scope, application scope • void setAttribute(String name, Object value) • void setAttribute(String name, Object value, int scope) • Where scope can be one of PageContext.APPLICATION_SCOPE, PageContext.PAGE_SCOPE, PageContext.REQUEST_SCOPE, or PageContext.SESSION_SCOPE • So you can access a lot of information from a PageContext object!