Struts 2 Learning Notes (Day 3)

Keywords: Attribute Struts Java Session

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>

Posted by Ionisis on Mon, 08 Jul 2019 14:14:44 -0700