过滤器可以拦截请求及控制响应,而servlet对此毫无感知。过滤器有如下作用:
1)请求过滤器:完成安全检查、重新格式化请求首部或体、建立请求审计日志。
2)响应过滤器:压缩响应流、追加或修改响应流、创建一个完全不同的响应。
当多个过滤器映射到一个给定资源时,容器会使用先URL模式后servlet-name的规则。
过滤器的顺序为: filter1、filter2、filter3
需求:1)项目只接受/hello 请求的GET方法,对于其他请求则返回“404没有找到对应资源”。2)对所有响应,返回内容结尾都追加“filter实战”。
- public class HelloServlet extends HttpServlet {
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- PrintWriter writer = resp.getWriter();
- writer.print("你好 Servlet");
- writer.close();
- }
-
- }
-
- public class RequestFilter implements Filter {
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- System.out.println("拦截器初始化");
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- HttpServletRequest request = (HttpServletRequest) servletRequest;
- String method = request.getMethod();
- String servletPath = request.getServletPath();
- HttpServletResponse response = (HttpServletResponse) servletResponse;
- CustomResponseWrapper responseWrapper = new CustomResponseWrapper(response);
- responseWrapper.setContentType("text/html;charset=UTF-8");
- if ("GET".equalsIgnoreCase(method) && "/hello".equalsIgnoreCase(servletPath)) {
- filterChain.doFilter(request,responseWrapper);
- } else {
- PrintWriter writer = responseWrapper.getWriter();
- writer.print("404没有找到对应资源");
- writer.close();
- }
- }
-
- @Override
- public void destroy() {
- System.out.println("拦截器销毁");
- }
- }
-
- public class CustomResponseWrapper extends HttpServletResponseWrapper {
-
- private CustomPrintWriter pw;
-
- public CustomResponseWrapper(HttpServletResponse response) {
- super(response);
- }
-
- @Override
- public PrintWriter getWriter() throws IOException {
- if (pw == null) pw = new CustomPrintWriter(super.getWriter());
- return pw;
- }
- }
-
- public class CustomPrintWriter extends PrintWriter {
- public CustomPrintWriter(Writer out) {
- super(out);
- }
-
- @Override
- public void print(String s) {
- super.print(s + "——filter实战");
- }
- }
- <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
- version="2.4">
- <servlet>
- <servlet-name>helloServlet</servlet-name>
- <servlet-class>HelloServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>helloServlet</servlet-name>
- <url-pattern>/hello</url-pattern>
- </servlet-mapping>
-
- <filter>
- <filter-name>reqFilter</filter-name>
- <filter-class>RequestFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>reqFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- </web-app>
web.xml
Web系统要求着良好的性能,让用户得到更快的响应时间及支持更多的并发用户;为了让应用不同部分能同时在不同主机上运行,要以适当方式模块化;同时系统还要有一定的灵活性、可维护性和可扩展性。
在对象跨网络通信时存在一些常见的问题:查找远程对象及处理本地和远程对象之间的底层网络I/O通信。也就是如何找到远程对象,以及如何调用其方法。
JNDI和RMI可以解决上述的问题。
Java Naming and Directory Interface,Java命名和目录接口。可以在网络上的一个集中位置上完成查找。想被查找并访问的对象,要先向JNDI注册,再通过JNDI来查找。
图 WEB服务请求调用远程服务器服务过程
业务委托:完成请求的业务处理。
服务定位器:从JDNI查找需要调用的远程服务。
Model-View-Controller(模型-视图-控制器)。
模型:真正的业务逻辑和状态。了解获取和更新状态的规则。
视图:从控制器得到模型的状态。发起请求及接受响应。
控制器:从请求取得用户输入,并向模型明确输入用户的含义。
控制器的3大任务及处理方案:
1)获得和处理请求参数,将这个任务交给另外一个单独的表单验证组件,由它获得表单参数、完成转换、进行验证、处理错误并创建一个对象保存参数值。
2)调用模型,采用声明方式,在定制部署描述文件中列出一些模型,控制器可以读取这些模型,并且根据请求来决定要使用哪些模型。
3)分派到视图,采用声明方式,根据URL控制器就能区分要分派到哪个视图。
前端控制器:应用所有的请求都会通过一个控制器,由它处理,并将请求分派到适当地方。