//导包 //配置WEB.XML <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter .StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> */ </filter-mapping> //加入struts.xml到src下 <struts> //配置扩展名 <constant name="struts.action.extension" value="do"></constant> //package:struts2使用package来组织模块 //name属性:必须,用于其他的包引用当前包,一定要与项目名一致 //extends:继承,可以继承所有的配置,通常继承struts-default //namespace:可选,若定义了,必须把namespace加进url //http://localhost:8080/contextPath/namespace/actionName.action <package name="helloWorld" extends="struts-default"> <action name="product-input"> <result>/WEB-INF/pages/input.jsp</result> </action> //class是实体类,默认值是:com.opensymphony.xwork2.ActionSupport, //method为调用的方法,默认值execute() ,返回值为SUCCESS //result返回结果 <action name="product-save" class="com.gmy.entiy.Product" method="save"> //type是类型 dispatcher转发 redirect重定向 redirectAction重定向到一个 //Action chain转发到一个Action 默认值是dispatcher <result name="details" type="dispatcher">/WEB-INF/pages/details.jsp</result> //重定向到Action <result name="index" type="redirectAction"> <param name="actionName">testAction</param> <param name="namespace">/gmy</param> </result> //redirect重定向可以 但是chain转发不可以 通过这种方式 <result name="index" type="redirect">/gmy/testAction.do</result> </action> </package> <package name="helloWorld" extends="struts-default" namespace="/gmy"> <action name="testAction"> <result>/WEB-INF/pages/input.jsp</result> </action> </package> </struts> //表单页面 //input中的name属性一定要和实体类中的变量对应 <form action="product-save.action" method="post"> ProductId:<input type="text" name="productName"> <br><br> ProductDesc:<input type="text" name="productDesc"> <br><br> ProductPrice:<input type="text" name="productPrice"> <br><br> <input type="submit" value="提交"> </form> //实体类‘ public class Product { private Integer productId;//变量一定要和name属性对应 private String productName; private String productDesc; private double productPrice; //geter、seter方法 //必须要一个空参数构造器,供反射用 } //Servlet API解耦方式 //ActionContext //上下文对象 ActionContext context = ActionContext.getContext(); //application Map<String, Object> application = context.getApplication(); application.put("applicationString", "applicationString"); //session Map<String, Object> session = context.getSession(); session.put("sessionString", "sessionString"); //request Map<String, Object> request = (Map<String, Object>) context.get("request"); request.put("requestString", "requestString"); //parameters取不到值 //parameters只能读不能写 Map<String, Object> parameters = context.getParameters(); parameters.put("parametersString", "parametersString"); System.out.println(((String[])parameters.get("name"))[0]); System.out.println(((String[])parameters.get("sex"))[0]); //实现XXXAware接口 private Map<String, Object> application; private Map<String, Object> session; private Map<String, String[]> parameters; private Map<String, Object> request; public String tests(){ application.put("applicationString", "application1"); session.put("sessionString", "session"); //不能设值 parameters.put("parametersString", new String[]{"gmy1","gmy2"}); request.put("requestString", "request"); System.out.println(((String[])parameters.get("name"))[0]); return "success"; } @Override public void setApplication(Map<String, Object> application) { this.application = application; } @Override public void setParameters(Map<String, String[]> parameters) { this.parameters = parameters; } @Override public void setRequest(Map<String, Object> request) { this.request = request; } @Override public void setSession(Map<String, Object> session) { this.session = session; } //Servlet API耦合方式 //使用ServletAcionContext HttpServletRequest request = ServletActionContext.getRequest(); HttpSession session = request.getSession(); ServletContext servletContext = ServletActionContext.getServletContext(); //实现ServletXXXAware接口 private HttpServletResponse response; private ServletContext context; private HttpServletRequest request; public String tests(){ return "success"; } @Override public void setServletResponse(HttpServletResponse response) { this.response = response; } @Override public void setServletContext(ServletContext context) { this.context = context; } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } //值栈 //${}取得是值栈中的内容,并不是request中的 //两个逻辑部分 //Map栈:实际上是OgnlContext类型,是个Map,也是ActionContext的引用, //里面保存各种Map:requestMap,sessionMap,applicationMap,parametersMap,attr //读取:可以使${requestScope.对象.属性},也可以通过<s:property //value="#request.对象.属性"> //对象栈:实际上是CompoundRoot类型,是一个使用ArrayList定义的栈, //里边保存各种和当前Action示例相关的对象,是一个数据结构意义的栈 //读取:可以用${name},也可以用<s:property value="[0].name">从栈里面第几个开始读 //调用public类的静态字段默认是true例如<s:property value="@java.lang.Math@PI">, //调用public静态方法默认是false,必须配置<s:property value="@java.lang.Math@cos(0)"> //使用对象栈方法为属性赋值<s:property value="调用seter方法"> //异常 <global-results> <result name="input"></result> </global-results> <global-exception-mappings> <exception-mapping result="input" exception="java.lang.ArithmeticException"> </exception-mapping> </global-exception-mappings> //对于Map栈,打印request,session,application,parameters的某个属性值或某个请求参数 <s:property value="#session.date"> <s:property value="#parameters.date[0]"> //创建一个URL字符串 <s:url value"/getProduct" var="url"> <s:param name="productId" value="2002"></s:param> </s:url> //取值栈中的属性,对于value值自动ognl解析,若不进行,用单引号 <s:url value"/getProduct" var="url"> <s:param name="productId" value="productId"></s:param> </s:url> //set标签:在request,session,application,page域加入属性值 <s:set name="productName" value="productName" scope="request"></s:set> productName:${requestScope.productName} //push标签:把对象在标签开始后压入到值栈中,在标签结束时,弹出值栈 <s:push value="#request.person"> ${name}//这里取值有效 </s:push> ${name}//这里取值无效 //if,else标签,可以直接是使用值栈中的属性 <s:if test="productPrice > 1000"> I7处理器 </s:if> <s:elseif test="productPrice >800"> I5处理器 </s:elseif> <s:else> I3处理器 </s:else> //iterator标签:遍历集合,把集合的每个元素放到栈顶 <s:iterator value="#request.person"> ${name}-${age}//取得到 </s:iterator> ${name}-${age}//取不到 //sort标签:可以对集合元素进行排序 <s:srot comparator="#request.comparator" source="persons" var="persons2"></s:sort> //date标签:可以对Date对象进行排版 <s:date name="#session.date" format="yyyy-MM-dd hh:mm:ss" var="date2"/> date:${date2} //a:标签:用%{}都属性进行强制ognl解析 <s:a href="getPerson.action?name=%{name}">${}</s:a> //表单标签:可以自动回显 <s:form action="save"> <s:hidden name=""></s:hidden> <s:textfield name="userName" label="UserName"></s:textfield> <s:password name="password" label="Password"></s:password> <s:textarea name="desc" label="Desc"></s:textarea> <s:submit></s:submit> </s:form> //checkbox标签: <s:checkbox name="married" label="Married"></s:checkbox> //radio标签:使用#{}创建Map <s:radio name="gender" list="#{'1':'Male','0':'Female'}" label="Gender"></s:radio> //checkboxlist标签: <s:checkboxlist list="#request.cities" listKey="cityId" listValue="cityName" label="City" name="city"></s:checkboxlist> //select标签:使用{}创建LIST <s:select list="{11,12,13,14,15,16,17,18,19,20}" headerKey="" headerValue="请选择" label="Age" name="age"> <s:optgroup label="21-30" list="#{21:21}"></s:optgroup> <s:optgroup label="31-40" list="#{31:31}"></s:optgroup> </s:select> //theme属性 //可以在标签中增加theme属性 //在request.setAttribute("theme","simple"); //可以改成全局的在struts.xml 默认是xhtml <constant name="struts.ui.theme" value="simple"></constant> //例 //加入Jar包 //配置web.xml <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter .StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern>*/ </filter-mapping> //配置struts.xml <struts> //配置扩展名 <constant name="struts.action.extension" value="do,"></constant> <package name="s2-5" extends="struts-default"> //自定义拦截器栈 <interceptors> <interceptor-stack name="gmy"> <interceptor-ref name="paramsPrepareParamsStack"> <param name="prepare.alwaysInvokePrepare">false</param> </interceptor-ref> </interceptor-stack> </interceptors> <default-interceptor-ref name="gmy"/> <action name="emp-*" class="com.gmy.app.EmployeeAction" method="{1}"> <result name="{1}">emp-{1}.jsp</result> <result type="redirectAction">emp-list</result> </action> </package> </struts> //EmployeeAction public class EmployeeAction implements RequestAware,ModelDriven<Employee>, Preparable{ private Dao dao = new Dao(); private Employee emp; public String update(){ dao.update(emp); return "success"; } public void prepareUpdate(){ emp = new Employee(); } public String edit(){ return "edit"; } public void prepareEdit(){ emp = dao.get(empId); } public String save(){ dao.save(emp); return "success"; } public void prepareSave(){ emp = new Employee(); } public String delete(){ dao.delete(empId); return "success"; } public String list(){ arg0.put("emps", dao.getEmployees()); return "list"; } private Integer empId; public void setEmpId(Integer empId) { this.empId = empId; } private Map<String, Object> arg0; @Override public void setRequest(Map<String, Object> arg0) { this.arg0 = arg0; } @Override public Employee getModel() { if(empId == null) emp = new Employee(); else emp = dao.get(empId); return emp; } @Override public void prepare() throws Exception { System.out.println("prepare..."); } } //Dao public class Dao { private static Map<Integer, Employee> emps = new LinkedHashMap<Integer, Employee>(); static{ emps.put(1001, new Employee(1001, "AA", "AA", "[email protected]")); emps.put(1002, new Employee(1002, "BB", "BB", "[email protected]")); emps.put(1003, new Employee(1003, "CC", "CC", "[email protected]")); emps.put(1004, new Employee(1004, "DD", "DD", "[email protected]")); emps.put(1005, new Employee(1005, "DD", "DD", "[email protected]")); emps.put(1006, new Employee(1006, "EE", "EE", "[email protected]")); emps.put(1007, new Employee(1007, "FF", "FF", "[email protected]")); emps.put(1008, new Employee(1008, "GG", "GG", "[email protected]")); emps.put(1009, new Employee(1009, "HH", "HH", "[email protected]")); emps.put(10010, new Employee(10010, "II", "II", "[email protected]")); } public List<Employee> getEmployees(){ return new ArrayList<Employee>(emps.values()); } public void delete(Integer empId){ emps.remove(empId); } public void save(Employee emp){ emp.setEmpId((int)System.currentTimeMillis()); emps.put(emp.getEmpId(), emp); } public Employee get(Integer empId){ return emps.get(empId); } public void update(Employee emp){ emps.put(emp.getEmpId(), emp); } } //Employee public class Employee { private Integer empId; private String firstName; private String lastName; private String email; public Integer getEmpId() { return empId; } public void setEmpId(Integer empId) { this.empId = empId; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Employee(Integer empId, String firstName, String lastName, String email) { super(); this.empId = empId; this.firstName = firstName; this.lastName = lastName; this.email = email; } public Employee() { // TODO Auto-generated constructor stub } } //index.jsp <body> <a href="emp-list.do">Emp List</a> </body> //emp-list.jsp <body> <!-- private Integer empId; private String firstName; private String lastName; private String email; --> <s:debug></s:debug> <s:form action="emp-save.do"> <s:textfield name="firstName" label="FirstName"></s:textfield> <s:textfield name="lastName" label="LastName"></s:textfield> <s:textfield name="email" label="Email"></s:textfield> <s:submit></s:submit> </s:form> <br><br> <table cellpadding="10" cellspacing="0" border="1"> <thead> <tr> <td>ID</td> <td>FirstName</td> <td>LastName</td> <td>Email</td> <td>Edit</td> <td>Delete</td> </tr> </thead> <tbody> <s:iterator value="#request.emps"> <tr> <td>${empId}</td> <td>${firstName}</td> <td>${lastName}</td> <td>${email}</td> <td><a href="emp-edit.do?empId=${ empId}">Edit</a></td> <td><a href="emp-delete.do?empId=${ empId}">Delete</a></td> </tr> </s:iterator> </tbody> </table> </body> //emp-edit.jsp <body> <s:form action="emp-update.do"> <s:hidden name="empId" ></s:hidden> <s:textfield name="firstName" label="FirstName"></s:textfield> <s:textfield name="lastName" label="LastName"></s:textfield> <s:textfield name="email" label="Email"></s:textfield> <s:submit></s:submit> </s:form> </body> //错误消息显示 //1、继承ActionSupport //2、配置<result name="input">标签 //3、在Action所在包内创建properties文件,例如UserAction.java,UserAction //.properties,UserAction.properties增加内容invalid.fieldvalue.age=... //可以通过debug标签看值栈中的属性 ,${fieldErrors.age[0]} //也可以通过标签<s:fielderror filedName="age"></s:fielderror> //提出ul li span,在src下,新建template.simple包,在新建fielderror.ftl文件 <#if fieldErrors??><#t/> <#assign eKeys = fieldErrors.keySet()><#t/> <#assign eKeysSize = eKeys.size()><#t/> <#assign doneStartUlTag=false><#t/> <#assign doneEndUlTag=false><#t/> <#assign haveMatchedErrorField=false><#t/> <#if (fieldErrorFieldNames?size > 0) ><#t/> <#list fieldErrorFieldNames as fieldErrorFieldName><#t/> <#list eKeys as eKey><#t/> <#if (eKey = fieldErrorFieldName)><#t/> <#assign haveMatchedErrorField=true><#t/> <#assign eValue = fieldErrors[fieldErrorFieldName]><#t/> <#if (haveMatchedErrorField && (!doneStartUlTag))><#t/> <#assign doneStartUlTag=true><#t/> </#if><#t/> <#list eValue as eEachValue><#t/> <#if parameters.escape>${eEachValue!?html}<#else>${eEachValue!}</#if> </#list><#t/> </#if><#t/> </#list><#t/> </#list><#t/> <#if (haveMatchedErrorField && (!doneEndUlTag))><#t/> <#assign doneEndUlTag=true><#t/> </#if><#t/> <#else><#t/> <#if (eKeysSize > 0)><#t/> <#list eKeys as eKey><#t/> <#assign eValue = fieldErrors[eKey]><#t/> <#list eValue as eEachValue><#t/> <#if parameters.escape>${eEachValue!?html} <#else>${eEachValue!}</#if> </#list><#t/> </#list><#t/> </#if><#t/> </#if><#t/> </#if><#t/> //自定义转换器 //国际化 //在struts.xml文件中加入<constant name="struts.custom.i18n.resources" // value="i18n"></constant> //在src下新建i18n_en_US.properties和i18n_zh_CN.properties文件 //在标签中不使用label标签,而使用key标签,label中要使用的必须label="%{getText('submit')}" //通过超链接来切换语言 <a href="testI18n.action?request_locale=en_US">English</a> <a href="testI18n.action?request_locale=zh_CN">中文</a> //验证文件 //1、将struts-2.3.20\apps\struts2-blank\WEB-INF\classes\example下 //的Login-validation.xml复制到Action所在包下 //把Login的名字改为当前Action的名字 <field name="age"> <field-validator type="int"> <param name="min">20</param> <param name="max">50</param> <message key="">..${min}.${max}...</message>//也是使用国际化 </field-validator> </field>