1.Hibernate如何解决延迟加载? 在配置文件里设置lazy="false" 关闭延迟加载 Hibernate.initialize(u.getAccout()); 设置HQL语句:from User u join fetch u.accts where u.ui=?2.Session的状态管理和对象的状态转换。暂态(Transient):po对象,在DB中无记录,和Session无关。 有内部状态,无外部状态。 和Hibernate Session发生过关系。持久态(Persistent):po对象,在DB中有记录,和Session有关 有内部状态,也有外部状态,由session自动同步 正在和Hibernate Session正在发生关系, 游离态(Detached):po对象,在DB中有记录,和Session无关 有内外部状态,但要手工同步曾经和Hibernate Session发生过关系,用于分布式new 对象后进入暂态 saveorupdate/update后有暂态进入持久态 evict/clear/close:有持久态进入游离态delete:有持久态进入暂态 save/saveorupdate:可有游离态重新进入持久态3.继承映射的三种策略的选择,如何选择配置文件? 一个类一个表eg:<hibernate-mapping package="com.bank.biz.entity"> <class name="Account" table="t_account "> <id name="oid"> <generator class="native" /> </id> <property name="actNo" column="actNo" not-null="true" unique="true"/> <property name="bal" not-null="true"/> <property name="openDate" type="date" not-null="true" /> <one-to-one name="addr" cascade="all"/> <many-to-one name="owner" column="fid" cascade="save-update" /> <joined-subclass name="DebitAccount" table="t_debit "> <key column="debitoid" /> <property name="currency" /> </joined-subclass> <joined-subclass name="CreditAccount" table="t_credit "> <key column="creditoid" /> <property name="credit" /> </joined-subclass> </class> </hibernate-mapping>
一个实体一个类<hibernate-mapping package="com.sd0904.bank.biz.entity"> <class name="Account"> <id name="oid" column="oid"> <generator class="native"></generator> </id> <property name="actNo" column="actNo" unique="true" /> <property name="bal" column="bal" not-null="true"/> <one-to-one name="addr" cascade="all"></one-to-one> <many-to-one name="owner" column="fid" cascade="save-update"/> <union-subclass name="DebitAccount" table="t_debit_perconcrete_sd0904"> <property name="currency"></property> </union-subclass> <union-subclass name="CreditAccount" table="t_credit_perconcrete_sd0904"> <property name="credit"></property> </union-subclass> </class> </hibernate-mapping>所有类在一个表中<hibernate-mapping package="com.sd0904.bank.biz.entity"> <class name="Account" table="t_acct_perhiarchy_sd0904"> <id name="oid" column="oid"> <generator class="native"></generator> </id> <discriminator column="type"></discriminator> <property name="actNo" column="actNo" unique="true" /> <property name="bal" column="bal" not-null="true"/> <one-to-one name="addr" cascade="all"></one-to-one> <many-to-one name="owner" column="fid" cascade="save-update"/> <subclass name="DebitAccount" discriminator-value="D"> <property name="currency"></property> </subclass> <subclass name="CreditAccount" discriminator-value="C"> <property name="credit"></property> </subclass> </class> </hibernate-mapping>
选择原则(1)不需要多态查询时,一个实体类一个表 (2)需要多态查询时,类不太多,类中属性也不太多时,选择只建一个表,这样的方式用的较多 (3)类多,属性也多,则考虑每个类建一个表4.如何解决条件查询中的动态HQL(自己如何拼装以及Criteria查询)自己拼装HQL: StringBuffer hql=new StringBuffer(); if(name!=null){ hql.append(" and name="+name); } if(passwd!=null){ hql.append(" and passwd="+passwd); } Criteria查询: Criteria cr=session.createCriteria(Student.class); cr.add("name","Bill"); Lsit list=cr.list(); Student stu=(Student)list.get(0); System.out.println(stu.getName());5.实现1对1的两种策略如何实现?一对一外键映射实现: 关联属性是个引用,是个内存地址,读不出不能存也不能恢复,是虚的,数据库中没有关联属性的映射,所以不能直接存到数据库中去,只能通过表之间的主外键关系体现<hibernate-mapping package="com.sd0904.bank.biz.entity"> <class name="Account" table="t_accts_sd0904"> <id name="oid" column="oid"> <generator class="native"></generator> </id> <property name="actNo" column="actNo" unique="true" /> <property name="bal" column="bal" not-null="true"/> <one-to-one name="addr"cascade="all" property-ref="act" /> </class> </hibernate-mapping> <hibernate-mapping package="com.sd0904.bank.biz.entity"> <class name="Address" table="t_addrs_sd0904"> <id name="oid" column="oid"> <generator class="native"></generator> </id> <property name="postcode" not-null="true" /> <property name="city" not-null="true"/> <many-to-one name="act" column="fid" unique="true"> </many-to-one> <!--使用many-to-one主要由于外键是天生的多对一的体现--> </class> </hibernate-mapping>一对一主键映射实现: <hibernate-mapping package="entity"> <class name="Account" table="t_acct"> <id name="oid" column="oid"><generator class="native"></generator></id> <property name="actNo" column="actNo" unique="true" /> <property name="bal" column="bal" not-null="true"/> <one-to-one name="addr"cascade="all" property-ref="act" /> </class> </hibernate-mapping>
<hibernate-mapping package="entity"> <class name="Address" table="t_addrs"> <id name="oid" column="oid"> <generator class="foreign"> <param name="property">act</param> </generator> </id> <property name="postcode" not-null="true" /> <property name="city" not-null="true"/> <one-to-one name="act" constrained="true"/> </class> </hibernate-mapping>6.如何实现1对多?<hibernate-mapping package="hibernate.association.o2m.entity"> <class name="Order" table="ec_order"> <id name="id" column="id" type="integer"> <generator class="native" /> </id> <property name="owner" column="owner" type="string" length="15" not-null="true"/> <property name="phone" column="phone" type="string" length="15" not-null="true"/> <property name="address" column="address" type="string" length="50" /> <set name="items" cascade="all" inverse="true"> <key column="orderid" /> <one-to-many class="Item" /> </set> </class> </hibernate-mapping>
<hibernate-mapping package="hibernate.association.o2m.entity"> <class name="Item" table="ec_item"> <id name="id" column="id" type="integer"> <generator class="native" /> </id> <property name="product" column="product" type="string" /> <property name="amount" column="amount" type="integer" /> <many-to-one name="order" class="Order" column="orderid" cascade=”save-update”/> </class> </hibernate-mapping>7.Hibernate和JDBC的对比。Hibernate是对JDBC的封装,在程序中实现了与数据库的连接在Hibernate中的查询语句是面向对象来实现的,JDBC中的查询语句是简单的查询语句Hibernate实现了数据库,映射文件,实体三者(ORM)之间的连接8.lazy、reverse、cascade constrained(get load list iterator) lazy:处理对象的延迟加载,为true时开启延迟加载,false时关闭延迟加载即在访问对象立即加载与其相关的对象reverse:用于判断是否放弃关系维护权,多用于多对多连接,当为true时该类放弃关系维护权,为false时不放弃维护权,不设是由主键的一方负责维护关系cascade:指明那些对象会从父对象关联到的关联对象 有三种类型:delete(级联删除),saveorupdate,all,none(与默认的相同不会产生级联操作)constrained:该类所对应的数据库中的表和被关联对象所对应的数据库中的表之间,通过一个外键应用本表主键进行约束
1.分页问题(Hibernate SQL) String hql="select count(*) from Book"; Query query=session.createQuery(hql); List list=query.list();int totalRows=list.get(0).intValue(); int totalpage=0;if (totalRows % rowsPerPage == 0) { totalpage= totalRows / rowsPerPage;//确定总页数 } else { totalpage= totalRows / rowsPerPage + 1;} query.setMaxResults(rowsPerPage);//一页可以容纳的条数 query.setFirstResult(rowsPerPage * (page - 1));//一页的第一条记录是第几条记录 默认是从0开始 List<?> list = query.list();2.Struts中的Action有几类,分别有什么特点? DispatchAction:在一个Action里执行多个操作,该类是为执行一些聚合操作而设计的Action类使用该类需要在配置文件设置parameter="method";ForwardAction:在配置文件里设置type="org.apache.struts.actions.ForwardAction" parameter="/WEB-INF/jsp/menu.jsp" />MappingDispatchAction:在配置文件中通过路径进行响应3.关于Struts的控制流程是怎么样的? 页面向服务器发出请求(ActionServlet),先到RequestProcessor进行过滤确定是响应那个Action,然后才到响应的具体Action 执行该操作需要在配置文件里做一下设置注意应该在servlet之前设置: <controller processorClass="org.whatisjava.MaRequestProcessor"></controller>4.关于ActionForm的缓存和Struts的标签在项目中的应用,在项目中的意义ActionForm缓存作用:将表单中用户输入的数据缓存在表单对象里,不会由于一个信息出错就丢失所有刚输入的信息 <html:form> <html:text property="name"/> <html:textarea property="comment"/> <html:password property="pwd"/> </html:form>
5.RequestProcessor在分模块中的地位,想想在项目中控制访问权限的应用(和Filter的对比) RequestProcessor:拦在Action之前,相应ActionServlet在其中判断到底采用那个action 在只有一个模块时也会默认添加一个RequestProcessor Filter:拦在用户向服务器提交之前,在<servlet>之前控制访问权限 <load-on-startup>应用:设置编码,如果用户请求信息不是合乎设置的条件使用Filter会被拦截不会执行接下来的操作6.分模块如何应用,注意的问题(路径和文件) 在web.xml中<servlet>中设置<init-param> <param-name>config/ma</param-name> <param-value>/WEB-INF/ma-structs-config.xml</param-value> <param-value>/WEB-INF/mb-structs-config.xml</param-value> </init-param>
ma-structa-config-xml: <action path="/login" type="action.LoginAction"> <forward name="success" path="/login.jsp" module="/WEB-INF/jsp/ma"/></action>
注意问题:structs-config-xml:即使里边为空也必须保留路径:module+path path默认会在前面加模块名7.HashMap查找在项目中的应用? DispatchAction:将方法名缓存在HashMap里,以后再有同样方法被请求则先从缓存里查找,不用每次都使用反射来得到method,节省了时间 HashMap还可以缓存用户名,密码这样在登录时可以直接在缓存中查找不用直接到数据库
8.JSON的格式是怎样的?如何使用?JSON全名为JavaScript Object Notation,是一种轻量级的数据交换格式JSON数据格式文件:{ info:"hello world",version:"2.0"} JSONArray json=JSONArray.fromObject(userlist); //将集合转化为json数组 String str=json.toString();//将json转化为字符串JSONObject json1=JSONObject.fromObject(user);//将单个对象转化为json对象 在页面中获取json:var json=eval(xmlHttp.responseText); str.evalJSON();/将字符串转化为对象 Object.toJSON():将对象转化为字符串 9.如何使用Struts的验证框架?以及结合validator方法的扩展应用(钩子方法的设计和应用)使用struts的验证框架需要重写validation.xml 在struts-config.xml配置文件里需要添加插件: <plug-in class="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validor-rules.xml,/WEB-INF/validation.xml"> </plug-in>ActionForm里要继承ValidatorActionForm
ValidatorActionForm 是ActionForm 的子类 ValidatorActionForm重写了validate方法 在该方法中通过调用commons-validator.jar(验证框架)提供的功能进行验证需要对验证框架进行配置
在表单extends ActionForm 实现validator方法(验证表单时调用,填充完之后调用): public ActionErrors validator(){ ActionErrors error=new ActionErrors(); error.add("name",new ActionMessage("error.name"));//在这里error.name对应属性文件的数据 return error; }钩子方法:public class Foo{ protected void f(){} protected void some(){ f();} }public class Bar extends Foo{ public void f(){System.out.println("f method");} public void some(){};}Bar bar=new Bar(); bar.some();子类重写自己的方法,在子类中还可以访问以前没被重写过的方法10.如何读取属性文件?想想在哪里用过? new ActionMessage("error.name"):可以直接取属性文件里的值在validation.xml配置文件里可以通过<arg0 key="user.password">Properties ps=new Properties();FileInputStream fis=new FileInputStream(new File("d://ad.txt"));ps.load(fis);String name=ps.getProperty("name");
11.Ajax(原理)请求数据,以及如何填充div(根据class or id)Ajax最重要功能就是将web请求和处理从同步转变成了异步,这意味这客户端和服务端不必相互等待了,而是可以进行一些并发操作客户端向Ajax引擎发送请求,经处理发给服务器,客户端不用等待可以进行其他操作,当服务器处理完一个请求之后,会自动将处理结果返回给前台的Ajax引擎来更新页面中的部分数据 浏览器----Ajax引擎----客户端处理----服务器var respTxt=xmlHttpRequest.responseText;var emplist=respTxt.evalJSON();for(i=0;i<emplist.length;i++){ var tb=document.getElementById("tb"); var tr=tb.insertRow(tb.rows.length); var td1=tr.insertCell(tr.cells.length); var td2=tr.insertCell(tr.cells.length); td1.innerHTML=emplist[i].id; td2.innerHTML=emplist[i].name;}同步与异步:异步:两个操作不相互影响 12.Struts的标签如何使用(form bean logic) 如何对应基本的html元素<html:form> <html:button> <html:text> <html:textarea> <html:submit> <html:hidden> <html:errors><html:checkbox> <html:file> <html:radio> <html:multibox>
info.myKey=The number entered are {0},{1},{2},{3}<bean:message key="info.myKey" arg0="5" arg1="6" arg2="7" arg3="8" /><bean:resource id="myResource" name="/WEB-INF/myResource.xml"/><bean:define id="targetBean" name="sourceBean" scope="request"/><bean:cookie id="myCookie" name="userName"/><bean:include id="myInclude" page="Myjsp?x=1"/><bean:write name="myBean" property="myProperty" scope="request" filter="true"/>
条件逻辑:<logic:equal parameter="name" value="SomeName"/> <login:present name="bean" property="prop" scope="page"/> <login:forward name="myGlobalForward" /> <login:redirect />13.如何实现自己的EL和JSTL?自定义El:三部曲 定义一个ElFunction类/建立一个el_function.tld /在页面中引用 public class ElFunction { //list set属于Collection 集合分为Collection/map/Array[] public static Integer length(Object obj){ if(obj instanceof Collection<?>){ return ((Collection<?>) obj).size(); } else if(obj instanceof Map<?, ?>){ return ((Map<?, ?>) obj).size(); }else if(obj instanceof Object[]){ return ((Object[]) obj).length; }else{ return null; } }}
<?xml version="1.0" encoding="UTF-8"?><taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"> <tlib-version>1.0</tlib-version><!--版本--> <short-name>el-funciton</short-name><!--函数标记库名称--> <function> <!--函数标记的名称, 用在EL中--> <name>len</name> <!-- 这个函数的实现类--> <function-class>com.tstc.edu.el.ElFunction</function-class> <!-- 方法的签名声明--> <function-signature> java.lang.Integer length(java.lang.Object) </function-signature> </function></taglib>
<%@ taglib uri="/WEB-INF/tld/el-function.tld" prefix="f"%> <c:when test="${f:len(bookList) gt 0}">自定义JSTL新建一个类继承SimpleTagSupport 并重写doTag方法doTag方法中的关键点:public void doTag() { JspFragment body = this.getJspBody(); PageContext ctx = (PageContext)this.getJspContext();//通过PageContext可以获得任何内置对象 body.invoke(ctx.getOut());}应用实例public class HelloTag extends SimpleTagSupport{ protected int count=0; public void setCount(int count){ this.count=count; } public int getCount(int count){ return count; } public void doTag() throws JspException, IOException { for(int i=0;i<10;i++){ getJspContext().setAttribute("count", String.valueOf(i+1)); getJspBody().invoke(null); }}}tld文件:<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"> <tlib-version>1.0</tlib-version> <tag> <name>hello</name> <tag-class>JSTL.HelloTag</tag-class> <body-content>jsp</body-content> <attribute> <name>num</name> <required>true</required> </attribute> </tag></taglib>
页面:引入<%@ taglib uri="/WEB-INF/hello.tld" prefix="t"%><t:iterator count=10>这是第${count}次循环!</t:iterator>14.验证码在项目中的应用 想想原理(验证码 分步注册)在登录页面或注册时会使用原理:验证码就是生成的一个图片其中的数字是利用随机数生成的,将生成的数字保存到session里,等从表单中取到用户输入的验证码后,将两个number进行对比如果相同则用户输入的验证码是正确的,否则是不正确的
15.css 的简单使用,改变某个div标签样式16.实现Ajax的方式(手写和框架),描述原理 1 新建xmlHttpRequest对象 xmlHttpRequest=new XMLHttpRequest(); 2 打开连接 xmlHttpRequest.open("get",url,true); 3 当状态改变时调用的function方法 xmlHttpRequest.onreadyStatechange=function(){}; 4 xmlHttpRequest.send(null);//将信息发给服务器<script type="text/javascript"> function testAjax(){ var xmlHttpRequest = null; //初始化xmlHttpRequest对象 if ((typeof XMLHttpRequest) != 'undefined') { // FF xmlHttpRequest = new XMLHttpRequest(); } else { // IE xmlHttpRequest = new ActiveXObject('Microsoft.XMLHttp'); } var userValue = document.getElementById('user').value; var url = 'some?user='+userValue; //创建和服务器的连接 //arg0: get或post方式 //arg1: 要连接的地址 //arg2: 是否是异步的方式连接 true代表异步方式连接 xmlHttpRequest.open('GET', url, true); // 给onreadystatechange属性赋值了一个函数 // 注册了一个‘状态监听器’,当xmlHttpRequest的状态 // 一改变,该函数就调用 xmlHttpRequest.onreadystatechange = function(){ //xmlHttpRequest.readyState属性表示当前的状态码 if (xmlHttpRequest.readyState == 4) { //responseText返回文本方式的响应内容 var respTxt = xmlHttpRequest.responseText; var d1 = document.getElementById('msg'); d1.innerHTML = respTxt; }else { var d1 = document.getElementById('msg'); d1.innerHTML = 'loading...'; } }; xmlHttpRequest.send(null); } </script> </head> <body> Username:<input type="text" id="user" name="user" οnblur="testAjax();"/><span id="msg"></span><br/> Password:<input type="password" id="pwd" name="pwd"/> <input type="button" οnclick="testAjax();" value="Click Me" /> <div id="info"></div> </body>装载信息到页面 function load(url, id) { new Ajax.Request(url, { method :'get', onSuccess : function(req) {$(id).innerHTML = req.responseText;} });}
17.js如何提交表单?如何往浏览器上发请求? $(id).submit;18.Action的粒度如何来控制? Action继承DispatchAction:在类中实现 public ActionForward f(){}实现DispatchAction类 使用技术:基于Method的反射public class DispatchAction extends Action { private Map map = Collections.synchronizedMap(new HashMap()); public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String param = mapping.getParameter(); String methodName = request.getParameter(param); Method method = (Method) map.get(methodName); if (method == null) { Class clazz = this.getClass();//class 在方法区找到方法 反射直接使用方法区中的值 动态在方法区生成类 method = clazz.getMethod(methodName, new Class[] { ActionMapping.class, ActionForm.class, HttpServletRequest.class, HttpServletResponse.class }); map.put(methodName, method); }//this:在哪一个对象上调用方法 第二个参数:调用方法传的参数 ActionForward forward = (ActionForward) method.invoke(this, new Object[] { mapping, form, request, response }); return forward; }}
实现MapDispatchAction:这两种方法的主要区别是在struct-config.xml中的配置不同:DispatchAction:<action path="/some" type="org.whatisjava.action.SomeAction" parameter="option" />在浏览器输入url为http://localhost:8080/ssh/some.do?option=fMapDispatchAction:<action path="/otherf" type="org.whatisjava.action.OtherAction" parameter="f" />在浏览器输入url为http://localhost:8080/ssh/otherf.do19.如何进行JUnit测试?首先导入JUnit包 JUnit3.18版本的需要继承TestCase 不用写注解@TestJUnit4.0不用继承TestCase 当需要写@Test否则在运行时找不到JUnit Test被测试的类:public class SomeService { public int max(int[] arry) { int max = Integer.MIN_VALUE; for (int n : arry) { if (n > max) max = n;}return max; }}测试类:public class TestSomeService { @Test public void tstMax1() { SomeService ss = new SomeService(); int max = ss.max(new int[] { 1, 2, 3 }); TestCase.assertEquals(3, max);//断言指定值是否为真 }}
20.如何测试Action?继承MockStrutsTestCase类public class TestLoginAction extends MockStrutsTestCase { public void testSuccess() { this.setContextDirectory(new File("WebRoot")); this.addRequestParameter("username", "whatisjava"); this.addRequestParameter("password", "whatisjava"); this.setRequestPathInfo("/login"); this.actionPerform(); HttpSession session = this.getSession(); Object obj = session.getAttribute("key_username"); assertEquals("whatisjava", obj); this.verifyForwardPath("/WEB-INF/jsp/main.jsp"); }
public void testFail() { this.setContextDirectory(new File("WebRoot")); this.addRequestParameter("username", "whatisjava"); this.addRequestParameter("password", "hahaha"); this.setRequestPathInfo("/login"); this.actionPerform(); this.verifyForwardPath("/WEB-INF/jsp/error.jsp"); }}在配置文件里需要配置<action path="/login" type="org.whatisjava.action.LoginAction" name="loginForm"> <forward name="success" path="/WEB-INF/jsp/main.jsp" /> <forward name="fail" path="/WEB-INF/jsp/error.jsp" /> </action> 21.复习文件的上传和下载?22.复习在哪里用到过日期类型,如何处理?23.Struts资源文件在哪里验证文件,页面标签中的使用(国际化)native2ascii 1.txt 2.txt
24.关于异常的进一步理解(Exception vs RuntimeException)25.log4j的属性文件大体了解26.关于项目描述和项目后台扩展27.乱码问题 乱码解决方案:1:create database student default character set=utf8; 2 连接数据库uri设置 jdbc:mysql://localhost:3306/dangdang?characterEncoding=utf8; 3 request.setCharacterEncoding("text/html;charset=utf-8"); //request必须设在第一个得到表单参数之前 4 response.setContentType("utf-8"); 5 在页面中设置<%page pageEncoding="utf-8" %> 6 String str=new String(request.getParameter("name").getBytes("iso-8859-1"),"utf-8"); 7 修改服务器中的server.xml配置文件 <Connector port="8080" protocol="http/1.1" connectionTimeOut="2000" redirectPort="8443" URLEncoding="utf-8" />三大框架整合后在web.xml中可以使用spring封装好的过滤属性进行过滤编码 <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
对字符串可以进行编码和解码: URLEncoder.encode(str,"gbk"); URLDecoder.decode(str,"gbk");28.关于smartstruts中涉及问题1)servlet的相关API2)xml的解析和封装对象3)Commons组件的使用4)多态的使用5)ActionForm的缓存
6)自定义标记库1) 前端控制器 Front Controller 2) 基于Commond模式(?)的Action 配置,通过反射的方式3) commons-digester 解析配置文件,基于配置对象 (常用解析技术dom.sax本案例使用digester来得到表单中的 数据---可以一次性全部得到) 4) Form对象封装且缓存用户提交,底层使用了commons-beanutils.jar5) 支持资源文件,通过标记库 (使用commant类来封装资源文件中的变量 以后页面中信息可以通过commant类中的常量来获得)29.项目中常见的JSTL和EL的使用EL的使用:${value}:从四个范围内进行查找value${emp.name}从四个范围内进行查找emp${requestScope.dept.no} 指定从requestScope中找${param.name} :request.getParameter("name");${empList[0]} empList集合中的第一个元素EL中可以进行的一些运算${a gt b} ${page eq 1}JSTL使用:c:if c:choose c:forEachfmt的使用:<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%><fmt:formatDate var="publishDate" value="${book.publishDate}" pattern="yyyy年M月" /><fmt:formatNumber var="price" value="${book.price}" pattern="¥0.00" />30.http响应的状态码:200:请求成功 202:请求被接受,但是尚未完成 400:错误的请求404:请求资源未找到 500:内部服务器错误,例如后台jsp处理文件语法错误302:重定向时的相应的状态码readyState:在Ajax中readyState对象状态:0=未初始化 1=读取中 2=已经读取 3=交互中 4=完成31 使用UUID来生成唯一标示用于邮箱的验证 public class UUIDUtil { public static String nextCode() { UUID uuid = UUID.randomUUID(); return uuid.toString().toUpperCase(); } }
使用MD5算法进行加密public class MD5Util { public static String md5(String msg) { try { MessageDigest md = MessageDigest.getInstance("MD5"); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(md.digest(msg.getBytes())); } catch (NoSuchAlgorithmException e) { return null; } }}32 使用过滤器:web.xml中的设置在servlet之前设置: <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class> org.whatisjava.dang.filter.CharacterEncodingFilter </filter-class> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping>新建类实现Filter接口并实现其中的方法doFilterpublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("utf-8"); chain.doFilter(request, response); }1 Java 服务器端组件1.1 HTTP协议1.1.1 GET请求如何传递数据--通过地址中的请求参数1) 数据量小 2)文本协议头信息--可以通过request对象的相应方法获得1.1.2 POST请求如何传递数据--通过协议1)数据较大 2)并不安全3)可以传递其他类型4)文本数据的编码问题(同GET)URLEncoder URLDecoder封装了这样的编码算法服务器端的组件在获取数据时需要解码request.setCharaterEncoding(...)POST协议头
1.1.3 HTTP响应
状态码 200 404 500 302 ...响应头信息Content-Type: text/html;charset=utf-8Content-Length: ...服务器端的response对象生成响应的信息response.setContentType(...)
PrintWriter out = response.getWriter();out.println(...);
1.2 Servlet服务器端组件,获取请求信息,动态生成响应Servlet容器 将如何获得请求信息,如何生成响应封装成API(HttpServletRequest HttpServletResponse)同时管理Servlet(实例化,调用生命周期方法)
1.3 JSPJSP指令,指示JSP引擎在生成Servlet的时候要注意的问题<%%> <%=%>内建对象pageContext,request,responseout,session,application
1.4 应用技巧
1.4.1 处理表单1) request.getParameter2) 编码问题 表单提交会编码(按浏览器的当前编码 <%@page contentType="text/html;charset=utf-8"%>) Tomcat默认是ISO8859-1 request.setCharaterEncoding(必须置于request.getParameter之前)3) checkbox的问题 //使用地方:dangdang之前项目分页显示 request.getParameterValues 一个都不选的问题(和文本框不一样)4)数据大小问题5)文件上传 commons-fileupload.jar 获得文件的大小和类型6) 表单的验证(JS)
1.4.2 查询列表1)分页(分页查询oracle rownum / mysql limit,分页显示JDBC 可滚动的结果集)
2)排序(服务器端排序,客户端排序JS)
1.4.3 会话状态的保持Cookie在协议的层面理解具体的API:response.addCookie request.getCookiesage path 大小 多少cookie编码(URLEncoder URLDecoder)封装
Session通过SessionIDSessionID由客户端持有(一般是通过Cookie(age=负数))Session对象由服务器管理(时效)API request.getSession()
1.4.4 MVC在Web中的应用M 数据,数据访问,数据的计算(商业逻辑)V 数据呈现,数据的提交C 控制流程 接收请求,分析请求,调用M,选择V去呈现
转发和重定向 通过request传递数据共享数据范围pageContextrequestsessionapplication
2. Ajax HTML/javaScript EL/Taglib:在服务器端运行 javaScript向服务器发请求 1)XMLHttpRequest 基本访问步骤2)Prototype对Ajax的封装3)JSON的生成和解析4)同步和异步
3.2 Struts 1.2.91) 控制流程请求发给actionServlet---------RequestProcesser2) 如何控制Action粒度DispatchActionMappingDispatchAction
基于Method的反射Method m = clazz.getMethod(String methodName, Class[] args)m.invoke(Object obj, Object[] args)缓存
3) ActionForm的使用技巧封装提交的数据 FormFile来封装表单中的file属性缓存提交的数据,并且通过标记库 回写页面
服务器端验证客户端验证ValidatorForm ValidatorActionForm
4) Struts1的扩展ActionServletRequestProcessorAction
5) Tiles框架 用于设计页面模板6) 资源文件和国际化 <bean:message key=""/> 页面中直接显示 ActionErrors errors = ... errors.addMessage("***",new ActionMessage("...")) 前面是标识,后面是错误信息 return errors; 验证框架通过配置文件自动的完成 <html:errors property="***"/> Action中 ActionMessages msg = ... msg.addMessage("***",new ActionMessage("...")) saveErrors(msg,request); 7) 分模块8) Struts1 的测试 动态页面:即不用写form类但需要在配置文件设置在action中通过f.getString("score");来获得具体设置在struts-config.xml中: <form-beans> <form-bean name="f" type="org.apache.struts.action.DynaActionForm"> <form-property name="score" type="java.lang.String" />//设置表单中的参数 </form-bean> </form-beans>
Token技术:在相应的action中设置this.saveToken(request);在相应的页面中,strut标签库会自动创建一个hidden域type为token并且会随页面一起提交struts标记会根据session中的token生成隐藏表单而隐藏表单的值就是token的值 // isTokenValid方法的含义: 如果当前的session中有token 且和提交来的请求参数中的token相等返回true否则返回false // 参数为true,判断完后从session中删除Token if (this.isTokenValid(request, true)) { String score = (String) f.get("score"); System.out.println(score); }