Struts2培训笔记

7.25
---------
struts2

mvc开发模式

struts2是一个mvc框架

struts2与struts1
struts2封装了WebWork

struts2框架的优点
 提高了Action组件的灵活性(摆脱了框架api,Servlet容器的api的依赖性)
 提供了多种视图技术的整合
 提供拦截器和拦截器栈

struts2框架的主要结构
核心控制器
使用过滤器实现
实现组件为
 struts2.1.8版本以前使用
 org.apache.struts2.dispatcher.FilterDispatcher	 

 从struts2.1.8开始
 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter 

Action组件
 普通的JavaBean,可以选择继承或者不继承框架api

Result组件
 用于衔接视图响应技术,如jsp,freemarker,stream,json,表格,图表等

Interceptor组件(拦截器组件)
 用于封装通用的功能,可以在Action业务方法执行前后处理

struts2核心jar包
 struts2-core.jar

struts2框架配置
 Struts-default.xml(内置)
  在struts2-core.jar包下
  作用:预订义了一些Result组件Interceptor组件,拦截器栈

 xml定义结构
  元素,用于创建JavaBean对象时,为底层注入信息
  元素,用于存放Result,Interceptor,Action组件的定义
  元素,用于定义Result组件
  元素--【拦截器】,用于定义interceptor和interceptor-stack组件
  元素,用于定义Action组件

 struts.xml(自定义):DTD模板(struts2-core-2.1.8/struts-2.1.7.dtd)必须要有的
  要求定义在类加载路径下,配置结构和struts-default.xml相同
  作用:自定义定义的Result组件,Interceptor组件,Action组件

 default.properties(内置)
  struts-core-2.1.8.jar-org.apache.struts2包下
  作用:定义与框架相关的系统属性,如字符编码,请求后缀名等

 struts.properties(自动义) 不是必须要有的  
   定义在类加载路径下

使用需要修改内置的default.properties中的值有两种方法:
方法一:
 struts.properties 中 key=value 如:struts.action.extension=do
方法二:
 struts.xml中:
 


获得web组件
方法一:
 ActionContext
 代码:
Map session 
	= ActionContext.getContext().getSession();
Map application 
	= ActionContext.getContext().getApplication();
Map request 
	= (Map)ActionContext.getContext().get("request");

适配器模式:底层就是HttpSession

方法二:
ServletActionContext

HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext application = ServletActionContext.getServletContext();

方法三:
XxxAware

public class BaseAction extends ActionSupport implements ServletRequestAware,ServletResponseAware,ServletContextAware,SessionAware

XxxAction extends BaseAction

XxxAction 可以直接使用request response application seesion 对象

ActionSupport--返回值可以大写【SUCCESS = "success"】


struts.xml详细配置
修改default.properties(内置)中的值:
 

元素:相对路径 类加载器路径,作用就是包含其它的xml文件
 
 

元素:namespace
 /member/login.jsp
 /menager/login.jsp
 Action组件对应的请求格式:协议://ip:port/应用名/namespace名/Action组件名.后缀名
 
action中method没写,默认执行execute方法(ActionSupport中的方法)
result中的name 没写:默认值是SUCCESS
result中的type没写:默认是转发【default-struts】

元素:用于为包含他的对象注入信息
使用:Action中提供属性,提供get set方法

从Action中读值
${path}

7.26
-------
通配符*
元素的name属性可以使用*,表示任意字符
其他属性可以使用{1},{2}....{N}引用第N个*代表的信息

例子:

	/index.jsp

url访问路径:http://localhost:8080/struts2-1/user/opt_add.action



	/{3}.jsp


url访问路径:http://localhost:8080/struts2-1/user/opt_Opt_add_success.action


直接访问WEB-INF下的jsp文件
例子:

	/WEB-INF/a.jsp



	/WEB-INF/{1}.jsp


动态方法调用
请求格式
namespace名/Action名!业务方法名.后缀名

例子:
请求路径:http://localhost:8080/struts2-1/user/opt!add.action

	/index.jsp


struts2标签+ognl表达式
ognl开源项目【Object Graphic Navigation Language 对象图导航语言】

作用:通过一个字符串对对象进行操作

jar包:ongl.jar 在WebWork以前就存在
了解Ognl API
 getValue(String expression,Map context,Object root);
 setValue(String expression,Object root,Object value);

<%@ taglib uri="/struts-tags" prefix="s"%>

作用:
 可以访问对象属性  语法:对象.属性
 可以访问对象方法  语法:对象.方法()
 可以访问类中静态成员【静态方法 属性 内部类】 语法:@包名.类名@静态成员名
 可以对集合进行过滤操作 
    [n] 	返回下标为n的元素
    #this	表示集合中每一个元素
    ?		返回满足条件的所有元素
    ^		返回满足条件的第一个元素		
    $		返回满足条件的第最后一个元素
    %{}		先计算后取值
    .{}		对集合筛选

struts2中ValueStack结构
 Map context			request,session,application,parameter,临时变量
 CompoundeRoot root栈结构	放Action对象

struts2将Ongl方法分成了2个方法
 findString context
 findValue root

package org.apache.struts2.dispatcher;
public class StrutsRequestWrapper extends HttpServletRequestWrapper{
	public Object getAttribute(String key){
		Object val=super.getAttribute(key);
		if(val==null){
			//从Action的属性取值
			val=valuestack.findValue(key);
		}
		return val;
	}
}

class HttpServletRequestWrapper implements HttpServletRequest{
	
	private HttpServletRequest request;

	

	getAttribute(){
		return request.getAttribute();
	}

	setAttribute(){
		request.setAttribute();
	}

	getParamerter(){
		request.getParamerter();
	}
}

EL表达式问题:
 Struts2允许在页面使用EL表达式访问Action中的数据,
 原因是struts2将HttpServletRequets的实例封装了,
 并且重写了getAttribute方法,
 先调用super.getAttribute();
 如果找不到再访问ValueStack中root区域Action的属性

例子:
使用EL显示Action中name属性:${name }
使用EL显示Action中的msg属性:${msg }
name:
msg: 代码获得msg: <% String msg = (String)request.getAttribute("name"); if(null != msg) { out.print(msg); } %>
request:
requets.msg:
emp.name:
emp.name:${emp.name }
emp.name:
request.get("msg"):
PI:
ls中下标为1的值:
emps中满足id>4的所有元素:
ls中小表为i+1的元素: iterator if else elseif date 例子: 其它标签 <% request.setAttribute("abc","abc"); %> list <%--set标签用于向指定的范围设置一组值request,sessionapplication,context --%> <%-- {}表示数组 --%> <%-- #{}表示map --%>
  • =
  • 表单标签 重定向到Action form!showForm /form showForm 转发到Action form /form showForm 表单数据校验 ------- 数据格式检查分为客户端和服务器端两种 客户端:使用js,特点相应速度快,对客户友好,服务器压力小 缺点:安全性差 服务器端:使用服务器编程语言 特点:安全性高,其它全是缺点 50w以上考虑服务器端验证 使用struts2创建实现表单数据格式校验 1、基于java代码,表写校验规则 a:Action继承ActionSuppor,重写validate方法 在validate方法中可以使用addFieldError方法中添加错误消息 b:在struts.xml配置Action时,需要定义name为input的result c:input指定的result页面中,可以使用标签显示错误消息 表单标签也具有显示错误消息的功能,theme="xhtml" 注意:一个action的validate方法对所有action中的方法校验。 所以:Action中存在多个业务方法, 不同的业务方法需要不同的校验逻辑 可以使用validateXxx()命名格式的方法来校验 Xxx为业务方法名,首字母大写 检验流程的条用顺序: 获得请求数据-->类型转换-->setter--> validateXxx()-->validate()-->业务方法 -->result name="input" @Override public void validate() { System.out.println("validate()...."); if("".equals(username)) { this.addFieldError("username", "用户名不能为空!"); } if("".equals(password)) { this.addFieldError("password", "密码不能为空"); } } 2、基于xml配置,使用预订义好的校验器 xml文件和Action放在同一个包下 xml文件命名: Action类型-validation.xml Action类型-请求名-validation.xml xml文件遵守dtd规范(xwork-core-2.1.6/xwork-validator-1.0.3.dtd) xml校验配置分为字段型风格和非字段型风格 校验规则: 文件路径 (xwork-core-2.1.6.jar- com.opensymphony.xwork2.validator.validators -default.xml) required 非String类型使用,检查是否为空 requiredstring String类型使用,检查是否为空 int 范围检查 long 范围检查 short 范围检查 double 范围检查 date 范围检查 expression 非字段风格,跟ognl表达式匹配 fieldexpression 字段风格,跟ognl表达式匹配 email email格式检查,可以为空 url url格式检查 ,可以为空 visitor 用于检查复合类型 user.username conversion stringlength 字符串长度检查 regex 正则表达式匹配 conditionalvisitor 非字段型 username 用户名不能为空 password 密码不能为空 password 6 2 密码位数必须在${minLength}-${maxLength}位之间 字段型 用户名不能为空 密码不能为空 3 7 密码位数在${minLength}-${maxLength}之间 7.30 I18N 国际化 需要国际化的有:日期 数字 文字 java中需要使用这个类ResourceBundle来操作properties文件 文件编写格式: xxx.properties xxx_语言编码_国家编码.properties struts2中 JSP,Action,validation.xml中的文字要做国际化 需要修改的key值 default.propreties中 struts.custom.i18n.resources struts.xml配置 找到properties的文件 JSP中使用国际化 使用 文本框中的label中文,把label换成key 其它标签一样 代码: Action中国际化【Action必须要要继承ActionSupport】 String s = this.getText(""); validation.xml中国际化 国际化 日期 数字 文字 Java代码: //日期 Date date = new Date(); System.out.println(date); //格式化日期 getDateTimeInstance 会调用Locale.getDefault() DateFormat format = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL); System.out.println(format.format(date)); //获得当前默认的语言 System.out.println(Locale.getDefault()); //获得计算机所有语言 Locale[] locales = Locale.getAvailableLocales(); for(Locale locale:locales) { System.out.println(locale.getCountry()+" "+locale.getLanguage()); } //数字 double d = 2131231321313.23; NumberFormat format1 = NumberFormat.getNumberInstance(); System.out.println(format1.format(d)); //货币 format1 = NumberFormat.getCurrencyInstance(); System.out.println(format1.format(d)); //获得文件的路径 URL url = Test.class .getClassLoader() .getResource("i18n/info.properties"); System.out.println(url); Test.class .getClassLoader() .getResourceAsStream("i18n/info.properties"); //相对于src路径 ResourceBundle rb = ResourceBundle.getBundle("i18n/info"); System.out.println(rb.getString("a"));; // Properties p=new Properties(); // p.load(in); // // System.out.println(p.getProperty("a")); 异常处理: 手动异常 业务异常 this.addActionError("用户名或密码错误"); Action异常 Action中抛出异常 struts默认不处理异常 需要配置struts.xml /login1.jsp jsp中获取异常消息 全局异常 当前包中都可以用 顺序不能反 不同的包 有相同的异常 也可以写在单独的包 其它包extends继承使用 配置文件properties 预订义的配置文件 struts.properties 整个应用可以访问 package.properties 当前包有效 Action类名.properties 当前action有效 自定义的配置文件 struts.properties struts.xml 属性类型转换 struts2框架默认支持的类型: String String[] List 基本类型 包装类型 List<包装类型> ognl表达式表示的复合类型 如:user.username 自定义【其它类型】 编写规则 写个类继承StrutsTypeConverter 类加载路径下 创建xwork-conversion.properties 类型=规则 在国际化文件中 创建Action类名.properties文件 写入:invalid.fieldvalue.xxx=消息【xxx表示属性名】 获得请求数据-->类型转换-->setter-->validateXxx()-->validate()-->业务方法 --->conversionError拦截器负责处理错误消息-->result name="input" 拦截器 拦截器的作用 用于在执行Action组件业务处理之前和之后调用 可以将和业务处理相关的通用处理封装成拦截器, 从而达到服用以及模块化管理 AOP 自定义拦截器 编写拦截器类,实现Interceptor接口或者继承AbstractInterceptor String methodName = invocation.getProxy().getMethod(); HttpServletRequest request = ServletActionContext.getRequest(); //执行下一个组件,将下一个组件的返回值返回或者将下一个组件的异常返回 String result = invocation.invoke(); 在struts.xml中配置拦截器 包中 引用拦截器 action中 注意:如果Action显示引用自定义拦截器,默认的拦截器不起作用 在引用默认包中的拦截器 方法过滤功能的拦截器 要求:拦截器类继承MethodFilterInterceptor类 在struts.xml中配置拦截器 引用拦截器 execute*,modify*,remove* add* 面向过程 面向对象 面向接口 面向切面 面向惯例 了解内置拦截器: autowiring 自动装配拦截器: 主要用于当struts2和spring整合时,struts2可以使用自动装配方式 来访问spring容器中的Bean chain链拦截器:构建一个Action链,放到ValueStack的root区域, 和 一起使用 conversionError转换错误拦截器:负责处理类型转换错误的拦截器 clearSession清除Session拦截器:负责销毁HttpSession对象 createSession创建Session拦截器:负责创建一个HttpSession对象 exception异常拦截器:将Action抛出的异常映射到结果 fileUpload文件上传拦截器:用于处理文件上传 i18n国际化拦截器:负责把用户所选的语言和区域存放到Session中 params参赛交互过滤拦截器:最基本的拦截器,负责解析Http请求中的数据, 并注入到Action中,必须要有。 staticParams静态参数拦截器:负责将xml文件中Action标签下的 标签中的参数注入到Action token令牌拦截器:负责阻止表单重复提交 tokenSession令牌会话拦截器:负责阻止表单重复提交 validation验证拦截器:负责处理XxxAction-validation.xml校验 workflow工作流拦截器:负责处理validate()方法校验 checkbox复选框拦截器:负责处理复选框提交的数据设置成boolean类型 fileUpload拦截器 struts2中的Action代码 private File f; private String fFileName; public String execute() throws Exception { System.out.println(name); String path = application.getRealPath("upload"); // FileUtil.copy(f, path+"/"+fFileName); f.renameTo(new File(path,fFileName)); return SUCCESS; } Util包 public class FileUtil { public static void copy(File src,String dest) { BufferedInputStream bis = null; BufferedOutputStream bos = null; try { bis = new BufferedInputStream(new FileInputStream(src)); bos = new BufferedOutputStream(new FileOutputStream(dest)); byte[] b = new byte[2048]; int i; while((i=bis.read(b)) != -1) { bos.write(b,0,i); } } catch (Exception e) { } } } 7.31 ---------- 限制上传文件的类型 struts.xml配置 .txt,.ppt /upload.jsp /upload.jsp name值:maximumSize allowedTypes allowedExtensions 消息错误,配置国际化,编写properties文件 key有四种: struts.messages.error.file.extension.not.allowed struts.messages.error.content.type.not.allowed struts.messages.error.file.too.large struts.messages.error.uploading token/tokenSession拦截器【防止表单重复提交】 客户端:提交按钮后设置按钮为disable不可用,IE浏览器要加一步手动提交表单 服务器:用验证码来防止表单重复提交 默认的defaultStack中没有token拦截器 token用法: struts.xml中引用taken拦截器 jsp中 写一行代码 报404 用result重新指向一个页面 tokenSession区别:不报404自己会访问上一次页面 struts.xml代码: /index.jsp Result组件 ----------- 执行完Action后执行Result组件 案例:输出JSON数据 自定义: 编写Result实现类,使用Result接口或继承StrutsResultSupport 需要jar包:json-lib-2.1.jar 步骤: JSONResult代码: 1、获得Action对象 Object action = invocation.getAction(); 2、将Action中的数据转换成json字符串 String jsonStr = JSONUtil.toJson(action); 3、获得response对象 HttpServletResponse response=ServletActionContext.getResponse(); 4、设置response的contentType text/json;charset="utf-8"; response.setContentType("text/json;charset=utf-8"); 5、将json字符串写回给客户端 PrintWriter out = response.getWriter(); out.write(jsonStr); out.flush(); Action:中提供数据就行 struts.xml中代码: emp 官方包中提供了转换JSON的Result组件 struts2-json-plugin-2.1.8.jar-struts-plugin.xml 相关使用 get方法上加 @JSON(serialize=false) JSON字符串中不显示该属性 @JSON(name="name") 修改显示的名字 Result组件 ----------- web组件:dispatcher redirect Action组件:chain redirectAction chain的原理:是valueStack将两个action同时放入到root区域 Action中要有相同的属性 属性共享 struts.xml相关配置 a2 /chain.jsp stream --------- 做下载功能: name=inputName--告诉struts下载哪个流下面的文件 【当action有两个以上的输入流时,如果名字为InputStream时不许要写,莫恶人是这个】 attachment--附件意思 代码: Action: private InputStream fstream; private String fileName; public String execute() throws Exception { String path=application.getRealPath("WEB-INF/tomcat_admin.rar"); fstream=new FileInputStream(path); fileName="tomcat.rar"; return SUCCESS; } struts.xml配置: fstream attachment;filename=${fileName} 2048 做验证码: Action中代码: private InputStream imageSteam; private String s = "0123456789abcdefghigkinmopqrstuvwxyz"; public String execute()throws Exception { BufferedImage image = new BufferedImage(80, 30, BufferedImage.TYPE_INT_BGR); Graphics graphics = image.getGraphics(); graphics.setColor(Color.red); graphics.fillRect(0, 0, 80, 30); graphics.setColor(Color.yellow); graphics.setFont(new Font("宋体", Font.BOLD+Font.ITALIC, 20)); StringBuffer sb = new StringBuffer(); Random random = new Random(); for(int i=0;i<5;i++) { int index = random.nextInt(s.length()); sb.append(s.charAt(index)); } graphics.drawString(sb.toString(), 8, 25); session.put("code",sb.toString()); ByteArrayOutputStream dest = new ByteArrayOutputStream(); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(dest); encoder.encode(image); imageSteam = new ByteArrayInputStream(dest.toByteArray()); return SUCCESS; } JSP中代码: struts.xml中的代码: imageSteam /index.jsp /image.jsp 补充 ------------------ eclipse添加dtd文件: window-preferences-xml(搜索)-xml catalog extension 扩展名 重定向:两次请求 转发:一次请求 servlet 实例化两种情况(第一次调用,服务器启动[]) servlet生命周期:初始化-init(有参) 数字精确计算,尤其是银行系统计算 BigDecimal b1 = new BigDecimal("12.345"); BigDecimal b2 = new BigDecimal("12"); System.out.println(b1.subtract(b2)); //0.345 BigInteger i1 = new BigInteger("123132131231231312312313123"); BigInteger i2 = new BigInteger("123132131231231312312313123"); System.out.println(i1.subtract(i2)); //0 //告诉容器,以utf-8编码解析请求体中的数据 request.setCharacterEncoding("utf-8"); //告诉浏览器,以utf-8编码解析响应数据,并以utf-8编码打开 response.setCharacterEncoding("utf-8"); //告诉容器,响应数据格式为text/html的编码为utf-8,并且以utf-8编码传输 //以utf-8编码解析响应数据,并以utf-8编码打开 response.setContentType("text/html;charset=utf-8"); get请求数据在请求头中 只有iso8859-1字符集 post请求数据在请求体中 <%@include file="/index.jsp"> //编译期间 进入字符串代码:选中字符串-ctrl+shirt+t 转发到另一个action type=“china” 重定向到另一个action type="redirectAction" properties 只有一个字符编码 iso8859-1 不能写中文 能写中文是myeclipse装了插件 cmd native2ascii 注册 == \u6CE8\u518C 当前文件-rt.jar-环境变量 file相对路径是 相对运行java程序的路径 Test.class.getClassLoader().getResource(); js中的调用方法传参问题: for(var i=0;i

    你可能感兴趣的:(培训笔记)