servlet 及其过滤器filter

package com.mystudy.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.connector.Request;

public class helloServlet extends HttpServlet {
	//http请求方法不只是post和get,还有options用于返回服务器支持的方法,put方法用于上传指定的资源,
	//delete方法用于删除指定的资源,head和get相同只是返回http的报头,一般用到的只有post和get
	@Override
	public void init() throws ServletException {
		System.out.println("========servlet init without param============");
		super.init();//无参数的时候可以不调用super
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("========servlet init with param============");
		//有参数时需要手动调用super方法,init方法并不一定要重写,在需要servlet初始化的时候做一些操作,则重写,其他时候也不需要重写
		//有参数的init方法在父类中会显示的调用无参的init方法。
		super.init(config);
		}
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		System.out.println("========servlet service============");
		PrintWriter p=resp.getWriter();
		p.print("hello world");
		p.close();
	}

	@Override
	public void destroy() {
		//当servlet容器销毁servlet的时候才会调用destroy方法
		System.out.println("========servlet destroy============");

	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.doGet(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.doPost(req, resp);
                PrintWriter p=resp.getWriter();
                p.print("hello world");
                p.close();

                 String userNameString=req.getParameter("uname");
		String passwordString=req.getParameter("upwd");
		
		System.out.println("用户名:  "+userNameString);
		System.out.println("密码:  "+passwordString);
		
		//请求重定向,直接返回这个url,浏览器会重新访问返回 的url,因此这个url可以是当前应用的也可以是其他应用的地址,
		//那么浏览器的请求实际上完成的是两次,第一次访问目标地址,第二次访问重定向地址
		resp.sendRedirect(req.getContextPath()+"/04/success.jsp");
		
		//请求转发   和请求重定向不一样的是,请求转发只有一个http请求,不会产生第二次,
		//并且转发的地址必须是同一个应用中的地址,各个组件公用一个req请求和resp返回对象
		String forwordString="/04/error.jsp";
		RequestDispatcher rDispatcher=req.getRequestDispatcher(forwordString);
		rDispatcher.forward(req, resp);
	}



}


还需要在web.xml中配置servlet
  <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.mystudy.servlet.helloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping> 


通过HttpServlet类中的service方法可以看到,他的功能是根据请求的方法,自动的映射到不同的请求处理方法中,如果请求是get,那么请求交给doget(),如果是post交给dopost()。那么默认的service方法相当于一个请求转发的功能,因此如果我们自己重写servce方法, 父类HttpServlet中的service方法就会失效

所以收到的任何请求都会由我们自己覆写的service方法来处理

如果我们的servlet中只有service方法, 是没有问题的

但值得注意的是,一定要在执行完自己代码后调用父类service方法, super.service;

否自你的doGet和doPost是不会被执行的



servlet的过滤器 filter

Filter,过滤器,顾名思义,即是对数据等的过滤,预处理过程。为什么要引入过滤器呢?在平常访问网站的时候,有时候发一些敏感的信息,发出后显示时 就会将敏感信息用*等字符替代,这就是用过滤器对信息进行了处理。这只是一个简单的例子,当然,过滤器那么强大,它的功能也不可能局限于此,它不仅能预处 理数据,只要是发送过来的请求它都是可以预处理的,同时,它还可以对服务器返回的响应进行预处理,这样,大大减轻了服务器的压力。例如,实现URL级别的 权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能

过滤作用,对从客户端向服务器端发送的请求进行过滤,也可以对服务器端返回的响应进行处理。它使用户可以改变一个request和修改一个 response.。Filter 不是一个servlet,它不能产生一个response,但是它能够在一个request到达servlet之前预处理request,也可以在 response离开servlet时处理response。换句话说,filter其实是客户端与servlet中间的一个传递者,并且它可以对要传递 的东西进行修改。

扫描二维码关注公众号,回复: 1701445 查看本文章

如何实现拦截

  • 当客户端发生请求后,在HttpServletRequest 到达Servlet 之前,过滤器拦截客户的HttpServletRequest 。 
  • 根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。 
  • 在过滤器中调用doFilter方法,对请求放行。请求到达Servlet后,对请求进行处理并产生HttpServletResponse发送给客户端。
  • 在HttpServletResponse 到达客户端之前,过滤器拦截HttpServletResponse 。 
  • 根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。
  • 最后,HttpServletResponse到达客户端。

package com.mystudy.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;


public class FilterOne implements Filter {

    /**
     * Default constructor. 
     */
    public FilterOne() {
        // filter的构造函数
    	System.out.println("========filter one construct===========");
    }
	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// filter 的初始化,可以获取在注册时候的参数
		System.out.println("========filter one init===========");
//		System.out.println("param= "+fConfig.getInitParameter("encoding"));
	}


	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
		// 过滤器的具体实现,在请求进入对应的servlet之前输出一句话,在退出servlet之后输出一句话。
		
		System.out.println("========filter one dofilter start===========");
		chain.doFilter(request, response);
		System.out.println("========filter one dofilter end===========");
	}

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// 过滤器销毁的时候执行
		System.out.println("========filter one  destroy===========");
	}

}

在web.xml中进行注册,和servlet一样。
<filter>
    <filter-name>FilterOne </filter-name>
    <filter-class>com.mystudy.filter.FilterOne </filter-class>
    <init-param>//指定参数
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>FilterOne </filter-name>
    <url-pattern>/*</url-pattern>//对于所有该应用的请求都做拦截
  </filter-mapping> 

对于一个应用可以有多个过滤器,那么过滤器按照其配置的顺序进行调用。在dofilter()方法中的Filterchain对象就是放行到下一层过滤器的作用,可以通过

chain.doFilter(request, response);

实现。

如果没有filter了,那么直接放行到servlet,具体如上图那样。

//一个简单的字符编码过滤器,在注册该过滤器的时候指定一个参数encoding,值为UTF-8
//每次请求来的时候截获检查是不是指定的编码方式,不是就需要进行修改
public void init(FilterConfig fConfig) throws ServletException {
		
		charEncodingString=fConfig.getInitParameter("encoding");
		if (charEncodingString==null) {
			throw new ServletException("encoding  can't null");
		}
		
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
		
		if (!charEncodingString.equals(request.getCharacterEncoding())) {
			request.setCharacterEncoding("UTF-8");
		}
		response.setCharacterEncoding("UTF-8");
		chain.doFilter(request, response);
	}


servlet本质是什么?

servlet接口定义的是一套处理网络请求的规范,所有实现servlet的类,都需要实现它那五个方法,其中最主要的是两个生命周期方法 init()和destroy(),还有一个处理请求的service(),也就是说,所有实现servlet接口的类,或者说,所有想要处理网络请求的类,都需要回答这三个问题:

  • 你初始化时要做什么
  • 你销毁时要做什么
  • 你接受到请求时要做什么

这是Java给的一种规范!servlet是一个规范,那实现了servlet的类,就能处理请求了吗?不是

我们不会在servlet中写什么监听8080端口的代码,servlet不会直接和客户端打交道!

那请求怎么来到servlet呢?答案是servlet容器,比如我们最常用的tomcat,,我们需要把servlet部署到一个容器中,不然你的servlet压根不会起作用。

tomcat才是与客户端直接打交道的家伙,他监听了端口,请求过来后,根据url等信息,确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,tomcat再把这个response返回给客户端。


jsp和servlet的区别是什么?


jsp的本质就是servlet,jsp经过编译之后就成了servlet。

  • Servlet在Java代码中通过HttpServletResponse对象动态输出HTML内容
  • JSP在静态HTML内容中嵌入Java代码,Java代码被动态执行后生成HTML内容
  • Servlet能够很好地组织业务逻辑代码,但是在Java源文件中通过字符串拼接的方式生成动态HTML内容会导致代码维护困难、可读性差。servlet更擅长逻辑控制
  • JSP虽然规避了Servlet在生成HTML内容方面的劣势,但是在HTML中混入大量、复杂的业务逻辑同样也是不可取的。jsp更擅长页面显示
  • Servlet中没有内置对象,所需要必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到.


servlet的构造函数和init方法????

首先,构造函数是有的,虽然我们通常不写servlet的构造函数,但是就像任何一个普通的java类一样,编译器会自动给你生成一个默认构造函数;

其次,构造函数和init方法都会被web容器调用,而且是先调用构造函数,然后调用init方法;

最后,貌似容器只会调用默认构造函数,所以如果你自己写了带参数的构造函数(系统就不会自动生成默认构造函数),容器初始化servlet就会出错……P.S.:任何时候都不推荐自己写构造函数来初始化servlet类,哪怕你自己提供不带参数的构造函数……




猜你喜欢

转载自blog.csdn.net/u010365819/article/details/80712009