1. Tasks for Today
· OGNL expression
· Combination of OGNL and Struts 2
· Use Struts 2 to optimize customer queries
2. Relevant knowledge
2.1 OGNL
Overview of 2.1.1 OGNL
OGNL expression
OGNL, known as Object-Graph Navigation Language, is a powerful expression language for acquiring and setting attributes of Java objects. It aims to provide a higher and more abstract level to navigate Java object diagrams.
The basic unit of OGNL expression is "navigation chain". Generally, navigation chain consists of the following parts:
property name
method invoke
Array element
OGNL can not only navigate views. It supports more functions than EL expressions.
2.1.2 Role of OGNL
1. Supporting object method calls, such as xxx.doSomeSpecial();
2. Supporting static method calls and value access of classes. Format of expressions:
@ [Full class name (including package path)]@ [method name | value name], for example:
@java.lang.String@format('foo%s', 'bar')
Or @tutorial.MyConstant@APP_NAME;
Set struts.ognl.allowStaticMethodAccess=true
3. Access OGNL context and ActionContext; Access value stack
4. Support assignment and expression concatenation, such as price=100,discount=0.8,
CalulatePrice (), which returns 80;
5. Operating on Collection Objects.
2.1.3 Introduction to OGNL
1. Guide Pack
Struts jar packages already contain OGNL packages
2. Test code
public class TestOGNL { @Test public void f1() throws OgnlException{ //Prepare root User rootUser = new User("tom",25); //Prepare context Map<String, User> context = new HashMap<>(); context.put("user1", new User("jack",18)); context.put("user2", new User("rose",16)); OgnlContext oc = new OgnlContext(context); //Use rootUser as the root part oc.setRoot(rootUser); //Test to get the name attribute of root String rootName = (String) Ognl.getValue("name", oc, oc.getRoot()); System.out.println(rootName); //Test to get the name attribute of context user1 String user1Name = (String) Ognl.getValue("#user1.name", oc, oc.getRoot()); System.out.println(user1Name); //Test to get the age attribute of context user1 Integer user1Age = (Integer) Ognl.getValue("#user1.age", oc, oc.getRoot()); System.out.println(user1Age); } }
2.1.4 OGNL grammar
public class TestOGNL { /** * Basic Grammar * * @throws OgnlException */ @Test public void f1() throws OgnlException { // Prepare root User rootUser = new User("tom", 25); // Prepare context Map<String, User> context = new HashMap<>(); context.put("user1", new User("jack", 18)); context.put("user2", new User("rose", 16)); OgnlContext oc = new OgnlContext(context); // Use rootUser as the root part oc.setRoot(rootUser); // Test to get the name attribute of root String rootName = (String) Ognl.getValue("name", oc, oc.getRoot()); System.out.println(rootName); // Test to get the name attribute of context user1 String user1Name = (String) Ognl.getValue("#user1.name", oc, oc.getRoot()); System.out.println(user1Name); // Test to get the age attribute of context user1 Integer user1Age = (Integer) Ognl.getValue("#user1.age", oc, oc.getRoot()); System.out.println(user1Age); } /** * assignment * * @throws OgnlException */ @Test public void f2() throws OgnlException { // Prepare root User rootUser = new User("tom", 25); // Prepare context Map<String, User> context = new HashMap<>(); context.put("user1", new User("jack", 18)); context.put("user2", new User("rose", 16)); OgnlContext oc = new OgnlContext(context); // Use rootUser as the root part oc.setRoot(rootUser); // Test name attribute assignment for context user1 String user1Name = (String) Ognl.getValue("#user1.name ='Xiaoming', oc, oc.getRoot()); System.out.println(user1Name); } /** * Call method * * @throws OgnlException */ @Test public void f3() throws OgnlException { // Prepare root User rootUser = new User("tom", 25); // Prepare context Map<String, User> context = new HashMap<>(); context.put("user1", new User("jack", 18)); context.put("user2", new User("rose", 16)); OgnlContext oc = new OgnlContext(context); // Use rootUser as the root part oc.setRoot(rootUser); // Test call user2 method String user2Name = (String) Ognl.getValue("#user2.setName('Xiaohong'),#user2.getName()", oc, oc.getRoot()); System.out.println(user2Name); // Call the static method Math.random() Double number = (Double) Ognl.getValue("@java.lang.Math@random()", oc, oc.getRoot()); System.out.println(number); } }
Overview of 2.2 Value Stack
2.2.1 What is a value stack?
ValueStack is an interface of Struts, literally a value stack. OgnlValueStack is an implementation class of ValueStack. When a client initiates a request Struts2 architecture, it creates an Action instance and an OgnlValueStack value stack instance. OgnlValueStack runs through the life cycle of an Action. In struts2, using OGNL, it requests A. The parameters of Action are encapsulated as objects and stored in the value stack, and the object attribute values in the value stack are read through OGNL expressions.
Internal structure of 2.2.2 value stack
There are two parts in OnglValueStack, value stack and map (that is, ognl context)
· Context: The OgnlContext context, which is a map structure, stores some references in the context, such as parameters, request, session, application, etc. The Root of the context is CompoundRoot.
Some references in OgnlContext:
Parameters: The Map contains the request parameters for the current request
Request: This Map contains all the attributes in the current request object
Session: This Map contains all the attributes in the current session object
Application: This Map contains all the attributes in the current application object
attr: The Map retrieves an attribute in the following order: request, session, application
· CompoundRoot: Stores an action instance as a Root object of the OgnlContext.
CompoundRoot inherits ArrayList to implement stack and stack-out functions. It has the characteristics of stack, first in first out, last in first out, and finally pushes the data into the stack at the top of the stack. We call it the object stack.
The improvement of struts2 to the original OGNL is that Root uses CompoundRoot (custom stack) and findValue method of OnglValueStack to find the attribute value of the object from the top of the stack to the bottom of the stack in CompoundRoot.
CompoundRoot acts as the Root object of OgnlContext, and the action instance is located at the top of the stack in CompoundRoot. When reading the attribute value of action, it will first find the corresponding attribute from the top object of the stack, and if it cannot be found, it will continue to look for other objects in the stack, and if it is found, it will stop searching.
2.2.3 The relationship between ActionContext and ValueStack
Query by source code: public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) { ActionContext ctx; Integer counter = 1; Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER); if (oldCounter != null) { counter = oldCounter + 1; } ActionContext oldContext = ActionContext.getContext(); if (oldContext != null) { // detected existing context, so we are probably in a forward ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap())); } else { ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack(); stack.getContext().putAll(dispatcher.createContextMap(request, response, null)); ctx = new ActionContext(stack.getContext()); } request.setAttribute(CLEANUP_RECURSION_COUNTER, counter); ActionContext.setContext(ctx); return ctx; } * In Creation ActionContext When created ValueStack Objects that will ValueStack Object to ActionContext. * ActionContext One of them is ValueStack Citation. ValueStack There is also one of them. ActionContext Citation. * ActionContext Obtain ServletAPI When,Dependency stack.
2.2.4 Get the value stack object
[Get the value stack through the ActionContext object.]
ValueStack stack1=ActionContext.getContext().getValueStack();
[Get the value stack through the request field.]
ValueStackstack2=(ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
2.2.5 Operational Value Stack
[How to provide get methods for attributes in Action]
Because the Action itself is in the value stack, the attributes in the Action are also in the value stack by default, so we can manipulate the value stack by providing get methods for the attributes of the Action.
[Manual operation value stack]
Call the push and set methods of the value stack to operate on the value stack
2.3 The Use of Special Characters in EL
2.3.1 # Use
[Getting context ual data]
<s:propertyvalue="#request.name"/>
[Used to build a Map collection]: When using UI tags for struts.
<s:iteratorvalue="#{'aaa':'111','bbb':'222','ccc':'333' }"var="entry">
<s:propertyvalue="key"/>---<s:propertyvalue="value"/><br/>
<s:propertyvalue="#entry.key"/>---<s:propertyvalue="#entry.value"/><br/>
</s:iterator>
<s: radiolist="{1':'male','2':'female'}" name= "sex"> </s: radio>
Use of 2.3.2% Number
[Mandatory parsing of OGNL expressions]
<s:textfield name="name"value="%{#request.name}"/>
[Mandatory non-parsing of OGNL expression]
<s:propertyvalue="%{'#request.name'}"/>
2.3.3 USD
[Use OGNL expressions in configuration files]
Use. XML file or attribute file in struts configuration file.
3.crm case
Use Struts 2 to optimize customer queries
Action code:
public class CustomerAction extends ActionSupport implements ModelDriven<Customer>{ private Customer customer = new Customer(); private int currentPage = 1; private CustomerService customerService = new CustomerServiceImpl(); /** * Get the customer list * @return * @throws Exception */ public String list() throws Exception{ DetachedCriteria dc = DetachedCriteria.forClass(Customer.class); //Get the filter customer name String cust_name = customer.getCust_name(); if (cust_name!=null) { //If filter customer name does not add ambiguous query condition for blank dc.add(Restrictions.like("cust_name", "%"+cust_name+"%")); } //Set up each page to display several records int pageSize = 10; //Call the business layer to get the customer list PageBean<Customer> pb = customerService.getCustomerByPage(dc,currentPage,pageSize); //Put pagebean s on the value stack ValueStack valueStack = ActionContext.getContext().getValueStack(); valueStack.getContext().put("pb", pb); return "list"; } /** * Adding Customers * @return * @throws Exception */ public String save() throws Exception{ customerService.save(customer); return "toList"; } @Override public Customer getModel() { // TODO Auto-generated method stub return customer; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } }
jsp page:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <TITLE>Customer List</TITLE> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <LINK href="${pageContext.request.contextPath }/css/Style.css" type=text/css rel=stylesheet> <LINK href="${pageContext.request.contextPath }/css/Manage.css" type=text/css rel=stylesheet> <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script> <SCRIPT language=javascript> function to_page(currentPage){ if(currentPage){ $("#currentPage").val(currentPage); } document.customerForm.submit(); } </SCRIPT> <META content="MSHTML 6.00.2900.3492" name=GENERATOR> </HEAD> <BODY> <FORM id="customerForm" name="customerForm" action="${pageContext.request.contextPath }/CustomerAction_list" method="post"> <TABLE cellSpacing=0 cellPadding=0 width="98%" border=0> <TBODY> <TR> <TD width=15><IMG src="${pageContext.request.contextPath }/images/new_019.jpg" border=0></TD> <TD width="100%" background="${pageContext.request.contextPath }/images/new_020.jpg" height=20></TD> <TD width=15><IMG src="${pageContext.request.contextPath }/images/new_021.jpg" border=0></TD> </TR> </TBODY> </TABLE> <TABLE cellSpacing=0 cellPadding=0 width="98%" border=0> <TBODY> <TR> <TD width=15 background=${pageContext.request.contextPath }/images/new_022.jpg><IMG src="${pageContext.request.contextPath }/images/new_022.jpg" border=0></TD> <TD vAlign=top width="100%" bgColor=#ffffff> <TABLE cellSpacing=0 cellPadding=5 width="100%" border=0> <TR> <TD class=manageHead>Current location: customer management > Customer List</TD> </TR> <TR> <TD height=2></TD> </TR> </TABLE> <TABLE borderColor=#cccccc cellSpacing=0 cellPadding=0 width="100%" align=center border=0> <TBODY> <TR> <TD height=25> <TABLE cellSpacing=0 cellPadding=2 border=0> <TBODY> <TR> <TD>Customer Name:</TD> <TD><INPUT class=textbox id=sChannel2 style="WIDTH: 80px" maxLength=50 name="cust_name" value="${param.cust_name }"></TD> <TD><INPUT class="button" id="sButton2" type="submit" name="sButton2"></TD> </TR> </TBODY> </TABLE> </TD> </TR> <TR> <TD> <TABLE id=grid style="BORDER-TOP-WIDTH: 0px; FONT-WEIGHT: normal; BORDER-LEFT-WIDTH: 0px; BORDER-LEFT-COLOR: #cccccc; BORDER-BOTTOM-WIDTH: 0px; BORDER-BOTTOM-COLOR: #cccccc; WIDTH: 100%; BORDER-TOP-COLOR: #cccccc; FONT-STYLE: normal; BACKGROUND-COLOR: #cccccc; BORDER-RIGHT-WIDTH: 0px; TEXT-DECORATION: none; BORDER-RIGHT-COLOR: #cccccc" cellSpacing=1 cellPadding=2 rules=all border=0> <TBODY> <TR style="FONT-WEIGHT: bold; FONT-STYLE: normal; BACKGROUND-COLOR: #eeeeee; TEXT-DECORATION: none"> <TD>Customer Name</TD> <TD>Customer Level</TD> <TD>Customer Source</TD> <TD>Contacts</TD> <TD>Telephone</TD> <TD>Mobile phone</TD> <TD>operation</TD> </TR> <s:iterator value="#pb.list"> <TR style="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none"> <TD>${cust_name }</TD> <TD>${cust_level }</TD> <TD>${cust_source }</TD> <TD>${cust_linkman }</TD> <TD>${cust_phone }</TD> <TD>${cust_mobile }</TD> <TD> <a href="${pageContext.request.contextPath }/customer?method=edit&custId=${cust_id}">modify</a> <a href="${pageContext.request.contextPath }/customer?method=delete&custId=${cust_id}">delete</a> </TD> </TR> </s:iterator> </TBODY> </TABLE> </TD> </TR> <TR> <TD><SPAN id=pagelink> <DIV style="LINE-HEIGHT: 20px; HEIGHT: 20px; TEXT-ALIGN: right"> //A total of [<B>${pb.totalCount} </B>] records, [<B>${pb.totalPage} </B>] pages ,Display per page <select name="pageSize"> <option value="15" <c:if test="${pb.pageSize==1 }">selected</c:if>>1</option> <option value="30" <c:if test="${pb.pageSize==30 }">selected</c:if>>30</option> </select> //strip [<A href="javascript:to_page(${pb.currentPage-1})">next page before</A>] <B>${pb.currentPage}</B> [<A href="javascript:to_page(${pb.currentPage+1})">The latter page</A>] //reach <input type="text" size="3" id="currentPage" name="currentPage" /> //page <input type="button" value="Go" onclick="to_page()"/> </DIV> </SPAN></TD> </TR> </TBODY> </TABLE> </TD> <TD width=15 background="${pageContext.request.contextPath }/images/new_023.jpg"><IMG src="${pageContext.request.contextPath }/images/new_023.jpg" border=0></TD> </TR> </TBODY> </TABLE> <TABLE cellSpacing=0 cellPadding=0 width="98%" border=0> <TBODY> <TR> <TD width=15><IMG src="${pageContext.request.contextPath }/images/new_024.jpg" border=0></TD> <TD align=middle width="100%" background="${pageContext.request.contextPath }/images/new_025.jpg" height=15></TD> <TD width=15><IMG src="${pageContext.request.contextPath }/images/new_026.jpg" border=0></TD> </TR> </TBODY> </TABLE> </FORM> </BODY> </HTML>