JavaWeb常用开发技术总结-js、spring、javabean、mysql数据库、dwr的使用等
来源:互联网 发布:淘宝上买气排会怎么样 编辑:程序博客网 时间:2024/05/21 02:11
JaveWeb 程序开发
一、 表单及表单元素
a) 文本框的应用:
<inputtype="password" name="userPass"style="font-family:Wingdings; width:139;" onpaste="returnfalse" oncut="return false" oncopy="return false"/>
不能复制,剪贴,黏贴一般用于密码框!
二、 窗口与导航条
a) 打开一个窗口自动关闭:
i. 父页面:
window.open("child.html","新的窗口","width=500;heigth=300;top=10;left=10")
ii. 子页面为body的onload 事件添加:
onload="window.setTimeout('window.close()',5000);";
b) 弹出窗口居中显示
function shownewpage(){ varhc=window.open("child.html","新的窗口","width=500;height=300;"); varwidth=screen.width; varheigth=screen.height; hc.moveTo((width-500)/2,(heigth-300)/2);}
c) 关闭窗口时,刷新父窗口
Window.opener.location.reload();
Window对象的opener 属性返回一个引用,表示返回打开这个子窗口的窗口的!所有通过它可以调用打开它的窗口的属性!
d) 弹出模式对话框
varresult=window.showModalDialog("child.html","","dialogWidth=407;dialogHeight=257;");
然后再模式对话框里:
parent.window.returnValue=document.form1.userPass.value;window.close();
e) 弹出全屏的模式对话框
var width=screen.width;var height=screen.height;varresult=window.showModalDialog("child.html","全屏的模式对话框","Dialogwidth="+width+";Dialogheight="+height+";");
三、 JavaScript函数:
a) 小写的金额转换为大写的金额
<script language="javascript"type="text/javascript"> functionchangeMoneyStr(str){ varbasestr="零壹贰叁肆伍陆柒捌玖"; varbasecw="万仟佰拾亿仟佰拾万仟佰拾元角分"; varnewstring=(str*100).toString(); newstringlog=newstring.length; newdw=basecw.substr(basecw.length-newstringlog); window.alert(newdw); varnum0=0; wan=0; dxje=""; for(vari=1;i<=newstringlog;i++){ xzf=newstring.substr(i-1,1);//小写金额 dzf=basestr.substr(xzf,1);//大写金额 dw=newdw.substr(i-1,1);//单位 if(dzf=="零"){ dzf=""; if(dw=="亿"){ }elseif(dw=="万"){ dzf=""; wan=1; }elseif(dw=="元"){ }else{ dw=""; } num0=num0+1; }else{ if(num0-wan>0){ dzf='零'+dzf; } num0=0; } dxje=dxje+dzf+dw; } if(newstring.length!=1){ if(newstring.substr(newstring.length-2)=="00"){ dxje=dxje+'整'; }else{ dxje=dxje; } } returndxje; } function showpigresult(){ varresult=changeMoneyStr(document.form1.money.value); document.getElementById("showresult").innerHTML=result; } </script>
四、 JavaBean技术
a) String类的 split() 应注意的地方:
1、如果用“.”作为分隔的话,必须是如下写法:String.split("\\."),这样才能正确的分隔开,不能用String.split(".");
2、如果用“|”作为分隔的话,必须是如下写法:String.split("\\|"),这样才能正确的分隔开,不能用String.split("|");
“.”和“|”都是转义字符,必须得加"\\";
3、如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如:“acount=? and uu=? or n=?”,把三个都分隔出来,可以用String.split("and|or");
五、 正则表达式在JAVA中的应用:
Pattern p = Pattern.compile("a*b");Matcher m = p.matcher("aaaaab"); sboolean b = m.matches();在仅使用一次正则表达式时,可以方便地通过此类定义 matches 方法。此方法编译表达式并在单个调用中将输入序列与其匹配。
语句 boolean b = Pattern.matches("a*b","aaaaab");等效于上面的三个语句,尽管对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式。
此类的实例是不可变的,可供多个并发线程安全使用。Matcher 类的实例用于此目的则不安全。
六、 MySQL数据库
1.选择唯一值:
selectdistinct * from student;
2.为某一列取别名,不能使用as :
selectstuScore*0.9 '结果'from student order by stuScore desc;
3.条件查询:
select* from student where stuAddress!='泾阳';
4.范围查询:
select* from student where stuScore between 80 and 100;
5.自增长标识列:
auto_increment;
6.选择来自一个集合的数据:(当集合中的数据不存在时,不会出现异常!)
select* from student where stuId in(1,2);
7.识别null数值或isnull :
select* from student where stuScore is not null;
8.模糊查询:
select * from student where stuName like'高%';
9.分组条件:(可以不查出stuAddress)
select * from student group by stuAddress
having count(*)>3;
10.查询最大值:
select max(stuScore) '最大分数' from student;
11.实现四舍五入到指定长度:
select round(100.12345,3);
12.显示当前时间(获取系统的当前时间):
select now();
13.日期函数:
selectmonth(),year(),dayofmonth();
selectdayofmonth(now());
七、 JSP部分:
a) 使用 application内置对象读web.xml 中的参数:
Web.xml 中如下:
<context-param> <param-name>driver</param-name> <param-value>com.jdbc.mysql.Driver</param-value> </context-param> <context-param> <param-name>uri</param-name> <param-value>jdbc:mysql://localhost:3306/shopping</param-value> </context-param> <context-param> <param-name>user</param-name> <param-value>root</param-value> </context-param><context-param> <param-name>pwd</param-name> <param-value>root</param-value></context-param>
上面就是在 web.xml 中配置将要读取的的全局参数! 下面使用 application 进行读取并显示到页面上:
Servlet中的代码:
String driver =getServletContext().getInitParameter("driver"); Stringuri=getServletContext().getInitParameter("uri"); Stringuser=getServletContext().getInitParameter("user"); Stringpwd=getServletContext().getInitParameter("pwd");
通过上面的连个步骤就可以读取全局变量!
b) 使用 config 对象,读取servlet的参数:
不管是Jsp页面还是servlet, config内置对象代表翻译之后的的 .java 本身!这种方法读取参数的使用场合:字符过滤器:
Serlet 中的配置如下:
<servlet> <servlet-name>config</servlet-name> <servlet-class>config</servlet-class> <init-param> <param-name>charset</param-name> <param-value>utf-8</param-value> </init-param> </servlet>
在serlvet 中的代码如下:
Stringcharset=this.getServletConfig().getInitParameter("charset");
c) request 对象:
使用 request.getParameterMap() 可以获取请求的Map 集合对象;使用request应注意以下情况:
并不是每个表单域都可以生成请求参数的,只有有name属性的表单域才可以生成请求参数的!如果多个表单域的name值相同,则生成一个请求参数;表单域的name属性为请求参数的名,value属性值为请求的值;如果某个表单的disabled=”true”则该表单不在生成请求参数!
Map<String,Object>res=request.getParameterMap(); Iterator<?>iter=res.keySet().iterator(); while(iter.hasNext()) { Stringstr=iter.next().toString(); System.out.println(str); }
使用如上代码获取请求信息的Map<String,String> 对象!为什么我们在jsp中设置的请求参数,不管是在 jsp中还是在 servlet中都可以获得到;原因就在于;系统将我们的请求参数放入了一个Map,不管是在jsp中还是在 servlet 总我们都是访问的这个map对象;
Stringqstr=request.getQueryString(); System.out.println(qstr); StringstrE=java.net.URLDecoder.decode(qstr,"utf-8"); System.out.println(strE); String []arrayStr=strE.split("&"); for (Stringstring : arrayStr) { System.out.println("每个请求参数的值,对"+string); String []subStr=string.split("="); System.out.println("名称:"+subStr[0]); System.out.println("值"+subStr[1]); }
Request 对象的 getQuaryString() 方法,可以获取请求字符串,java.net.Decoder.decode()用于解码(原因是在请求参数中含有非西欧字符的参数,所以要使用java.net.Decoder.decode()进行解码);
使用getRequestDispatcher(“{0}”).forward()跳转时,要在 0 处的项目资源加 ‘/’;
d) response 对象:
比较request.getRequestDispatcher().forward(request,response)与response.sendRedirect():
Forward 执行完之后还是上一次的请求,而redirect 后生成第二次请求;forward 请求后,目标页面可以访问请求的请求参数,因为是同一个request请求,即所有的请求参数在同一个 request对象中都存在,而使用 redirect 后目标页面不能使用原来的请求参数,因为已经是第二次请求了,那也就是说,request对象的消失,请求的参数就会跟着消失;还有使用 forward 请求 url 中的地址不会改变. 而使用 redirect 会改变为目标的 url;
e) cookie 的读写:
写入 cookie 对象:ss
//设置临时Cookie
Cookie tempCookie=newCookie("temp","222222"); tempCookie.setMaxAge(-1); //默认值,不会把 Cookie 保存到硬盘上 response.addCookie(tempCookie); //设置 MaxAge 为 0 的 Cookie Cookie cookie=newCookie("cookie","111111"); cookie.setMaxAge(0); //表示浏览器接受 Cookie 后会被立即删除 response.addCookie(cookie); //设置永久的 Cookie Cookie mcookie=newCookie("name","000000"); mcookie.setMaxAge(60*60*24); response.addCookie(mcookie);
读取 cookie 对象:
protectedCookie getCookie(Cookie [] cookies,String name){ if(cookies!=null){ for(Cookie c : cookies) { if(c.getName().equals(name)){ returnc; } } } returnnull; } PrintWriter out = response.getWriter(); //获得临时的 Cookie Cookie temp=getCookie(request.getCookies(),"temp"); if(temp!=null){ out.print("临时Cookie的值为:"+temp.getValue()); }else{ out.print("没有值!"); } //获取时间为 0 的Cookie,这个 Cookie永远都不可能获得到 Cookiecookie=getCookie(request.getCookies(), "cookie"); if(cookie!=null) { out.print("MaxAge为零的Cookie:"+cookie.getValue()); }else { out.print("没有值!"); } //获取永久的Cookie Cookiename=getCookie(request.getCookies(), "name"); if(name!=null) { out.print("永久Cookie 值:"+name.getValue()); }else { out.print("没有值!"); }
在cookie中写的时候对汉字的处理:
添加之前将字符串使用java.net.URLEncoder.encode("高江涛","utf-8"); 取出来之后将结果java.net.URLDecoder.decode(temp.getValue(),"utf-8");
f) 自定义标签:
传统的Jsp脚本有什么坏处:
i. Jsp 脚本非常丑陋,难以阅读!
ii. Jsp 脚本和 HTML 代码混杂,维护成本高!
iii. HTML 页面中嵌入 Jsp 脚本,导致美工难以参加开发!
g) 自定义标签的开发步骤:
i. 建立自定义标签的处理类;
ii. 建立一个 *.tld 文件,每一 tld文件都对应一个标签库,每个标签库对应多个个标签!
iii. 在Jsp 页面上使用自己的标签!
h) .tld 文件的描述(根元素为 tag-lib):
i. tlib-version:标签库的版本,这个对程序的作用不大!
ii. short-name:标签库默认的短名,通常对程序的作用也不大!
iii. uri: 该标签库的uri,指定该标签库的唯一标示;
iv. tag:tag-lib 下可以有多个 tag,每个 tag 都代表一个标签;
i) tag 下的元素描述:
name: 这个非常重要,jsp页面就是根据这个来使用这个标签的;
tag-class: 这个是这个标签的后台处理类!
body-content: 这个属性可以是一下值:tagdependent: 指定标签的处理类,自己负责处理标签体! Empty: 空体标签;scriptless: 该标签里面可以含有静态的 HTML , 表达式语言,但不可以是JSP 脚本! JSP :这个已被忽视;
j) 带属性自定义的标签开发:
对于有属性的标签,要为tag添加 attribute 子元素: 每个 attribute 子元素定义一个属性,attribute含有一下子元素:
Name: 属性的名称;
Required:设置该属性为必须属性;
Fragment:是否支持Jsp脚本等动态内容!s
k) 在页面上使用自己定义的标签:
<%@ taglib uri="http://xabc.net"prefix="mytag" %>
带体的标签:
Collection<?>itemList=(Collection<?>)getJspContext().getAttribute(this.getCollection()); for (Object object : itemList) { getJspContext().setAttribute(this.getItem(),object); getJspBody().invoke(null);}
g) 过滤器:
a) 过滤器的使用场合:
i. 权限过滤;
ii. 日志过滤;
iii. 非法IP过滤;
iv. 字符集过滤;
b) 创建过滤器的后台处理类,实现Filter接口,实现如下方法:
i. init(FilterConfigconfig); 用于对过滤器的初始化;
ii. defiler(ServletRequestrequest,SerletResponse response,FilterChain chain);用于将请求继续传递;
iii. destroy():用于在 Filter 销毁之前将某些资源回收!
c) 在 web.xml 下如下配置:
<filter> <filter-name>filter</filter-name> <filter-class>util.DoFilter</filter-class> <init-param> <param-name>endoding</param-name> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>fristPage</param-name> <param-value>index.jsp</param-value> </init-param> <init-param> <param-name>IP</param-name> <param-value>127.0.0.2</param-value> </init-param> </filter> <filter-mapping> <filter-name>filter</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
* 过滤器主要是对用户的请求进行预处理,也可以对 HttpServletResponse进行后处理!
过滤器的核心代码:
public void doFilter(ServletRequest request,ServletResponse response, FilterChainchain) throws IOException, ServletException { request.setCharacterEncoding(this.encoding); HttpServletRequesthrequest=(HttpServletRequest)request; HttpServletResponsehresponse=(HttpServletResponse)response; Stringspath=hrequest.getServletPath();//获取请求的路径 Stringip=hrequest.getLocalAddr();//获取请求的IP if(!ip.equals(this.IP)) { if(!spath.endsWith(this.firstpage)) {request.getRequestDispatcher(this.firstpage).forward(hrequest,hresponse); }else{ chain.doFilter(hrequest,hresponse); } }else{ hrequest.setAttribute("msg","<scriptlanguage='javascript'>window.alert('您被限制了!')</script>"); hrequest.getRequestDispatcher("error.jsp").forward(hrequest,hresponse); }}
h) 监听器:
a) 使用 Listener 的步骤:
i. 创建 Listener 实现类,实现ServeltContextListener 接口;包含一下方法:
1. contextInitialized (ServletContextEvent sce): 启动web应用时,系统调用的方法;
2. contextDestroyed(ServletContextEvent sce): 关闭 web 应用时,系统调用的方法;
ii. 在web.xml 中配置如下:
<listener> <listener-class>util.Listener</listener-class></listener>
监听器如 servlet的 load-on-startup一样,但是比servlet的 load-on-startup 执行的还早,还有监听器不负责处理及相应用户的请求; 还有监听器在web.xml 下配置的时候无需配置参数,所访问的参数为全局共有参数。
v) JSP中表达式语言(Expressionlanguage):
a) ${1+2}: 前加 ‘ \’ 表示此EL 表达式不被解析;
b) 表达式语言的内置对象:
i. pageContext:代表页面的 pageContext 对象,与JSP中的PageContext相同;
ii. pageScope:获取page 范围内的属性;
iii. requestScope:获取 request 范围内的属性;
iv. sessionScope: 获取 session 范围内的属性;
v. applicationScope: 获取 application 范围内的属性;
vi. param :用于获取请求参数;
vii. paramValues:用于获取请求的参数,与param不同的是该对象是用于获取返回值为数组的参数;
viii. header:用于获取请求头信息;
ix. headerValues: 用于获取请求头信息; 与header不同的是该对象是用于获取返回值为数组的请求参数;
x. initParam:用于获取有 web 应用初始化的参数;
xi. cookie:用于获取指定 cookie 的值;
i) EL的自定义函数:
i. 自定义表达式语言与自定义标签类似;步骤分为:
1. 开发 EL函数处理类,这个类中的方法要求是静态的方法;
2. 建立tld 文件,tld 文件的描述:
name: 指定了函数的名称;
function-class: 函数对应的处理类;
function-signature: 指定函数的实现方法;
3. 使用该函数;
<%@ taglib uri="http://xabc.com"prefix="fn" %> ii. public staticString reverse(String str){ returnnew StringBuffer(str).reverse().toString(); } publicint countChar(String text){ returntext.length(); } <function> <name>reverse</name> <function-class>demo.myfunction</function-class> <function-signature> java.lang.Stringreverse(java.lang.String) </function-signature> </function> <function> <name>countChar</name> <function-class>demo.myfunction</function-class> <function-signature> intcountChar(java.lang.String) </function-signature></function>
八、 ajax中dwr框架的使用:
a. 配置dwr.xml:
<dwr> <allow> <createcreator="new" javascript="JCheckName"> <paramvalue = "net.xabc.bbs.biz.UserBiz" name ="class"/> <include method ="checkName"/> </create> </allow> </dwr>
b.配置 web.xml:
<servlet> <servlet-name>dwr</servlet-name> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping>
c.在js中设置回调函数:
functioncheckName(){ var name= document.getElementById("uName").value; JCheckName.checkName(name,checkUserName); }
九、 Struts2技术应用:s
1. Struts2上传文件:
原理:
Struts 2是通过Commons FileUpload文件上传。Commons FileUpload通过将HTTP的数据保存到临时文件夹,然后Struts使用fileUpload拦截器将文件绑定到Action的实例中。从而我们就能够以本地文件方式的操作浏览器上传的文件。
Web.xml 下的配置:
< filter > < filter-name > struts-cleanup </filter-name > < filter-class > org.apache.struts2.dispatcher.ActionContextCleanUp </ filter-class > </ filter > < filter > < filter-name > struts2 </ filter-name> < filter-class > org.apache.struts2.dispatcher.FilterDispatcher </ filter-class > </ filter > < filter-mapping > < filter-name > struts-cleanup </filter-name > < url-pattern > /* </ url-pattern > </ filter-mapping > < filter-mapping > < filter-name > struts2 </ filter-name> < url-pattern > /* </ url-pattern > </ filter-mapping >
org.apache.struts2.dispatcher.ActionContextCleanUp 在 struts 是对org.apache.struts2.dispatcher.FilterDispatcher 的一个补充,在做上传文件加上这个配置时,上传文件就万无一失了!
Struts.xml中的配置:
< action name ="fileUpload" class="tutorial.FileUploadAction" > < interceptor-refname ="fileUpload" > < param name="allowedTypes" > image/bmp,image/png,image/gif,image/jpeg </ param > </ interceptor-ref> < interceptor-refname ="defaultStack" /> < result name="input" > /FileUpload.jsp </ result > < result name="success" > /ShowUpload.jsp </ result > </ action >
通过在 strust.xml 中拦截器的配置,可以限制上传文件的大小和类型!但是如果在一个 Action 中配置拦截器,那么要在引用一次默认的拦截器栈!
在程序中:
private List<File> photo;private List<String> photoContentType;private List<String>photoFileName;private String savePath;
这四个属性是必须的并且为他提供 get,setter 方法,这几个属性是 struts 框架自动为其赋值的!
九、Struts2 的输入验证:
基本原理:
遇到类型转换错误的时候(也就是说不能进行类型转换),struts2框架自动生成一条错误信息,并且将该错误信息放到addFieldError里面
类型转换与输入校验的流程
1. 首先Struts2对客户端传来的数据进行类型转换
2. 类型转换完毕后再进行输入校验
3. 如果类型转换和输入校验都没有错误发生,那么进入execute方法(调用商业逻辑)
注意:如果类型转换不成功,也同样要进行输入校验!
在xxx-validation.xml中的一段配置:
<field name="username"> <field-validatortype="requiredstring"> <paramname="trim">true</param> <message>${getText('name.requied')}</message> </field-validator> <field-validatortype="regex"> <paramname="expression"><![CDATA[(\w{4,25})]]></param> <message>${getText('name.regex')}</message> </field-validator> </field> <fieldname="password"> <field-validatortype="requiredstring"> <paramname="trim">true</param> <message >${getText('pass.required')}</message> </field-validator> <field-validatortype="regex"> <paramname="expression"><![CDATA[(\w{4,25})]]></param> <message>${getText('pass.regex')}</message> </field-validator> </field> <fieldname="age"> <field-validatortype="int"> <paramname="max">150</param> <paramname="min">0</param> <message >${getText('age.range')}</message> </field-validator> </field> <fieldname="birthday"> <field-validatortype="date"> <paramname="min">1900-01-01</param> <paramname="max">2050-02-21</param> <message>${getText('birth.range')}</message> </field-validator></field>
使用 ${getText(‘ xxx’)}获取国际化资源文件!这段配置存在于 classpath 目录下 XXXXX-validation.xml 中!xxxx表示处理逻辑的 Action;
自动搜索:
如果在一个action中有多个业务,struts支持 效验文件自动搜索规则;如:UserAction-login-validation.xml;UserAction 是处理业务的Aciton, login 是登录的方法!struts2搜索规则是从上到下的,实际上用的效验规则是所有的效验规则总和;如果在两个效验文件中指定的效验规则发生了冲突,则后面的的取胜!
校验器的配置风格:
A. 字段效验风格:
<field name="username"> <field-validatortype="requiredstring"> <paramname="trim">true</param> <message>${getText('name.requied')}</message> </field-validator> <field-validatortype="regex"> <paramname="expression"><![CDATA[(\w{4,25})]]></param> <message>${getText('name.regex')}</message> </field-validator></field>
B. 非字段效验风格:
<validator type="regex"> <paramname="fieldName">username</param> <paramname="trim">true</param> <paramname="expression"><![CDATA[(\w[4,25])]]></param> <message>${getText('username.required')}</message></validator>
注意:如果使用非字段效验风格的话,必须指定 filedName 属性!
短路校验器:
通过在<field> </field>或 <validator></validator > 中配置short-circuit设置该校验是否为短路效验器!改值默认为 false(非);
Struts2 中所有的内建校验器:
A. 必填校验器:
<field name="username"> <field-validatortype="required"> <message>userNameto be not null!</message> </field-validator></field>
B. 必填字符串校验器:
<field name="username"> <field-validatortype="requiredstring"> <paramname="trim">true</param> <message>请填写用户名!</message> </field-validator></field>
注:该校验器有一个属性 trim表示是否在校验前清空前后的空格;默认为true;
C. 整数校验器:
<validator type="int"> <paramname="fieldName">age</param> <paramname="max">150</param> <paramname="min">0</param> <message>年龄必须在 0-150 岁之间!</message></validator>
注:该校验器采用的是非字段配置风格,配置的;整数效验器有两个属性 max 和min,最大和最小值!
D. 日期校验器:
<validator type="date"> <paramname="fieldName">birthday</param> <paramname="max">2050-02-01</param> <paramname="min">1990-01-01</param> <message>对不起,您的生日超范围了!</message> </validator>
注:max和min指的是最大和最小!
E. 表达式校验器:
<validator type="expression"> <paramname="expression">1==1</param> <message>正确!</message></validator>
注:该校验器只能使用非字段校验器风格!
F. 字段表达式校验器:
<validator type="fieldexpression"> <paramname="fieldName">pass</param> <paramname="expression"><![CDATA[(pass==repass)]]></param> <message>原密码要和重复密码相同!</message></validator>
G. 网址校验器:
<validator type="url"> <paramname="fieldName">url</param> <message>您的主页必须是一个有效的网址!</message></validator>
H. 字符串长度校验器:
<validator type="stringlength"> <paramname="fieldName">username</param> <paramname="maxLength">10</param> <paramname="minLength">1</param> <message>长度必须在 1-10 之间!</message></validator>
I. 正则表达式校验器:
<validator type="regex"> <paramname="fieldName">username</param> <paramname="expression"><![CDATA[(\w{4,25})]]></param> <paramname="caseSensitive">false</param> <message>请填写正确格式的用户名!</message></validator>
注:在这个校验器中 caseSensitive表示: 在做效验的时候是否区分大小写,默认为 true,区分大小写!
在程序中验证:
重写父类的validate 方法,如果在一个action 中,存在多个业务逻辑的处理方法,那么就要为其提供 validateXxx() 方法;如果使这种情况的话,建议不要在出现父类的 validate() 方法,以为如果有父类的validate()时,struts2 的验证顺序为类型转换 validateXxx() ,validate() ;
在程序中使用 ActionError,如果使用了 ActionError 的话,建议将form的 theme 属性设置为 simple;在页面上使用 <s:actionErrors/> 标签显示! 如果使用 fieldError时,在页面上使用<s:fieldErrors/>标签来显示信息!
值得注意的是ActionError在底层时放入到 List 中,而FieldError 时放入到 Map 中的!
一般情况下如果效验不是太复杂的话,我们都是配置文件的方式完成输入效验!但是对于配置文件难以解决校验我们重写 ActionSupport 类的 validate() 方法! 但是配置文件和 重写父类的validate() 方法建议不要同时使用!
2. Struts2 核心拦截器
A. struts2 的拦截器是根据 aop的思想设计的,实现aop有两种方式 dynamic prox 和 cglib; 拦截器的出现满足了我们对 dry 的实现!
关于动态代理的一段关键代码:
Proxy.newProxyInstance(UserAction.class.getClassLoader(), newClass[] { IAction.class }, hander);public Object invoke(Object proxy,Method method, Object[] args) throwsThrowable { Objectobj=null; if("execute".equals(method.getName())) { doService.Inteceptor(); obj= method.invoke(actionService, args); doService.Inteceptor(); }else{ obj=method.invoke(actionService,args); } returnobj; }
B. 在struts2中实现一个拦截器的几种方式:
实现 Interceptor 接口;
继承 DefaultInterceptor 类;
继承MethodFilterInterceptor 类(方法过滤拦截器);
C. 拦截器在struts.xml中的配置:
首先在 struts.xml 中注册拦截器:
<interceptors> <interceptorname="" class=""></interceptor> </interceptors>
拦截器栈和拦截器在struts.xml 中没有太大的区别 (从宏观角度上看!)
然后在Action中引用:
<interceptor-refname="MyInterceptor3"> <paramname="includeMethods">userlogin</param> </interceptor-ref><interceptor-refname="defaultStack"></interceptor-ref>
如果配置了多个拦截器引用,执行的顺序是从上到下! 在这里还可以配置参数,在Action中引用时注册的参数会覆盖注册时的参数值,并且这些参数会自动封装到 Inteceptor中;
十、Spring 技术应用:
1. Spring 的配置文件:
配置文件的名称可以为多个,并且名称随便给! 最后通过ClassPathXmlApplicationContext的构造函数传入配置文件的路径;
为了减少配置文件的字节,一般可采取两种方案: 使用通配符或者写多个配置文件,最后通过如上方式引入!但是在多个配置文件中应注意的是:不能出现相同的Id名称!
按名称自动装载,或按类型自动装载!
使用 <import /> 在配置文件中导入!<importresource="applicationContext.xml"/>
2. 构造注入:
<bean id="gaojiangtao"class="entity.User"> <constructor-arg index="0"> <value>高江涛</value> </constructor-arg> <constructor-arg index="1"> <value>男</value> </constructor-arg> <constructor-arg index="2"> <value>18</value> </constructor-arg> <constructor-arg index="3"> <value>泾阳</value> </constructor-arg> <constructor-arg index="4"> <value>770212507</value> </constructor-arg></bean>使用构造器注入时,使用 index(参数索引为 Spring 官方推荐的构造其注入用法);
3. 普通属性注入:
<property name="list"> <list> <value>list1</value> <value>list2</value> <value>list3</value> </list> </property> <property name="set"> <set> <value>set1</value> <value>set2</value> <value>set3</value> </set> </property> <property name="array"> <list> <value>array1</value> <value>array2</value> <value>array3</value> </list> </property> <property name="map"> <map> <entry key="k1" value="v1"/> <entry key="k2"value="v2"></entry> </map> </property>
以上是几种常见的集合的注入!
5. 属性编辑器:
首先定义属性编辑器后台类,继承PropertyEditorSupport, Java.beans 包下的;重写它的 setAsText()方法,在方法中类型转换完成之后,通过 this.setValue()方法保存;
然后在 Spring 配置文件中注册:
<bean id="propertyEdit"class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <propertyname="customEditors"> <map> <entrykey="java.util.Date"> <beanclass="net.xabc.entity.PropertyEdit"></bean> </entry> </map> </property> </bean>
通过以上的注册,Spring就会知道把相应的类型进行转换!
6. 几种初始化 Ioc 容器的方式:
ClassPathResourceresource=new ClassPathResource("applicationContext.xml");BeanFactoryfactory=new XmlBeanFactory(resource); Resourceresource=new FileSystemResource("E:\\applicationContext.xml");BeanFactoryfactory=new XmlBeanFactory(resource); ApplicationContextact=new ClassPathXmlApplicationContext("applicationContext.xml");
7. 采用静态工厂方法或者实例工厂方法创建对象:
静态工厂方法:
<bean id="gaojiangtao" class="entity.factory"factory-method="createUser">
要求createUser方法必须为静态的!
实例工厂方法:
<beanid="createuser" class="entity.factory"></bean><beanid="gaojiangtao" factory-bean="createuser" factory-method="createUser"></bean>
8. 名称自动装备 和 类型自动装备:
名称自动装备就是:如果一个类中的一个属性为 user时, 在配置文件中,我们没有为这个user属性设置它的引用! 那么 Spring就会自动在所有的Id中找 Id 为user的<bean> 如果找到了,Spring 容器自动添加其引用!(default-autowire="byName")
类型自动装备就是,Spring容器会在配置文件中找 Spring 为 user 对应的类型,
找到了会自动添加其引用 !(default-autowire="byType")
9. 采用 aspectJ 的 annocaton 方式实现aop:
a) spring依赖库
* SPRING_HOME/dist/spring.jar
* SPRING_HOME/lib/jakarta-commons/commons-logging.jar
* SPRING_HOME/lib/log4j/log4j-1.2.14.jar
* SPRING_HOME/lib/aspectj/*.jar
b) 采用Aspect定义切面
c) 在Aspect定义Pointcut和Advice
d) 启用AspectJ对Annotation的支持并且将Aspect类和目标对象配置到Ioc容器中
<aop:aspectj-autoproxy/>
e) 注意:在这种方法定义中,切入点的方法是不被执行的,它存在的目的仅仅是为了重用切入点
即Advice中通过方法名引用这个切人点
10. 采用静态文件实现 aop:
首先,定义切面类!然后在配置文件中注册配置的切面类!
<aop:config> <aop:aspect id="aspectTransaction"ref="transactionHander"> <aop:pointcut id="transaction"expression="execution(* staticFile.*.add*(..))"/> <aop:beforemethod="startTransaction" pointcut-ref="transaction"/> <aop:aftermethod="closeTransaction" pointcut-ref="transaction"/> </aop:aspect> </aop:config>
注意:
Aspect默认情况下不用实现接口,但对于目标对象,在默认情况下必须实现接口
如果没有实现接口必须引入CGLIB库!
我们可以通过Advice中添加一个JoinPoint参数,这个值会由spring自动传入,从JoinPoint中可以取得参数值、方法名等等!
11. Java的动态代理,以及 CGLIB对aspectj 实现 aop 的支持:
如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
如果目标对象实现了接口,可以强制使用CGLIB实现AOP
如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
如何强制使用CGLIB实现AOP?
添加CGLIB库,SPRING_HOME/cglib/*.jar
在spring配置文件中加入<aop:aspectj-autoproxyproxy-target-class="true"/>
JDK动态代理和CGLIB字节码生成的区别?
JDK动态代理只能对实现了接口的类生成代理,而不能针对类
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
12. SSH集成(第一种集成方案):
原理:在Action中取得BeanFactory对象,然后通过BeanFactory获取业务逻辑对象
1、spring和struts依赖库配置
* 配置struts
--拷贝struts类库和jstl类库
--修改web.xml文件来配置ActionServlet
--提供struts-config.xml文件
--提供国际化资源文件
* 配置spring
--拷贝spring类库
--提供spring配置文件
2、在struts的Action中调用如下代码取得BeanFactory
BeanFactoryfactory =WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext());
3、通过BeanFactory取得业务对象,调用业务逻辑方法
13. 采用声明式事务:
a、声明式事务配置
* 配置SessionFactory
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <propertyname="configLocation"> <value>classpath:hibernate.cfg.xml</value> </property> </bean>
* 配置事务管理器
<bean id="transactionProxy" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <propertyname="sessionFactory"ref="sessionFactory"></property> </bean>
* 配置事务的传播特性
<tx:advice id="txadvice"transaction-manager="transactionProxy"> <tx:attributes> <tx:method name="add*"propagation="REQUIRED"/> <tx:method name="update*"propagation="REQUIRED"/> <tx:method name="delete*"propagation="REQUIRED"/> <tx:method name="*"read-only="true"/> </tx:attributes> </tx:advice>
* 配置那些类那些方法使用事务
<aop:config> <aop:pointcut id="allMethod"expression="execution(* net.xabc.hr.biz.impl.*.* (..))"/> <aop:advisor advice-ref="txadvice"pointcut-ref="allMethod"/> </aop:config>
b、编写业务逻辑方法
* 继承HibernateDaoSupport类,使用HibernateTemplate来持久化,HibernateTemplate是
Hibernate Session的轻量级封装
* 默认情况下运行期异常才会回滚(包括继承了RuntimeException子类),普通异常是不会滚的
* 编写业务逻辑方法时,最好将异常一直向上抛出,在表示层(struts)处理
* 关于事务边界的设置,通常设置到业务层,不要添加到Dao上
c、了解事务的几种传播特性
1. PROPAGATION_REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启
2. PROPAGATION_SUPPORTS:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
3. PROPAGATION_MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
4. PROPAGATION_REQUIRES_NEW:总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
5. PROPAGATION_NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的事务。
6. PROPAGATION_NEVER:总是非事务地执行,如果存在一个活动事务,则抛出异常
7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务,
则按TransactionDefinition.PROPAGATION_REQUIRED属性执行
d、Spring事务的隔离级别
1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
另外四个与JDBC的隔离级别相对应
2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
这种隔离级别会产生脏读,不可重复读和幻像读。
3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
5. ISOLATION_SERIALIZABLE这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
除了防止脏读,不可重复读外,还避免了幻像读。
14. Spring中的任务调度:
a) Java Timer 调度器:
需继承 TimerTask 类,重写 run() 方法;
<bean id="testTask" class="org.rongxin.springtest.time.Task.TestTask"/> <bean id="scheduledTestTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"> <property name="timerTask"> <ref bean="testTask" /> </property> <property name="period"> <value>10000</value> //间隔时间 </property> <property name="delay"> <value>2000</value> //懒执行的时间 (都是以毫秒为单位) </property> </bean> <beanid="timeFactory" class="org.springframework.scheduling.timer.TimerFactoryBean"> <property name="scheduledTimerTasks"> <refbean="scheduledTestTask" /> </property> </bean>
b) Quartz(opensymphon) 调度器:
继承QuartzJobBean,必须要 quartz-1.5.2.jar ! 重写它的 executeInternal 方法!
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean"> //任务的详细信息 <propertyname="jobClass"> <value>org.rongxin.springtest.time.Task.QuartzJob</value> </property> <propertyname="jobDataAsMap"> <map> <entrykey="fristDate"> <beanclass="java.util.Date" /> </entry> </map> </property></bean>
//间隔多少时间执行任务
<beanid="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <propertyname="jobDetail"> <refbean="jobDetail" /> </property> <propertyname="startDelay" value="2000" /> <propertyname="repeatInterval" value="2000" /> </bean>
//到什么时间执行任务
<beanid="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <propertyname="jobDetail" ref="jobDetail" /> <propertyname="cronExpression"> <value>** * * * ?</value> //? 是星期天不必设置! * 代表任意 </property></bean><beanid="quartFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <propertyname="triggers"> <refbean="cronTrigger"/> </property> </bean>
十一、 Hibernate介绍:
一般应用中常用到五个接口
1.configaction
通过这个接口的实例来找到映射配置文件的信息,然后根据里面的映射信息创建sessionFactory对象
2.session
管理增删改差五个方法
一个应用程序中可以有多个session实例,可以随时销毁,因为它占用资源小,被称为第一插件
3.sessionFactory
线程是安全的,它的同一个实例可以给多个线程调用
它的实例是重量级的,不能随意销毁
负责实力所有的session对象,一般一个应用程序中只能有一个SESSIONFACTORY,因为它占用的系统资源过大!
称为hibernate的第二插件
4.query和criteria
执行hibernate查询方法的接口,它包装了一个HQL查询语句,criteria完全封装了字符串形式的查询语句,比QUERY更加面向对象,一般用于动态查询。他们功能比session中的find()方法强大许多,因为find()方法只能执行一些简单的,单一对象的查询
5.Transaction
管理事务接口
十二、 SSH 集成:
第一种集成方案:
原理:在Action中取得BeanFactory对象,然后通过BeanFactory获取业务逻辑对象
a、spring和struts依赖库配置
* 配置struts
--拷贝struts类库和jstl类库
--修改web.xml文件来配置ActionServlet
--提供struts-config.xml文件
--提供国际化资源文件
* 配置spring
--拷贝spring类库
--提供spring配置文件
b、在struts的Action中调用如下代码取得BeanFactory
BeanFactoryfactory =WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext());
c、通过BeanFactory取得业务对象,调用业务逻辑方法
(第二种集成方案):
原理:将业务逻辑对象通过spring注入到Action中,从而避免了在Action类中的直接代码查询
a、spring和struts依赖库配置
* 配置struts
--拷贝struts类库和jstl类库
--修改web.xml文件来配置ActionServlet
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
--提供struts-config.xml文件
--提供国际化资源文件
* 配置spring
--拷贝spring类库
--提供spring配置文件
b、因为Action需要调用业务逻辑方法,所以需要在Action中提供setter方法,让spring将业务逻辑对象注入过来
c、在struts-config.xml文件中配置Action
* <action>标签中的type属性需要修改为org.springframework.web.struts.DelegatingActionProxy
DelegatingActionProxy是一个Action,主要作用是取得BeanFactory,然后根据<action>中的path属性值
到IoC容器中取得本次请求对应的Action
d、在spring配置文件中需要定义struts的Action如:
<beanname="/login" class="com.bjsxt.usermgr.actions.LoginAction"scope="prototype"> <property name="userManager"ref="userManager"/> </bean>
* 必须使用name属性,name属性值必须和struts-config.xml文件中<action>标签的path属性值一致
* 必须注入业务逻辑对象
* 建议将scope设置为prototype,这样就避免了struts Action的线程安全问题
Srping 中声明式事务的配置:
<!--SessionFactory -->
<bean id="sessionFatory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <propertyname="configLocation"> <value>classpath:hibernate.cfg.xml</value> </property> </bean>
<!-- 配置抽象bean-->
<bean id="basedao"abstract="true"> <propertyname="sessionFactory" ref="sessionFatory" /> </bean>
<!-- 配置事务管理器-->
<bean id="transactionProxy"class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <propertyname="sessionFactory"ref="sessionFatory"></property> </bean>
<!-- 配置事务的传播特性 -->
<tx:advice id="txadvice"transaction-manager="transactionProxy"> <tx:attributes> <tx:methodname="add*" propagation="REQUIRED"/> <tx:methodname="update*" propagation="REQUIRED"/> <tx:methodname="delete*" propagation="REQUIRED"/> <tx:methodname="*" read-only="true"/> </tx:attributes> </tx:advice>
<!-- 配置那些类需要声明事务 -->
<aop:config> <aop:pointcutid="allMethod" expression="execution(* org.rongxin.hr.basic.dao.impl.*.*(..))"/> <aop:advisorpointcut-ref="allMethod" advice-ref="txadvice" /> </aop:config>
- JavaWeb常用开发技术总结-js、spring、javabean、mysql数据库、dwr的使用等
- dwr开发总结 dwr+spring
- javaWeb开发之基础--------------MySQL数据库总结
- javaWeb常用技术语法总结
- javaWeb常用框架技术总结
- JavaWeb体系结构的理解-4.JavaBean技术
- Javaweb学习总结(四):JavaBean组件技术
- dwr的javaBean操作
- javaWeb之JavaBean总结
- javaweb---JavaBean总结
- 常用Node.js开发工具、开发包、框架等总结
- dwr技术使用的步骤
- Mac安装mysql数据库&MySQL基础和MySQL在开发中常用的技术
- javaweb开发之javaBean
- JavaWeb学习总结(基于Servlet+JSP+JavaBean开发模式的用户登录注册)
- javaweb学习总结(——基于Servlet+JSP+JavaBean开发模式的用户登录注册
- JavaWeb总结二十二、基于Servlet+JSP+JavaBean开发模式的用户登录注册
- javaweb开发要学习的所有技术和框架总结:
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- vb.net写机房收费系统
- GBS超级分床+超级排料=GBS省料专家
- 谈谈RGB、YUY2、YUYV、YVYU、UYVY、AYUV
- SOA商品(Item)查询接口
- JavaWeb常用开发技术总结-js、spring、javabean、mysql数据库、dwr的使用等
- android,多线程断点下载
- 黑马程序员---基础强化---java的类加载器
- C++学习方法
- ubuntu下配置NFS
- LeetCode 27 — Remove Element(C++ Java Python)
- hbase 数据模型
- CareerCup Josephus Problem
- Java面向对象——集合框架总结