java Servlet

栏目: Java · 发布时间: 5年前

内容简介:即,当http请求发出以后,在容器内解析http请求,创建出servlet实例,接着,再次调用init方法,接着再次调用service方法,最后由servlet输出响应信息,对于更多的请求来说,将会调用destroy()方法,最后把响应返回给客户端。简述一下php的过程,先请求处理,发送到apache,由apache进行处理静态资源的访问,对于动态访问,直接转发给php-fpm(其中php-fpm可以独立运行,但是不能处理静态资源)由php-fpm负责读取databases,然后把数据送给apache,再由

Servlet 介绍

Java Servlet 是运行在web服务器和应用程序上的程序,是一个中间层。

运行过程如图

java Servlet

即,当http请求发出以后,在容器内解析http请求,创建出servlet实例,接着,再次调用init方法,接着再次调用service方法,最后由servlet输出响应信息,对于更多的请求来说,将会调用destroy()方法,最后把响应返回给客户端。

简述一下 php 的过程,先请求处理,发送到apache,由apache进行处理静态资源的访问,对于动态访问,直接转发给php-fpm(其中php-fpm可以独立运行,但是不能处理静态资源)由php-fpm负责读取databases,然后把数据送给apache,再由apache返回给客户端,实际上,apache和nginx都可以作为服务器。事实上拿C++编写CGI也能完成上述的机制。

其中servlet类似于cgi,一种规范,只是一种规范。

并且,监听端口的任务由servlet服务器完成,类似的服务器由tomcat,jboss等服务器,都为实现了servlet的规则。

使用的时候,直接实现其规定的Servlet接口,当发生请求的时候,会由tomcat通过反射机制调用实现的Servlet接口的类。

生命周期

先调用init进行初始化,再次调用service方法来处理客户端的请求,再次调用destroy方法,终止,最后由jvm进行垃圾回收。

init方法

第一次创建servlet时被调用,后续每次用户请求时不在调用。即,它是一次性的初始化。

public void init() throws ServletException{
    // 初始化代码
}

service方法

为执行实际任务时的主要方法。

Servlet容器会调用service方法来处理客户端的请求,并把格式化后的响应返回给浏览器。

每次服务器接收到Servlet的时候,会产生一个新的线程来调用服务。

service方法是用来检查HTTP请求的类型。并在适当的时候,会调用适当的方法。

public void service(ServletRequest request, ServletResponse response) throws Exception{
    // service 方法
}

service方法,容器将会调用,并且是在适当的时候调用doGet和doPost等方法。

doGet方法

public void doGet(HttpServletRequest request,
                  HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码
}

doPost方法

public void doPost(HttpServletRequest request,
                   HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码
}

destroy方法

public void destroy() {
    // 终止化代码...
  }

此方法只会被调用一次,在生命周期结束的时候,会被调用。

destroy方法,用于关闭数据库连接,停止后台线程,把cookie列表写入磁盘,或者点击计数器写入磁盘,并,进行另外的清理活动

栗子

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

// 继承HttpServlet类
public class HelloWorld extends HttpServlet {
    private String message;

    @Override
    // 重写init方法,每当有请求的时候,会调用init方法
    public void init() throws ServletException{
        // 执行初始化
        this.message = "hello world";
    }

    @Override
    // 请求来的时候调用get
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 响应内容类型
        resp.setContentType("text/html");
        // 实际的逻辑处理
        // 获得输出流
        PrintWriter out = resp.getWriter();
        // 进行输出
        out.println("<h1>" + message + "</h1>");
    }

    // 进行后续处理
    public void destroy(){

    }
}

表单数据

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

// 继承HttpServlet类
public class HelloWorld extends HttpServlet {
    private static final long serialVersionUIS = 1L;

    public HelloWorld(){
        super();
    }

    protected  void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        // 响应内容类型
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String title = "get方法获取表单数据";
        // 中文处理
        String name = new String(request.getParameter("name").getBytes("ISO8859-1"), "UTF-8");
        String docTyoe = "<!Doctype html> \n";
        out.println(docTyoe + "<html>\n" +
                    "<head><title>" + title + "</title><head>\n" +
                    "<body bgcolor = \"#f0f0f0\">\n" +
                    "<h1 align=\"center\">" + title + "</h1>\n" +
                    "<u1>\n" +
                    "<li><b>站点名</b>" +
                    name + "\n" +
                    "  <li><b>网址</b>:"
                   + request.getParameter("url") + "\n" +
                    "</ul>\n" +
                    "</body></html>");
    }

    // 处理Post
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        doGet(request, response);
    }
}

过滤器

Servlet过滤器可以动态的拦截响应。

变换中间的响应的信息。

其中过滤器是实现javax.servlet.Filter 的类。

该接口定义了以下的三个方法

public void doFilter (ServletRequest, ServletResponse, FilterChain)

当客户端请求匹配的URL的时候,容器会先调用过滤器的doFilter方法。其中FilterChain用于访问下一个过滤器

public void init(FilterConfig filterConfig)

该方法,可以获得当前的FilterConfig对象

public void destroy()

在销毁过滤器实例前销毁该方法

先写过滤器

import javax.servlet.*;
import java.io.IOException;
import java.util.*;

public class LogFilter implements Filter {
    public void  init(FilterConfig config) throws ServletException {
        // 获取初始化参数
        String site = config.getInitParameter("Site");

        // 输出初始化参数
        System.out.println("网站名称: " + site);
    }
    public void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {

        // 输出站点名称
        System.out.println("站点网址");

        // 把请求传回过滤链
        chain.doFilter(request,response);
    }
    public void destroy(){

    }
}

书写请求

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

public class DisplayHeader extends HttpServlet {
    // 创建GET请求方法
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        // 设置响应内容类型
        response.setContentType("text/html;charset=UTF-8");

        PrintWriter out = response.getWriter();
        String title = "HTTP Header 请求实例 - 菜鸟教程实例";
        String docType =
                "<!DOCTYPE html> \n";
        out.println(docType +
                "<html>\n" +
                "<head><meta charset=\"utf-8\"><title>" + title + "</title></head>\n"+
                "<body bgcolor=\"#f0f0f0\">\n" +
                "<h1 align=\"center\">" + title + "</h1>\n" +
                "<table width=\"100%\" border=\"1\" align=\"center\">\n" +
                "<tr bgcolor=\"#949494\">\n" +
                "<th>Header 名称</th><th>Header 值</th>\n"+
                "</tr>\n");
        // 返回一个枚举,包含在请求头中的所有头名
        Enumeration headerNames = request.getHeaderNames();
        // 输出结果
        while(headerNames.hasMoreElements()){
            String paramName = (String)headerNames.nextElement();
            out.println("<tr><td>" + paramName + "</td>\n");
            String paramValue = request.getHeader(paramName);
            out.println("<td>" + paramValue + "</td></tr>\n");
        }
        out.println("<table>\n<body></html>");
    }
    // 处理POST
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

最后在配置文件中,配置好过滤器映射

在客户端请求访问后端资源前,拦截这些请求。

在服务器响应发送回客户端之前,处理这些响应。

有以下几种过滤器,身份验证过滤器,数据压缩过滤器,加密过滤器,触发资源访问事件,图像转换过滤器等。

作用:如把获取请求的用户名密码,进行逻辑处理此时,如果如果验证用户名密码不正确,禁止访问web浏览器资源的时候,此时过滤器将会提示。

其中配置文件如下

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   	  http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd"
          version="4.0">
   <filter>
       <!-- 过滤器所在的类名 -->
       <filter-name>LogFilter</filter-name>
       <filter-class>LogFilter</filter-class>
       <init-param>
           <!-- 设置参数值-->
           <param-name>Site</param-name>
           <param-value>xiao</param-value>
       </init-param>
   </filter>
   <!-- 设置过滤器网址 -->
   <filter-mapping>
       <filter-name>LogFilter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
   <!-- 设置容器网址 -->
   <servlet>
       <servlet-name>DisplayHeader</servlet-name>
       <servlet-class>DisplayHeader</servlet-class>
   </servlet>
   <servlet-mapping>
       <!-- 访问的网址 -->
       <servlet-name>DisplayHeader</servlet-name>
       <url-pattern>/DisplayHeader</url-pattern>
   </servlet-mapping>
</web-app>

异常处理

在servlet抛出异常的时候,web容器会在使用了 exception-type中搜索与之相匹配的设置,在配置文件当中需要指定error-page对于特定异常和状态码做出相应的servlet调用。

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class ErrorHandler extends HttpServlet {
    // 处理get请求
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        Throwable throwable = (Throwable)request.getAttribute("javax.servlet.error.exception");
        Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");
        String servletName = (String)request.getAttribute("javax.servlet.error.servlet_name");
        if(servletName == null){
            servletName = "Unknow";
        }
        String requestUrl = (String)request.getAttribute("javax.servlet.error.request_url");
        if(requestUrl == null){
            requestUrl = "Unknown";
        }
        // 设置响应类型
        response.setContentType("text/html;charset=UTF-8");

        PrintWriter out = response.getWriter();
        out.println("出现错误");

    }
    // POST
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws ServletException, IOException{
        doGet(request, response);
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd"
           version="4.0">
  <servlet>
      <servlet-name>ErrorHandler</servlet-name>
      <servlet-class>ErrorHandler</servlet-class>
  </servlet>
    <servlet-mapping>
        <servlet-name>ErrorHandler</servlet-name>
        <url-pattern>/ErrorHandler</url-pattern>
    </servlet-mapping>
    <error-page>
        <error-code>404</error-code>
        <location>/ErrorHandler</location>
    </error-page>
    <error-page>
        <exception-type>java.lang.Throwable</exception-type>
        <location>/ErrorHandler</location>
    </error-page>
</web-app>

Session

由于HTTP协议是一种无状态的协议。即,无法保存会话。

Cookies

在web服务器中,分配session会话ID作为web客户端的ID。把ID保存进入Cookies中,再次访问的时候,通过Cookies来验证

表单字段

在表单字段中指定sessionID作为本次会话的ID

URL重写

在URL末尾追加额外数据标识用来标识session会话。

服务器会把session会话进行关联

Token

即,在登录成功以后,服务器端生成一个token,即,用户唯一身份标识,+ 事件戳,+ 签名,签名是由token的前几位,+ 盐 用哈希算法进行压缩,防止第三方进行查询。

对于服务器来说,当用户登录的时候,根据用户唯一身份标识UID,+ 时间戳 + 签名,即,通过Token的前几位+ 盐,使用哈希算法生成,返回给客户端,客户端可以使用localhost,或者Cookie保存Token,并且,对Token进行过期时间设置,再次访问的时候,直接对Token,再次进行加密验证即可。

JWT Token

服务器端验证,信息通过哈希算法进行加密,私钥保存在服务器端,加密结果发送客户端,加密字符格式为三个点号分割的字符串Token,即,头部载荷,签名,头部,载荷,签名通过base64进行解码,客户端拿到Token,保存进入 local storage 再次发送请求,附加到header,服务端对header进行验证。

Oauth

即,保存一个令牌,用这个令牌,授权特定的网站,内的特定的资源,特定的时段,特定的信息。

即,点击登录按钮,用户引导进入授权页面,用户授权,重定向到redirect_uri,并附带上code。

使用code获取access_token 使用access_token获取用户的基本信息。

cookie - session

登录系统以后,创建session,把session保存进入cookie,再次请求通过cookie获取session进行校验。

改良

用户输入密码,登录系统后验证,数据保存进入redis,redis中获取key,把返回给客户端,根据key到 redis 中获取认证信息。

例子

下面的栗子核心在于isNew,servlet根据isNew来进行判断此用户是新用户还是老用户,当为新用户的时候,将会调用setAttribute,把当前的key,和id保存进行服务器的session。

若为老用户,将会getAttribute获取visitCountKey的key值,中间涉及一次自动装箱,然后把值进行相加。

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class SessionTrack extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        // 创建Session对象
        HttpSession session = request.getSession(true);
        // 获取创建时间
        Date createTime = new Date(session.getCreationTime());
        // 获取网页最后一次访问时间
        Date lastAccessTime = new Date(session.getLastAccessedTime());
        // 设置日期输出格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 设置标题
        String title = "title";
        Integer visitCount = new Integer(0);
        String visitCountKey = new String("visitCount");
        String userIDKey = new String("userID");
        String userID = new String("ming");
        // 获取保存在共享区的visitCountKey的value
        // 因为servlet创建的session为所有线程所共享的
        // 若为空,将会进行初始化
        if(session.getAttribute(visitCountKey) == null){
            session.setAttribute(visitCountKey, new Integer(0));
        }

        // 如果用户是第一次访问的时候,将会对session进行第一次的初始化
        if(session.isNew()){
            title = "ming";
            session.setAttribute(userIDKey, userID);
        }else{
            // 如果是老用户,对session保存的visitCountKey的key值进行加1操作
            // 获得上一个ID
            visitCount = (Integer)session.getAttribute(visitCountKey);
            // 对ID进行加1
            visitCount = visitCount + 1;
            // 获得当前的ID
            userID = (String)session.getAttribute(userIDKey);
        }
        // 从新进行设置
        session.setAttribute(visitCountKey, visitCount);

        // 设置响应内容类型
        response.setContentType("text/html;cahrset=UTF-8");
        PrintWriter out = response.getWriter();
        String docType = "<!DOCTYPE html>\n";
        out.println(docType +
                "<html>\n" +
                "<head><title>" + title + "</title></head>\n" +
                "<body bgcolor=\"#f0f0f0\">\n" +
                "<h1 align=\"center\">" + title + "</h1>\n" +
                "<h2 align=\"center\">Session 信息</h2>\n" +
                "<table border=\"1\" align=\"center\">\n" +
                "<tr bgcolor=\"#949494\">\n" +
                "  <th>Session 信息</th><th>值</th></tr>\n" +
                "<tr>\n" +
                "  <td>id</td>\n" +
                "  <td>" + session.getId() + "</td></tr>\n" +
                "<tr>\n" +
                "  <td>创建时间</td>\n" +
                "  <td>" +  df.format(createTime) +
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>最后访问时间</td>\n" +
                "  <td>" + df.format(lastAccessTime) +
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>用户 ID</td>\n" +
                "  <td>" + userID +
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>访问统计:</td>\n" +
                "  <td>" + visitCount + "</td></tr>\n" +
                "</table>\n" +
                "</body></html>");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>SessionTrack</servlet-name>
        <servlet-class>SessionTrack</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SessionTrack</servlet-name>
        <url-pattern>/SessionTrack</url-pattern>
    </servlet-mapping>
</web-app>

数据库访问

使用最最原始的JDBC访问即可


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Practical Django Projects, Second Edition

Practical Django Projects, Second Edition

James Bennett / Apress / 2009 / 44.99

Build a django content management system, blog, and social networking site with James Bennett as he introduces version 1.1 of the popular Django framework. You’ll work through the development of ea......一起来看看 《Practical Django Projects, Second Edition》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

html转js在线工具
html转js在线工具

html转js在线工具