<memo>Servlet

#Servlet:
* Servlets are a component of the JEE framework used for web development.
* Web container: Manages the execution of web pages, servlets, and some EJB components for Java EE applications. We can use Tomcat as Web container.

Servlets by normally extends `javax.servlet.http.HttpServlet` class, which is a sub class of `javax.servlet.GenericServlet` class

**flow:**

* Create a directory structure under Tomcat for your application.
* Write the servlet source code. You need to import the `javax.servlet` package and the `javax.servlet.http` package in your source file.
* Compile your source code.
* Create a deployment descriptor.
* Run Tomcat.
* Call your servlet from a web browser.

##three ways of creating a servlet
* implement “Servlet” interface 

```
//Servlet life cycle: the entire process from its creation till the destruction
public class ServletDemo1 implements Servlet {

    //public ServletDemo1(){}

     //The init method is called only once. It is called only when the servlet is created, and not called for any user requests afterward. So, it is used for one-time initializations, just as with the init method of applets.
    public void init(ServletConfig arg0) throws ServletException {
                System.out.println("=======init=========");
        }

    //The service() method is the main method to perform the actual task. The servlet container (i.e. web server) calls the service() method to handle requests coming from the client( browsers) and to write the formatted response back to the client.
    public void service(ServletRequest arg0, ServletResponse arg1)
            throws ServletException, IOException {
        System.out.println("hehe");

    }

    //The destroy() method is called only once at the end of the life cycle of a servlet.
    public void destroy() {
        System.out.println("******destroy**********");
    }
//servlet which would be destroyed when the tomcat stopped
    public ServletConfig getServletConfig() {
        return null;
    }

    public String getServletInfo() {
        return null;
    }
}
```

* inherit “GenericServlet” class

```
public class ServletDemo2 extends GenericServlet {
    @Override
    public void service(ServletRequest arg0, ServletResponse arg1)
            throws ServletException, IOException {
        System.out.println("heihei");
    }
}
```

* inherit “HttpServlet” method (most widely used)

```
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("haha");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("ee");
        doGet(req,resp);
    }
}
```


**Two top interfaces: Servlet and ServletConfig**
**Servlet provides five methods, three of them are life cycle methods, the other two are normal methods.**

**GenericServlet is an abstract class. It implement Servlet. It auto-implement init(),service(),destroy(). You should rewrite service() to deal with requests.**

**HttpServlet is an abstract class. It inherits and capsulate GenericServlet. Because it extends HTTP, so it also needs to use HttpServletRequest and HttpServletResponse, which are subclasses of ServletRequest and ServletResponse. HttpServlet also add doPost() and doGet() in service()
Customized Servlet usually inherit HttpServlet.**




##three ways to access servlet:
* input URL into the address bar to call doGet()
* hyperlink, refer servlet url in href to call doGet()
* submit a form, refer servlet URL in action, you can call either doGet() or doPost() in the form’s method



##servlet gets requests:
doXXX() methods have two parameters: HttpServletRequest and HttpServletResponse. 
Both are interfaces. We use a web container to create entity classes, which means when we access a servlet, tomcat creates request object and response object and passes them to doXXX() methods.
The type of entity class is the HttpServletRequest interface.

Methods of catching request data:
* getParameter: get value by name
* getParameterValues: get all values by name(checkbox or multi-select)
* getRemoteAddr: get client ip address
Those methods return string or string[], so type conversion is often needed: Integer.parseInt, Double.parseDouble, Timestamp.valueOf

example:

```
//single value
String username=request.getParameter("username(content of input text)");
String age=request.getParameter("age(content of input text)");
//multi values：same name
<input type="checkbox" name="fav" value="0"/>sing
<input type="checkbox" name="fav" value="1"/>dance
<input type="checkbox" name="fav" value="2"/>writing
String[] favs=request.getParameterValues("fav");
syso(favs[0]+favs[1]),
//when it comes to index, isnull validation is needed
```

##two ways of jumping:
* response redirect:
`Response.sendRedirect(String path);`
send a new request to the target resource to generate a new response
get()
data from the current request can not be passed to the target resource
data lost
URL changed

* request dispatcher:
`request.getRequestDispatcher.(String path).forward(request，response);`
data from current request can be passed to target resource
data not lost
follow the method, get() or post()
url not changed


#Configuration
##Servlet Config:
you should configure Servlet before accessing it.
you should reboot tomcat after modifying web.xml
web.xml location: webcontent/webinf/web.xml
web.xml can not be renamed

```web.xml
//<url-pattern> is path to access to Servlet
<servlet>
<servlet-name>user-defined registered servlet, unique in web.xml</servlet-name>
<servlet-class>Servlet class full name, the name of the entity class you make</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ditto</servlet-name>
<url-pattern>/user-defined logic address, must begin with "/"</url-pattern>
</servlet-mapping>
```


###using wildcard to configure  servlet:
* \*.suffix

```
<servlet-mapping>
<servlet-name>servlete name</servlet-name>
<url-pattern>*.jsp</url-pattern> 
</servlet-mapping>
//recognize java1first/abc.jsp
```

* /start, /*end

```
<servlet-mapping>
<servlet-name>servlete name</servlet-name>
<url-pattern>/action/*</url-pattern>
</servlet-mapping>
```
**priority:
accurate path>longest path>\*.do
“abc/\*.do” is wrong!**





##ServletConfig methods:

* `getInitParameter()`
* `getServletContext()`

ServletConfig can get init methods, they are config parameters written in `web.xml`
Those parameters can be acquired by `getInitParameter()`
ServletConfig defined `getInitParameter()` to get servlet init parameters.

```
<servlet>
<servlet-name>TestExtendsServlet</servlet-name>
<servlet-class>com.zhangxicompany.servlet.TestExtendsServlet</servlet-class>
<init-param>
<param-name>version</param-name>
<param-value>6.0</param-value>
</init-param>
</servlet>
</servlet>
```


you can make servlet init when you run the tomcat by modifying web.xml

```
<servlet>
<load-on-startup>1</load-on-startup>
</servlet>
note:"1" is not amount, "1" is order
//<init-param>should write before <load-on-startup>
```




##Context:
every web project is deployed under tomcat.
when running the tomcat, the tomcat will create an object for every application, this object is a context object.
one application can only have one context object, it is created and saved in the container.
the context object is like a global variable, it works over the whole application.
we can use context objects to complete data sharing during multi-users.

ServletContext is an interface, can not be created by "new".
getInitParameter is not a servlet init parameter but the tomcat start to init parameter
it is like an application in JSP.

#####example of login number account:

```loginservlet.
//this refers to ServletConfig
ServletContext sc=this.getServletContext()
Object countstr=sc.getAttribute("count");
int count=0;
if(countstr!=null){
 Integer.parseInt(countstr.toString())
}
count++;
sc.setAttribute("",count);
```

```loginsucess.jsp:
welcome!! you are the &{applicationScope.count}!!
```


###Context configuration:
get servlet parameters by ServletConfig: getInitParameter
get context parameters by ServletContext: getInitParameter

```web.xml：
<context-param>
<param-name>level</para-name>
<param-value>100</param-value>
</context-param>
```

```
//get ServletContext in servlet class：
sc.getInitParameter("level")；
```
```xxx.jsp
<%=application.getInitParameter("level”"%>
```





##Listener:
a listener is used for listening for an event. some kind of operation may trigger some kind of event, such as to run or destroy a container, create or destroy a session. 
When an event happened, the container will create a corresponding object.

###6 types of events:
* ServletContextEvent:  
context event, when context object is changed(created or destroyed), it trigged the context event.
* ServletContextAttributeEvent:  
context attribute event, triggered when context attributed is modified
* ServletRequestEvent:  
request event, triggered when request object is changed(created or destroyed)
* ServletRequestAttributeEvent:  
request attribute event, triggered when request attribute is modified
*  HttpSessionEvent:  
session event, trigged when session object is changed(session created or destroyed or activated, deactivated)
* HttpSessionBindingEvent:  
session binding event, triggered when session attribute is modified

###8 types of listener:
* ServletContextListener:  
context listener, listen for ServletContextEvent
* ServletContextAttributeListener:  
context attribute listener, listen for ServletContextAttributeEvent
* ServletRequestListener:  
request listener, listen for ServletRequestEvent
* ServletRequestAttributeListener:  
request attribute listener, listen for ServletRequestAttributeEvent
* HttpSessionListener:  
session listener, listen for HttpSessionEvent
* HttpSessionActivationListener:  
session activation listener, listen for HttpSessionEvent
* HttpSessionAttributeListener:  
session attribute listener, listen for HttpSessionBindingEvent
* HttpSessionBindingListener:  
session binding listener, listen for HttpSessionBindingEvent

###event and listener:
container create events according to a trigger condition, such as ServletContextEvent will be triggered when run or close a container, and the container will create an object according to the event.
when the event is triggered, the container will find a listener to deal with the event. the listener should be self-configured by the programmer.
the types of listeners have been defined already.



###example of modify counter:
####configure listener:

```web.xml:
<listener>
<listener-class>com.listener.VisitCountListener</listener-class>
</listener>
```

```com.listener:
VisitCountListener implements  ServletContextListner{
  public void contextInitialized(ServletContextEvent arg0){
  		ServletContext sc=arg0.getServletContext();
       String path=sc.getRealPath(“\\WEB-INF\\classes\\com\\listener”);
       File file=new File(path+”\\visitCount.txt”);
String count=null;
       BufferedReader br;
		br=new BufferedRead(new FileReader(file));
		 count=br.readLine();
       if(count!=null){
     
       } 
sc.setAttribute("count",count)
   }
  public void contextDestroyed(ServletContextEvent arg0){
       ServletContext sc=arg0.getServletContext();
       Object count=sc.getAttribute("count");
       String path=sc.getRealPath(“\\WEB-INF\\classes\\com\\listener\\”);
       File file=new File(path+"visitCount.txt");
		BufferedWriter bw;
		bw=new Bufferedwriter(new FileWriter(file));
		bw.writer(count.toString());
		bw.close();
   }
}
```




##Filter:
**3 interfaces about API in Servlet API: Filter, FilterChain, FilterConfig**

* Filter:
filter class must implement this interface.
there are three methods
 * init(FilterConfig filterConfig):  
   init filter object, called on once, get filter init parameters by filterConfig
 * doFilter(ServletRequest request,ServletResponse response,FilterChain filterChain):  
   filter method, filter classes must implement this method. preprocess by request and response, pass processed request and response to next resource by filterChain
 * destroy():  
   called on before container is destroyed

* FilterChain:
this interface is used as a parameter in doFilter() of the Filter interface
only one method:
  * doFilter(ServletRequest request,ServletResponse response):  
this method can pass current request and response to next resource(next filter or target resource) on the filter chain.

* FilterConfig:
this interface is used as a parameter in init() of the Filter interface
only one method:
  * getInitParameter(String name):  
get filter init parameters.
we can configure init parameters for every filter in web.xml.
similar to <init-param>




###filter configuration:

```web.xml:
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

/*<dispatcher>： four values can be configured to refer to which method will be filtered when access to a resource 
REQUEST： request, default method, filter request URL(input URL into address bar, form submit, hyperlink, response redirect)，REQUEST must be written when there are other dispatcher values
FORWARD： filter request dispatcher URL
INCLUDE： filter dynamic included URL
ERROR： filter error page

one filter can be configured to multi resources
one resource can have multi filters, call on by configuration order
*/
```

####sample of creating filter：

```LoginFilter.
//com.filter，new Filter LoginFilter
public class LoginFilter implements Filter{
public void doFilterServlet(Request arg0,ServletResponse arg1,FilterChain chain){
    HttpServletRequest request=(HttpServletRequest)arg0;
    HttpSession session=request.getSession();
    String username=(String)session.getAttribute("username");
    String password=(String)session.getAttribute("password");
	if(username==null||password==null){
	request.getRequestDispatcher("../index.jsp").forward(request,response);
	request.getRequestDispatcher(request.getContextPath()	+"index.jsp").forward(request,response);
  }
	chain.doFilter(request, arg1)
  }
}
```

```web.xml:
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
```


####example of using filter init parameters：

```
<filter>
<init-param>
<param-name>start</param-name>
<param-value>10</param-value>
</init-param>
<init-param>
<param-name>end</param-name>
<param-value>12</param-value>
</init-param>
</filter>
```

```
private in start；
private int end；
public class LoginFilter implements Filter{
public void doFilterServlet(Request arg0,ServletResponse arg1,FilterChain chain){
    HttpServletRequest request=(HttpServletRequest)arg0;
    HttpSession session=request.getSession();
    String username=(String)session.getAttribute("username");
    String password=(String)session.getAttribute("password");

Date sysdate=new Date();
int hour=sysdate.getHours();
if(hour>=end||hour<=start){
request.setAttribute("msg","not in time");
	request.getRequestDispatcher(“../index.jsp”).forward(request,response);
return;

	if(username==null||password==null){
request.setAttribute("msg","need login");

	request.getRequestDispatcher("../index.jsp").forward(request,response);
	request.getRequestDispatcher(request.getContextPath()	+"index.jsp").forward(request,response);
return;
  }
}
	chain.doFilter(request, arg1)
  }
}

public void init(FilterConfig fConfig){
String s=fConfig.getInitParameter("start");
if(s!=null){
  start=Integer.parseInt(s)
}
String e=fConfig.getInitParameter("end")
if(e!=null){
 end=Integer.parseInt(e);
}
 start=Integer.parseInt（fConfig.getInitParameter("start")）;
 end=Integer.parseInt（fConfig.getInitParameter("end")）;
}
```








#web.xml conclusion：

* Servlet configuration:

```
<servlet>
<servlet-name>
<servlet-class>
<init-param>
<load-on-startup>loading order</load-on-startup>
</servlet>
<servlet-mapping>
<url-pattern>logic path,start with “/“
</servlet-mapping>
```

* Filter Configuration：

```
<web-app>
<filter>
<filter-name>
<filter-class>
<init-param>
</filter>
<filter-mapping>
<url-pattern>
<dispatcher>filter dispatcher method(REQUEST,FORWARD,INCLUDE,ERROR)
</filter-mapping>
</web-app>
```

* Context Configuration(SevletContext):

```
<web-app>
<context-param>
<param-name>
<param-value>
</context-param>
</web-app>
```

* session timeout configuration：

```
<web-app>
<session-config>
<session-timeout>minutes</session-timeout>
</session-config>
</web-app>
```

* welcome page list：  
default is `index.jsp` or `index.html`  
assign multi welcome pages through `<welcome-file-list>`, the container will find in configuration order.

```
<web-app>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>login.jsp</welcome-file>
<welcome-file>main.jsp</welcome-file>
</welcome-file-list>
</web-app>
```

* error page configuration：

```
<web-app>
<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page>
<error-page>
<exception-type>com.etc.exception.RegisterException</exception-type>
<location>/register.jsp</location>
</error-page>
</web-app>
```

* listener configuration：

```
<web-app>
<listener>
<listener-class>com.listener.FirstListener</listener-class>
</listener>
</web-app>
```

* JSP configuration:  
set attribute for jsp file referred by certain url
  * `<url-pattern>`  
     certain url pattern
  * `<el-ignored>`  
     whether ignore el or not(true->ignore, explain el as text output)
  * `<scripting-invalid>`  
     script element valid or not(true->invalid, jsp file which contains script element will show interpreter error)
  * `<page-encoding>`  
     jsp respond encoding method

```example.
<jsp-config>
<jsp-property-group>
<url-pattern>/admin</url-pattern>
<el-ignored>false</el-ignored>
<scripting-invalid>false</scripting-invalid>
</jsp-property-group>
<jsp-property-group>
<url-pattern>/admin</url-pattern>
<page-encoding>utf-8</page-encoding>
</jsp-property-group>
</jsp-config>
```

* data source configuration：  
use connection pool provided by container,

```example.
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/meeting</res-ref-name>
<res-type>java.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
```