Showing posts with label Servlet. Show all posts
Showing posts with label Servlet. Show all posts

Friday, January 22, 2016

JSP

Location: /WEB-INF/A.jsp
WEB-INF represents web app inner files, not expose to outside.
To prevent some jsp/html file on the server directly accessed by browsers from URL, we need to put all request sensitive jsp file under WEB-INF folder.
Put other jsp/html file outside WEB-INF, so browsers can directly access those files by URL.

Normally used forward action:
<jsp:forward page="/WEB-INF/login.jsp"></jsp:forward>

When the first time visiting jsp

  1. web server will convert A.jsp to A_jsp.java
  2. A_jsp.java will compile to A_jsp.class

So when the first time visit jsp, response time will be slow


9 objects

  1. out
  2. request
  3. response
  4. session
  5. application   //servletContext
  6. pageContext  //only this jsp scope
  7. exception
  8. page   //this
  9. config   //servletConfig
3 syntax

Command
  1. <%@ page
    contentType="text/html;charset=utf-8"
    language="java"
    import="java.util.*,java.net.*"
    pageEncoding="utf-8"
    session="true"
    buffer="none|8k|"
    autoFlash="true" //autoFlash to client when buffer full
    isThreadSafe = "true"
    errorPage="/error"
    isErrorPage="false"
    %>
    We can use more than one page tag to make page nicer
    <%@ page import="java.util.*" %>
    <%@ page import="java.net.*" %>
  2. <%@ include file="a.jsp" %>  //static include
    //combine two jsp file to one servlet
  3. taglib
Script

  1. <% java code %>
  2. <%=rs.getString("name")>  //output string, no ; at the end
  3. <%! int count=10%>    //servlet scope, member variable
    <%  int count=10; %>    //function scope, local variable
    <%! public int test(String a){
        return a.length();
    }%>

Action

  1. <jsp:forward page="/a.jsp"></jsp.forward>     //forward to page
    <jsp:forward page="/WEB-INF/login.jsp"></jsp:forward>
  2. <jsp:include file=""></jsp:include>    //dynamic include
    //compile each jsp to different servlet first, then combine the output result
Comment
  1. <!-- Comments -->  HTML comment, still output comment content
  2. <%-- Comments --%>  JSP comment, does not output comment content to browser

Sunday, January 17, 2016

ServletContext

Scope: All servlets all clients
Life cycle:
  1. created when webapp boots
  2. destroyed when webapp closed


 ServletContext servletContext = this.getServletContext();
 //ServletContext servletContext servletContext = this.getServletConfig().getServletContext();
 servletContext.setAttribute("ABC", new Object()); //(String, Object)

Init Parameter
  
  <context-param>
    <param-name>Country</param-name>
    <param-value>China</param-value>
  </context-param>


    request.getServletContext().getInitParameter("Country");

Get Resource
 Properties pp = new Properties();
 InputStream fis = getServletContext().getResourceAsStream("WEB-INF/settings.properties");
 pp.load(fis);

 getServletContext().getRealPath("WEB-INF/settings.properties");

Captcha Image

Example

Image Service

public class ValidateCodeService {
 static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 static Random rnd = new Random();
 public static String createRandomString(int length) {
  StringBuilder sb = new StringBuilder(length);
  for (int i = 0; i < length; i++)
   sb.append(AB.charAt(rnd.nextInt(AB.length())));
  return sb.toString();
 }

 public static Image getImage(String code) {
  BufferedImage image = new BufferedImage(80, 30,
    BufferedImage.TYPE_INT_RGB);
  Graphics g = image.getGraphics();
  g.setColor(Color.WHITE);
  g.fillRect(0, 0, 80, 30);
  g.setColor(Color.BLACK);
  g.setFont(new Font(null, Font.BOLD, 20));
  g.drawString(code, 0, 20);
  return image;
 }
}

Output servlet

URL: /ValidateCode

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  response.setDateHeader("Expires", -1);
  response.setHeader("Cache-Control","no-cache");
  response.setHeader("Pragma","no-cache");
  response.setHeader("Content-Type", "image/jped");
  String code = ValidateCodeService.createRandomString(4);
  request.getSession().setAttribute("ValidateCode", code);
  Image image = ValidateCodeService.getImage(code);
  ImageIO.write((RenderedImage) image, "jpg", response.getOutputStream());
 }

View
 out.println(
  "Validation Code: <input type='text' name='ValidateCode'/>"
  +"<img id='ValidateCodeImg' src='"+request.getContextPath()+"/ValidateCode'>"
  +"<a href='#' rel='nofollow' title='Refresh Image' onclick=\"document.getElementById('ValidateCodeImg').src = '"+request.getContextPath()+"/ValidateCode?'+Date.now();return false;\">"
    +"Refresh"
         +"</a>"
    +"<br>");

Saturday, January 16, 2016

HttpSession


Session operation principle
Each session object has an id, using "JSESSIONID" in cookie to pass session id between client and server.
This cookie will be destroyed immediately when browser closed.
To still keep this session after browser closed, we need to overwrite the "JSESSIONID" cookie with the new one(in tomcat, the "JSESSIONID" string must be all uppercase):  
 HttpSession session = request.getSession();
 session.setAttribute("data", data);
 Cookie cookie = new Cookie("JSESSIONID",session.getId());
 cookie.setMaxAge(60*30); //session timeout in 30 minutes
 response.addCookie(cookie);

Request with session id


Set Session
 HttpSession session = request.getSession();//get session, if no session, create a new one
 //HttpSession session = request.getSession(true); //same as no parameter
 //HttpSession session = request.getSession(false); //if no session, return null
 session.setAttribute(String, Object);
 session.setMaxInactiveInterval(30); // precise in seconds
Get Session
 request.getSession();
 session.getAttribute(String); //return null if not exists
 
Delete object from Session
 session.removeAttribute(String);
Unbind Session
 request.getSession();
 session.invalidate(); //destroy the session, unbind all objects in session
                       //Normally used when safe sign out
  • Session stays in memory
  • One Session only work with one client browser(some wired browsers using same core may share the same session)
  • Session default life time: 30 minutes, default for site can be changed in tomcat/conf/web.xml, default for app can be changed in web.xml
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    
  • The precise in xml configs is in minutes, setMaxInactiveInterval(30) is in seconds
  • If another request proceed within the timeout, the session clock will be reset
  • If webapp reload/restart, all session will be destroyed


Friday, January 15, 2016

Servlet life cycle

Three ways to use servlet

1. Implement Servlet interface
2. Extends GenericServlet
3. Extends HttpServlet

Servlet Functions:

 voiddestroy()
          Called by the servlet container to indicate to a servlet that the servlet is being taken out of service.
 ServletConfiggetServletConfig()
          Returns a ServletConfig object, which contains initialization and startup parameters for this servlet.
 java.lang.StringgetServletInfo()
          Returns information about the servlet, such as author, version, and copyright.
 voidinit(ServletConfig config)
          Called by the servlet container to indicate to a servlet that the servlet is being placed into service.
 voidservice(ServletRequest req, ServletResponse res)
          Called by the servlet container to allow the servlet to respond to a request.

init: only run one time when the very first request
destory: only run once when web server stop webapp
service: run once per request



HttpServlet Functions:

doGet
doPost


urlPatterns:

using wildcard '*' character
1: start with "/" ends with "/*"
2. "*.extension" (no "/" at beginning)

url mapping rules:
1. looking for more specific mapping first (only count from left to right)
2. "*.extension" have lower priority than others(based on 1's left to right rule)


HttpServletResponse

setContentType("text/html")
setCharacterEncoding("utf-8")
setCharacterEncoding()


Servlet Config xml
<servlet>
    <init-param>
        <param-name></param-name>
        <param-value></param-value>
    </init-param>
    <load-on-startup>1</load-on-startup> : servlet init() when load, value is call sequence
</servlet>

<context-param> </context-param> :

Or

@WebServlet(name="InitServlet", urlPatterns="/InitServlet", loadOnStartup=1)

To override init or destroy function, for site open/close actions,
remember to set that servlet loadOnStartup, in case that servlet never been called

ServletConfig object

this.getServletConfig().getInitParameter("encoding")
Enumeration<String> names = getServletConfig().getInitParameterNames();
while(names.hasMoreElements()){
    String name = names.nextElement();
    ...
}

Redirection

Sendredirect
request.getRequestDispatcher("/Login").forward(request, response);






HttpServletRequest

Functions

  1. getRequestURL //full URL in type of StringBuffer: "http://localhost:8080/webapp/servlet1"
  2. getRequestURI //full URL in type of String: "/webapp/servlet1"
  3. getQueryString //all parameters string "name=abc&email=abc@gvace.com"
  4. getRemoteAddr //client IP address
  5. getRemoteHost //client host name if is registered in DNS server, return IP if not registered
  6. getRemotePort //client connection port
  7. getLocalPort //return server port "8080"
  8. getLocalAddr //web server IP address
  9. getLocalName //web server name
  10. getHeader("Host") //
  11. getHeaders() //return Enumeration
  12. getHeaderNames() //return Enumeration
  13. getParameter()
  14. getParameterValues(String name) // return String[], return null if no input
  15. getParameterNames()
Request Forward
  • request.getRequestDispatcher("/servlet1").forward(request,response);
    //forward to another servlet within webapp, share the same request and response
    //forward url can be only within the same webapp, so no "webapp" directory needed
    //keeping the same URL in browser
    //different from response.sendRedirect("/webapp/servlet1"); using different request/response
    //after the getRequestDispatcher("/servlet1").forward(request,response), all code continues to run, so make sure to return and finish the service

Thursday, January 14, 2016

Cookie

Set cookie

 Cookie cookie = new Cookie("name","abc"); //new Cookie(String,String)
 cookie.setMaxAge(1000); 
 //in seconds, default if not set: cleaned when browser closed
 response.addCookie(cookie); //remember to call addCookie

Get cookie

//Have to get all cookies as Array, then loop through each of them

Cookie cookies[] = request.getCookies(); //return null if none cookies
for(int i=0;i&ltcookies.length;i++){
 Cookie cookie = cookies[i];
 cookie.getName();
 cookie.getValue();
 cookie.getMaxAge();
}



  • Multiple browsers can share the same cookie 
  • If set the same key word, the old value will be replaced 
  • Every cookie can have their own life length 
  • All cookie from the same webapp will store in one single file on client hard drive, with timestamp
  • 20 most cookies a webapp can save to browser, each cookie have 4k max space
  • a browser can save 300 most cookies
Cookie life cycle
  • Cookie by default, will be destroyed when browser closed
  • setMaxAge(1000) can set length of life time for cookie
  • setMaxAge(0) destroy cookie
  • setMaxAge(-1000) cookie will destroy when browser closed
Cookie with Different Character set
  Saving
String val = java.net.URLEncoder.encode("中国字","utf-8");
Cookie cookie = new Cookie("name",val);
Getting
  String val = java.net.URLDecoder.decode(cookie.getValue(),"utf-8");

Monday, January 4, 2016

Servlet Utils

request.getContextPath()  // return "/webapp"

Tomcat default main directory:

getServletContext().getRealPath("/"); /var/lib/tomcat7/webapps/webapp1/

System.getProperty("catalina.base"); /var/lib/tomcat7


Load config file
Properties pp = new Properties();
InputStream fis = getServletContext().getResourceAsStream("WEB-INF/settings.properties");
pp.load(fis);


Read File


 String filePath = this.getServletContext().getRealPath("abc.text");
 FileReader fileReader = new FileReader(filePath);
 BufferedReader bufferedReader = new BufferedReader(fileReader);
 String line = bufferedReader.readLine();
 //do with line
 bufferedReader.close();
 fileReader.close();

Sunday, January 3, 2016

HttpServletResponse

Output:
  • getWriter() //characters only
  • getOutputStream() //bytes and characters.getByte()

We cannot use both method for one response, because an output will be auto closed, so the other output will not go through.
  • sendRedirect()
    response.sendRedirect("/webapp/anotherPage")// use at least "webapp" go back to client, client browser then send request to the new url
    //request.getContextPath() will return "/webapp"
    //the url can be anywhere in the world
    //the url from browser will change to the new url
    //after the sendRedirect, all code continues to run, so make sure to return and finish the service
    //To prevent user refreshing page, normally we use sendRedirect to direct to another url, so when user refresh, it keeps in the new url
  • flush()
    when response.flush() called, print writer committed all buffer to client, it can still push more content to client, but no forward contents will be affected.
    So if we call flush() first, request.getRequestDispatcher(url).forward(req,res) will not affect anything on the client side
    And before flush(), if we call request.getRequestDispatcher(url).forward(req,res) the printed buffer will not be affect, client will only see the forwarded contents.
  • Refresh: 1;url=http://www.baidu.com     //redirect to url after 1 second
    //response.setHeader("Refresh", "5;url=http://www.sohu.com");
  • cache: set http header, disable/enable cache
    response.setDateHeader("Expires",-1); //or value to System.currentTimeMillis()+1*1000;
    response.setHeader("Cache-Control","no-cache");
    response.setHeader("Pragma","no-cache");=
  • download file
    response.setHeader("Content-Disposition", "attachment; filename=winter.jpg");
    String path = getServletContext().getRealPath("/images/Winter.jpg");
    FileInputStream fis = new FileInputStream(path);
    byte buff[] = new byte[1024];
    int length=0;
    while((length=fis.read(buff))>0){
    response.getOutputStream().write(buff, 0, length);
    }
    response.getOutputStream().close();
    fis.close();
                    • Image type
                      response.setHeader("Content-Type", "image/jped");
                    • Encode URL, with SESSIONID in url
                      url = response.encodeURL("/webapp/servlet1");
                      // return /webapp/servlet1?SESSIONID=ABCDEFGHIJKLMN
                    • Captcha


                    Summary
                    1. Control response header, so you can manage the actions from browser
                    2. Use HttpServletResponse provided functions
                    3. Output stream will be auto closed when service is finished

                    Saturday, January 2, 2016

                    Character Encoding Issue, all solutions

                    Hibernate
                      <property name="hibernate.connection.CharSet">utf8</property>
                      <property name="hibernate.connection.characterEncoding">utf8</property>
                      <property name="hibernate.connection.useUnicode">true</property>



                    MySQL
                    Here is an doc for MySQL and Java io: http://blog.csdn.net/liuxueyongyu/article/details/2026788

                    Server encoding: iso-8859-1

                    Set page encoding to show Chinese character
                    response.setContentType("text/html;charset=utf-8");


                    Data request

                    1. form post
                    2. form get
                    3. url from html
                    4. sendRedirect

                    1. form post

                    Browser: utf-8

                    Web Server: iso-8859-1

                    Solution
                    request.setCharacterEncoding("utf-8")

                    2. form get / 3. url from html
                    Browser: utf-8

                    Web Server: iso-8859-1

                    Solution 1

                    @WebFilter("/CharacterEncoding")
                    public class CharacterEncoding implements Filter {
                     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
                      request.setCharacterEncoding("utf-8"); //set request character encoding
                      chain.doFilter(request, response);
                     }
                     @Override
                     public void init(FilterConfig filterConfig) throws ServletException {
                     }
                     @Override
                     public void destroy() {
                     }
                    }
                    


                    In web.xml
                    Write a filter by yourself

                    <filter>
                     <filter-name>CharacterEncoding</filter-name>
                     <filter-class>com.gvace.notebook.web.filter.CharacterEncoding</filter-class>
                    </filter>
                    <filter-mapping>
                     <filter-name>CharacterEncoding</filter-name>
                     <url-pattern>/*</url-pattern>
                    </filter-mapping>
                    

                    or Spring Web Filter(do not need to write a class then)
                     <!-- Encoding with spring filter -->
                     <filter>
                      <filter-name>encoding</filter-name>
                      <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
                      <init-param>
                       <param-name>encoding</param-name>
                       <param-value>UTF-8</param-value>
                      </init-param>
                     </filter>
                     <filter-mapping>
                      <filter-name>encoding</filter-name>
                      <url-pattern>/*</url-pattern>
                     </filter-mapping>
                    


                    Solution 2
                    request.setCharacterEncoding("utf-8")

                    Solution 3
                    new String(request.getParameter("name").getBytes("iso-8859-1"),"utf-8");




                    4. sendRedirect or All strings in URL

                    String info= java.net.URLEncoder.encode(name,"utf-8");
                    response.sendRedirect("EncodingPro/Welcome?username="+info);


                    Data Response

                    response.setContentType("text/html;charset=utf-8");


                    Cookie with Different Character set
                      Saving
                    String val = java.net.URLEncoder.encode("中国字","utf-8");
                    Cookie cookie = new Cookie("name",val);
                    
                    Getting
                      String val = java.net.URLDecoder.decode(cookie.getValue(),"utf-8");
                    
                    
                    Properties file
                    For character encoding in properties file
                    Use native2ascii from jdk/bin/, copy the String into native2ascii, it will translate to ascii




                    HTTP Protocol

                    1. http is built based on tcp/ip
                    2. Hyper Text Transfer Protocol
                    3. Http 1.0, and 1.1, now normally using 1.1
                        http1.0: short time connection, disconnect immediately
                        http1.1: longer time connection, 30 seconds

                    Request Header
                    GET /test/hello.html HTTP/1.1
                    Accept: */*
                    Referer: http://localhost:8080/test/abc.html
                    Accept-Language: zh-cn
                    User-Agent: Mozilla/4.0
                    Accept-Encoding: gzip, deflate
                    Host: localhost:8080
                    Connection: Keep-Alive
                    [empty line]
                    dataname1=data1
                    dataname2=data2

                    1. Accept: text/html, image/*
                    2. Accept-Charset: ISO-8859-1
                    3. Accept-Encoding: gzip, compress
                    4. Accept-Language: en-us,zh-cn
                    5. Host: www.sohu.com:80
                    6. If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT    //cache time, refresh if there is newer
                    7. Referer: http://www.sohu.com/index.jsp //tell host where this request come from, prevent spam
                    8. User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
                    9. Cookie
                    10. Connection: close    // or Keep-Alive
                    11. Date: Tue, 11 Jul 2000 18:23:51 GMT


                    Request Methods:

                    POST GET HEAD OPTIONS DELETE TRACE PUT


                    Response Header


                    1. HTTP/1.1 200 OK
                    2. Location: http://www.baidu.com //tell browser to redirect new url
                    3. Server: apache tomcat
                    4. Content-Encoding: gzip
                    5. Content-Length: 80
                    6. Content-Language: zh-cn
                    7. Content-Type: text/html; charset=GB2312 //response.setContentType("text/html;charset=GB2312");
                    8. Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT
                    9. Refresh: 1;url=http://www.baidu.com     //redirect to url after 1 second
                      //response.setHeader("Refresh", "5;url=http://www.sohu.com");
                    10. Content-Disposition: attachment; filename=aaa.zip
                      //tell browser that there is file to download
                      //response.setHeader("Content-Disposition","attachment; filename=aaa.zip");
                    11. Transfer-Encoding: chunked     //checksum verified
                    12. Set-Cookie:SS=Q0=5Lb_nQ; path=/search   //to be introduced
                    13. Expires: -1                               //tell browser(IE) how to cache data
                    14. Cache-Control: no-cache         //tell browser(FireFox) how to cache data
                    15. Pragma: no-cache                    //tell browser(some browser) how to cache data
                      //response.setDateHeader("Expires",-1); //or value to System.currentTimeMillis()+1*1000;
                      //response.setHeader("Cache-Control","no-cache");
                      //response.setHeader("Pragma","no-cache");
                    16. Connection: close/Keep-Alive
                    17. Date: Tue, 11 Jul 2000 18:23:51 GMT


                    State Code

                    • 200 normal
                    • 302 server request browser redirect to another resource
                      response.sendRedirect("anotherPage")
                      // or response.setStatus(302); response.setHeader("Location","anotherPage");
                    • 404 not found
                    • 500 server error
                      throw new RuntimeException();