文档章节

AOP-style programming for Web applications

y
 yaraja
发布于 2011/09/28 13:00
字数 1756
阅读 54
收藏 0

AOP-style programming for Web applications

Dmitry Namiot 
dnamiot@servletsuite.com

In this article we are demonstrating the usage of Java Servlets filters. Servlet filters are a new addition to the Servlet 2.3 specification. Filters are Java classes that can intercept requests from a client before they access a resource. Filters let you manipulate requests from clients, intercept responses from resources before they are sent back to the client and manipulate responses before they are sent to the client.

In other words filters let you preprocess and postprocess requests from clients. The typical examples are: authentication (check some conditions during the preprocessing), encryption and XSLT transformation (do some postprocessing) etc. Technically speaking any filter is simply a Java class that implements thejavax.servlet.Filter interface. The main method in javax.servlet.Filter is

public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain)

Actually this method does all the tasks. The typical code for filter looks so:

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import java.io.IOException;
import javax.servlet.ServletException;

public class SimpleFilter implements Filter
{
  public void doFilter (ServletRequest request,
             ServletResponse response,
             FilterChain chain) throws IOException, ServletException
  {

	// do some preprocessing
	// (filtering the Request)

	// execute request
	chain.doFilter (request, response);

	// do some postprocessing
	// (filtering the Response)

  }
  ...
}

Notice that doFilter() can be separated into two sections: filtering the request (preprocessing) and filtering the response (postprocessing). These two sections are separated by a call doFilter() method from the javax.servlet.FilterChain object. This call passes request to the next object in the chain, which could be the target resource (servlet, jsp page etc.) or another filter. The deployment for filters described in web.xml file (the way is similar to servlets deployment).

That is the basic. And what are we going to demonstrate in this article? Sure, it is possible to add new filters for some custom pre or post processing in your web application. But what if this deal could be done without Java programming and without updating web.xml file? More precisely we are going to use plain JSP files for our custom actions. So our actions in this case could be updated without the recompilation and redeployment for Java classes and custom JSP taglibs will open the way for writing such actions by non-programmers.

The main idea is very straightforward. Look at the above mentioned code example. That is the pattern that should be repeated from filter to filter. So we will just extract the reused part of this code and wrap it as a standard package.

Preprocessing. As a preprocessor we will use Generic preprocessor filter from Coldbeans: http://www.servletsuite.com/servlets/genericflt.htm

This filter lets you preprocess incoming requests right in JSP pages. So each incoming request will be forwarded to some JSP page (provided as a parameter for this filter) and that JSP page will play a role of preprocessor.

The usage for this filter is very simple: 

a) download .jar file with filter’s code and save it in WEB-INF/lib 
b) describe this filter in web.xml. Initial parameter preprocessor describes your JSP page for preprocessing. For example:

<filter> 
  <filter-name>GenericFilter</filter-name> 
  <filter-class>com.cj.genericflt.GenericFilter</filter-class> 
  <init-param> 
   <param-name>preprocessor</param-name> 
   <param-value>/preprocess.jsp</param-value> 
  </init-param> 
</filter>

c) describe a mapping for this filter in web.xml. E.g.:

<filter-mapping> 
  <filter-name>GenericFilter</filter-name> 
  <url-pattern>/myapp/*</url-pattern> 
</filter-mapping>

in this case filter will be on for each your file in /myapp. All steps here are standard and follow to the Servlets API. And now when you invoke any .jsp page:http://your_host/myapp/test.jsp GenericFilter will forward request to your JSP page provided in parameter preprocessor (in this case it is /preprocess.jsp). This page is a normal JSP page where you can do whatever you need with incoming requests. As soon as your preprocessing will be completed the normal chain for your request will be restored. In this example it means that /myapp/test.jsp (the original file) will be processed. And that is the main idea – you can program preprocessing (aspect in the modern terms) right in JSP. Even more: in this JSP page you can use a special custom JSP taglib that helps you change the normal control flow. You may decide for example in some cases to terminate preprocessed request right in this JSP (e.g. your preprocessing checks some access right). In other cases you may decide to add new attributes to request scope (e.g. pre-populate some DB data) and continue the normal chain of execution. For example, in our simple scenario our JSP preprocessor will check attribute presence in the session and terminate request if this attribute absent.

<%@ taglib uri="taglib.tld" prefix="pre" %> 
<%
 if (session.getAttribute("validUser")==null) {
%>
<p>You are not allowed to access <pre:getOriginalURI/>
<pre:stopChain/>
<% } %>

Here custom tag stopChain will terminate incoming request in your JSP preprocessor. So the normal execution chain will be skipped after the preprocessing. By default this execution chain will be resumed. We are using scriptlets here just in order to highlight the special tags from our preprocessor taglib. But of course you are free to use here any JSP tools you like: JSTL, Jakarta taglibs, Coldtags suite etc. E.g. (JSTL):

<c:if test="${session.validUser==null}">
	<p>You are not allowed to access <pre:getOriginalURI/>
	<pre:stopChain/>
</c:if>

And custom tag getOriginalURI lets you obtain in your preprocessor the original URI (URI from the preprocessed request). Now we can return back to our original goal. We do not need to update our web.xml (deploy a new component) for each new preprocessing task. Now it is enough to update our JSP code only. And because it is a plain old JSP file we are free to use all JSP related taglibs here.

Postprocessing. As a postprocessor we will use Generic postprocessor filter from Coldbeans: http://www.servletsuite.com/servlets/generic1flt.htm

The usage is similar to the above-mentioned preprocessor. We have to put .jar file into WEB-INF/lib and describe our filter in web.xml. Right now the initial parameter postprocessor describes our JSP page for postprocessing:

<filter> 
  <filter-name>Generic1Filter</filter-name> 
  <filter-class>com.cj.generic1flt.Generic1Filter</filter-class> 
  <init-param> 
   <param-name>postprocessor</param-name> 
   <param-value>/postrocess.jsp</param-value> 
  </init-param> 
</filter>

c) describe a mapping for this filter in web.xml. E.g.:

<filter-mapping> 
  <filter-name>Generic1Filter</filter-name> 
  <url-pattern>/myapp/*</url-pattern> 
</filter-mapping>

in this case filter will be on for each your .jsp file in /myapp. Now when you invoke any .jsp page: http://your_host/myapp/test.jsp Generic1Filter will execute this request and bypass the control to your JSP page provided in parameter postprocessor (in this case it is /postprocess.jsp). This page is a normal JSP page where you can do whatever you need with incoming request as well as with the outgoing data. In other words if your requested page (e.g. test.jsp in our example) produced some output you can read this info here (in your postprocessor), modify data or even completely replace the original output with your own content. So your postprocessor will decide what to do with the processed data: stream them to user as is, modify them and stream to user after that or even produce a completely new content. And again a special custom JSP taglib could be involved in this calculation.

What is a source point here? We do a post processing. So our original request has been processed already at this point. This processing produced some content that is ready to be streamed to client’s device (browser, micro browser etc.). In our JSP post processor we should be able to get this content and process it. By this reason our postprocessor taglib contains a bit more tags comparing with the preprocessing:

- we can obtain the original URI and indicate the termination for our request here in our preprocessor 
- we can obtain the content provided by our request as well as its attributes: content length, content type

What does it mean termination here? By default after the post processing the original content will be streamed to client’s device. Why do we need (or what can we do) post processing? Think for example about some logging or billing functions. We can for example just record the request and its result into DB or log file. Alternatively we can do something with the original content and send it to our client right here in the post processor. For example it could be XSLT transformation, compression, translation etc. And termination tells to our filter that the post processor itself will take care about the output.

For example in our post process JSP file we can do some like this:

a) assume our request produces some XML content and we will transform it here

<%@ taglib uri="http://java.sun.com/jstl/xml" prefix="x" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ taglib uri="postprocess.tld" prefix="post" %>


<!-- obtain our content as a String -->
<post:getContentString id=”xmlData”/>

<!-- import XSL data -->
<c:import url="/xslt/our_xsl_data.xsl" var="xsltData" />

<!-- do the transformation -->
<x:transform xml="${xmlData}" xslt="${xsltData}" />

<!-- terminate request -->
<post:stopChain/>

again, because it is just a JSP file we can use any of existing tools. In this case we used JSTL. Tag getContentString obtains content as a String (text). But we can do the same for the binary data too. Tag getContent will return a byte array.

b) just a simple logger for requested URI and its content length (e.g. for debug purposes)

<%@ taglib uri="postprocess.tld" prefix="post" %>

     <post:getOriginalURI id="uri"/>
     <post:getContentLength id="len"/>

     <%
         System.out.println(uri+":"+len);
      %>

we did not terminate request here, so after the post processing the calculated content will be streamed to client’s device as is. Actually our filter does this job. And again returning back to our original goal we see that we do not need to update our web.xml (deploy a new component) for each new post processing task. Now it is again enough to update our JSP code only. And because it is a plain old JSP file we are again free to use all JSP related taglibs here. In the real applications you are free of course to use both approaches: pre and post processing. The pattern for the usage is absolutely the same.

So what we did at the end of the day? We demonstrated here the ability to use the plain JSP for the pre- and post-processing incoming requests. This ability is more flexible and easy to use comparing with the writing custom filters for the appropriate tasks. And the usage of custom JSP tags opens the way for the even more simple way to program such actions. Also I would like to highlight that it is not yet another framework and everything could be done within the standard circle: filters and custom tags in the original form.

本文转载自:http://www.servletsuite.com/tips/aop.htm

共有 人打赏支持
y
粉丝 7
博文 10
码字总数 0
作品 0
浦东
私信 提问
现有AOP解决方案收集

基于.NET的AOP解决方案: Aspect# (http://aspectsharp.sourceforge.net/) is a free AOP framework for .NET. AspectDNG (http://sourceforge.net/projects/aspectdng/) is a .NET multi-l......

强子哥哥
2016/08/27
38
0
[雪峰磁针石博客]kotlin书籍汇总

下载地址 Learning Kotlin by Building Android Applications - 2018 初级 Develop amazing applications that will help you understand and explore the fundamentals of Kotlin while co......

python测试开发人工智能安全
08/30
0
0
.NET Open Source Developer Projects

This community maintained list showcases .NET open source developerprojects. It is intended to include projects that are useful for anyaspect of the development process. For con......

Yamazaki
2015/08/26
0
0
(转)Model-View-Controller (MVC) with JavaScript

原文:http://www.alexatnet.com/content/model-view-controller-mvc-javascript The article describes an implementation of Model-View-Controller software design pattern in JavaScrip......

Huawu
2010/07/27
0
0
spring aop 申明了切面类之后,如何申明切入点呢?

8.2.3 Declaring a pointcut Recall that pointcuts determine join points of interest, and thus enable us to control when advice executes. Spring AOP only supports method execution......

Oscarfff
2015/04/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

分布式锁的实现

redis实现分布式锁 方法1:普通实现方案 实现方式: 使用指令: set key 随机值 ex 5 nx.意思是当key不存在的时候设置key. 如果key存在返回OK,否则返回nil. 实现过程: 1.执行命令set key true ...

grace_233
28分钟前
1
0
解决CKEditor 4 富文本编辑器在图片组件无法显示[上传]选项卡的相关问题

关于解决CKEditor 4 富文本编辑器在图片组件无法显示[上传]选项卡的相关问题。 本文可能会对以下现象得以解决: 图片上传组件,没有 [上传] 选项卡。 资源无法加载 [imgupload] ( Uncaught E...

Eller
31分钟前
0
0
限制php解析、user_agent、php相关配置

11月20日任务 11.28 限定某个目录禁止解析php 11.29 限制user_agent 11.30/11.31 php相关配置 11.28、限定某个目录禁止解析php 核心配置文件内容 <Directory /data/wwwroot/www.123.com/upl...

zgxlinux
36分钟前
1
0
博客园首页新随笔联系订阅管理 随笔

注解Annotation实现原理与自定义注解例子 什么是注解? 对于很多初次接触的开发者来说应该都有这个疑问?Annontation是Java5开始引入的新特征,中文名称叫注解。它提供了一种安全的类似注释的...

onedotdot
54分钟前
4
1
Spring boot + redis 用RedisTemlate实现简单的String key value 操作

springboot集成redis, 简单的key, value缓存操作. 1. application-local.properties # redis on local#spring.redis.port=6379#spring.redis.host=localhost#spring.redis.password=......

园领T
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部