注意:(容易出错)
form.submit( )
NullPointerException 空指针异常的原因可能在 数据库原有的数据上,
while (rs.next()) { }
注意要用while,不要用if ,不然是不能遍历出来 的
当你把form的enctype设为multipart/form-data之后,
不能用request.getParameter来获取请求参数[X1] 。
var oOption = document.createElement("OPTION"); //或者是select
oOption.text="法拉利"; //这里并不是 innerHTML ,而是text ,js与HTML有一定的区别,查看文档XHTML
css 的属性与JS的属性不同 如:
background-color这是CSS的
backgroundColor 这是JS的
html的用align="center"
css的用 text-align: center;
position:relative ;
clear:both;
最好父类,子类对象里都要加,
写默认的构造器》
定义Vo的时候要用 日期格式,用String 类型
用<s:date />输出 date类型
mysql set names gbk ;
迭代select
<select name="emNumber">
<s:iterator value="employeeSelect">
<option value='${employeeNumber}'>${employeeName}</option>
</s:iterator>
</select>
<s:select
theme="simple"
name="emNumber"
list="employeeSelect"
listKey="employeeNumber"
listValue="employeeName">
</s:select>
集合技术:
标签
${pageContext.request.contextPath} 本地路径
${pageContext.request.queryString}
<%requet.getPageContext()%>
也可以用<base href=”<%=basePath%>”> base标签 DEMO
String basePath = request.getScheme() + "//" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath + "/" ;
MVC
Servlet
Filter: DEMO (Structs代替了)
设置charset
页面权限
---通过URL重写来实现”伪静态” urlrewrite组件(servlet重写)
Listener (相当于servlet start-on...属性)
JSTL
JSP配置
表达式语言 EL(自定义)
Jdbc 数据源(c3p0), DBUtil类 DEMO
javaMail
上传图片
图片上传时用的
把对象放进sessin中时,要先序列化,
private static final long serialVersionUID = 1L;
系统加载前application DEMO
集合:
最好在创建时完成,以防止意外对列表进行不同步的访问:
List list = Collections.synchronizedList(new ArrayList(...));
//得到两个日期的相隔的天数
dateLong = (int)(rs.getDate(4).getTime()-rs.getDate(5).getTime())/3600/1000 ;
列表对象
var newOption = new Option(arr[1] , arr[0]);
cityEle.options[cityEle.options.length] = newOption;
JSP 页面 9个内置对象
表达式11个内置对象
正则表达式:
Java里的表达式 “ ” 并且java里的/要用//
Javascript里的表达式 / /
Session过期的方式:
1. 浏览者超过了指定时间没有访问本站,可认为它的HttpSession过期。
2. 通过程序控制HttpSession过期:
调用HttpSession的invalidate()方法即可。
Web.xml里的 session-timeout里的 30表示30分钟
规定:公司包的规范
Package org.crazyit.项目名.模块名.组件类型名.类名
window.print();">打印报表 JS
tomcat的配置:
修改tomcat端口 conf目录下的server.xml <Connector port = "8080" //理论上1~65535可以放,但1~1024(有名端口)最好不要设置
设置虚拟目录 server.xml 文件,在<Host>元素内添加 <Context path="/myWebsite" docBase="c:/myWebsite" debug="0" />
<Context path="/myWebsite" docBase="c:/myWebsite" debug="0" privileged= "true "/>
设置自动更新修改后的类 context.xml <Context reloadable=”true”>
//在Struts2里这样用
ActionContext ctx = ActionContext.getContext();
ctx.getSession().put("user" , name);
//在Servlet里这样用
request.getSession(true).setAttribute("user", name) ;
request执行forward或include
RequestDispatcher dispacher = request.getRequestDispatcher("/资源");
dispacher.forward(request , response);
dispacher.include(request , response);
referer请求头可获取该请求的上一次的URL。
静态内部类
static class test
{}
表达式后面没有;
final可以修饰局部变量
相当于jsp的<%%>
jsp脚本:
局部内部类
方法里可以定义类
方法里没有初始化块
路径包含空格问题
target iframe DEMO
声明抛出:
子类方法抛出不能比父类方法的小
这种情况下,要用try catch
Stream 字节流
Writer/reader 字符
获取web应用所部署的服务器ip,部署应用名
Request.getLocalAddr() request.getLocalPort()
获取页面浏览器(客户端)的ip,端口
Request.getRemoteAddr() getRemotePort()
获取应用在服务器上所部署的物理位置
Application.getRealPath()
“http://” + request.getLocalAddr() + “:” + request.getLocalPort() + request.getContextPath() + “/list.jsp?username = ” + request.getParamer(“username”)
这里的username最好用uid ,uid用下面的last_insert_id查
Select LAST_INSERT_ID() from ... 选择上次插入的id(auto_increment属性)的id
Request.getDispatcher(“/a.jsp”).forward(request,response)
referer请求头可获取该请求的上一次的URL。
<%@ page contentType="text/html; charset=GBK" %>
text/html;的;前不可以有空格
context-param是位于web-app元素之内,所以它配置的参数对整个web yiettkycftjbe et ,
PreparedStatement ps = conn.prepareStatement("select * from user");
//前后两个statement不同,前一个有d
有时用JDBC获取数据时,getString(中文)会出现乱码
1. 原始的请求参数值,用.getBytes(“iso-8859-1”)分解成字节数组 Byte. valueOf(
String s)
2. 再用new String(byte[],”gbk”)
String rawUid = request.getParamer(“ ”);
String uid = new String(rawUid.getBytes(“ISO-8859-1”) , “gbk”);
对于post请求,如果有中文,为解决乱码,只有调用request.setCharacterEncoding即可
对于get请求,
1. 原始的请求参数值,用getBytes(“iso-8859-1”) 分解成字节数组
2. 再用new String(byte[],”gbk”)
与上面的一样
Mysql数据库:
如果要使用中文存取的话,还必须给定参数useUnicode及characterEncoding,表明是否使用Unicode,并指定字符编码方式,例如:
jdbc:mysql://localhost:3306/demo?user=root&password=123&useUnicode=true&characterEncoding=Big5
Cookie c = new Cookie(“name”,java.net.URLEncoder.encode(“中文字符”,”utf-8”));
解码:Java.net. URLDecoder.decode(c.getValue() , “UTF-8”)
String id = session.getId();
区分每个session
El表达式 (获取页面中javaBean的指定属性)
${cookie["name"].value} //记得有个value
同时也知道了session跟jsessionid紧密不可分割的联系。只有通过jsessionid才能使session机制起作用,而jsessionid又是通过cookie来保存。
现在的浏览器都支持session要求,即使关闭了cookie,浏览器也会向服务器传递sessionid,这个id是存储在浏览器的内存空间中的,不保存在硬盘cookie中。
session.getId()); 得到的跟jsessionid[X2]
下面的方法得到解决的是一样的
Cookie[] cc = request.getCookies();
For(Cookie c : cookies){
If(c.getName().equals(“JSESSIONID”)){
Jseid = c.getValue();
}
}
request.getHeader (“jsessionid”) //这个有点问题
那样的url:http://www.xxx.com/xxx_app;jsessionid=xxxxxxxxxx?a=x&b=x..。jessionid通过这样的方式来从客户端传递到服务器端,从而来标识session。
servlet里得到八个内置对象
pageContext =JspFactory.getDefaultFactory().getPageContext(this,request,response,null,true,8192,true);
HttpSession session = WebContextFactory.get()
// .getSession(true);
Get post区别
如果某个表单域设置了disabled = “disabled”属性,则此表单域不再生成请求参数
数据库插入操作 DEMO
updateString
批处理 demo stmt.addBatch( stmt.executeBatch[X4] ()
JDBC日期问题
Pstmt.setDate(new java.sql.Date(System. currentTimeMillis()
)) [X5] 这个有点问题
应该直接用 now() --mysql
与当前时间比较
Rs是前面返回的一个结果集
System.currentTimeMillis() - rs.getTimestamp(5).getTime() > TIMEOUT * 60 * 1000[X6]
可更新的结果集用
rs.updateRow();
删除当前行 rs.deleteRow();
一般的用
Rs.execute();/executeQuery/ execute..
计时器
CheckOnlineTask 继承了TimerTask
Timer timer = new Timer(true);
CheckOnlineTask task = new CheckOnlineTask(driver , url , user , pass);
timer.schedule(task , 0 , 2 * 1000);
Request.setAttribute(“re”,”request范围的属性”)
Request.getSession(true).setAttribute(“se”,”session范围的属性”)
getServletContext().setAttribute(“ap”,”application范围的属性”)
表达式对上面的应用:
${pageContext}
${pageScope}
${initParam.driver}
${param.user}
${requestScope.re}
${sessionScope.se}
${applicationScope.ap}
包括用到图片,JS,CSS等,都不要用相对路径
要用request.getContextPath()
配置方式
1. web.xml文件的application
2. Java属性文件 .properties ... = ... propertiesDEMO [X7]
InputStream is = this.getClass().getClassLoader()
.getResourceAsStream("db.properties");
//Properties可用于读取属性文件
Properties props = new Properties();
props.load(is);
String driver = props.getProperty("driver");
String url = props.getProperty("url");
String user = props.getProperty("user");
String pass = props.getProperty("pass");
也可以用这种方式:
ResourceBundle cache = ResuourceBundle.getBundle("") ; //不带.properties
String ... = cache.getString("key") ;
3.在java文件里得到
a) ServletContext application = s.getServletContext();
<%@ page contentType="image/jpeg" language="java"%>
图像验证码
@override 强制执行的是子类,好像
Response.setContentType(“text/html;charset=gbk”)
如果重写init方法,要在第一行调用super.init(config)
它的作用是:根据用户请求的URL,forward到指定的JSP.
比如用户请求/abc.do , forward到WEB-INF/jsp/abc.jsp
相当于过滤功能的filer
Servlet配置
<servlet>
<servlet-name> hello</servlet-name>
<!—如果是配置Servlet,这里用servlet-class -->
<!—如果是配置JSP,这里用jsp-file -->
<servlet-class>/hello</servlet- class >
</servlet>
url-pattern
<!-- 这是个通用Servlet -->
<servlet>
<servlet-name>crazyitServlet</servlet-name>
<servlet-class>org.crazyit.bbs.usersys.web.CrazyitServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>crazyitServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- 这是个通用Filter -->
<Filter>
<Filter-name>crazyitFilter</Filter-name>
<Filter-class>org.crazyit.bbs.usersys.web.CrazyitFilter</Filter-class>
<init-param>......
</Filter>
<Filter-mapping>
<Filter-name>crazyitFilter</Filter-name>
<url-pattern>/*</url-pattern>
</Filter-mapping>
Filter一般功能:
设置charset
页面权限
通过URL重写来实现”伪静态” (相当于之前的servlet功能)
public int update(String sql , Object... args)
放在java文件所在的包下面
视图层 - JSP.
控制器 - Struts1/Struts2等
业务逻辑层 - 负责实现系统的业务逻辑。
(其实软件都是更好地管理信息。Information,也需要访问数据库,只是它会通过DAO/EAO来访问数据库)
DAO/EAO (Entity Access Object) - 主要负责数据访问。
Domain Object
JSP - Java Server Page。
JSP必须位于Java Web应用中。JSP比Java简单很多。
Java Web应用又必须运行Web容器中。
Web容器:
- Tomcat
- Jetty
- Resin
安装Tomcat
1. 解压缩。
2. 配置JAVA_HOME , (是JDK的安装目录。)
容易犯错:a. 不是指向JDK的bin目录。 b. 更不是Tomcat的安装目录。
修改端口:修改conf/server.xml文件的69行。
进入Tomcat控制台:
修改conf/tomcat-users.xml
<role rolename="manager"/>
<user username="xx" password="xx" roles="manager"/>
自己做一个Web应用:
xxx
| - WEB-INF
| - web.xml
让Tomcat流出Web应用下所有页面资源:
修改conf/web.xml文件的95行,将其改为true。 好像是param-value
web.xml 它是Web应用的配置描述符。
它可以:
配置和管理Servlet/JSP。
配置和管理Filter。
配置和管理Listener。
配置标签库。
配置JSP属性
...
JSP页面:在静态的HTML页面中嵌入动态的JSP脚本。
不被JSP脚本控制的,就是普通的静态页面;JSP脚本控制的就会动态改变。
JSP其实是Servlet的草稿,最终起作用的不是JSP,而是Servlet。
JSP → Servlet
而且由JSP生成的Servlet中包含了3个有特殊意义的方法:
init
destroy
service
JSP页面第一次被请求时,会生成对应的Servlet。
以后再请求时,将直接使用已有的Servlet来提供服务。
学习Java Web编程,眼中看到的是JSP,心中想的是Servlet。
JSP的四种语法:
1. 注释。
Java的注释
//
/* */
/** */
JSP注释: 跟.net的一样
<%-- --%>
JSP注释在服务器端被服务器忽略,不会送给客户端浏览器。
HTML注释会送给客户端浏览器。
2. 声明 [W1]
声明的语法格式:
<%! %>
包括声明变量、方法、内部类等等。
JSP声明的内容最终转换成Servlet的成员部分。
-----------------------------------------------------------
Java类中可定义的成员 JSP声明部分可定义的成员
Field (属性) Field
方法 方法
构造器 ×
内部类 | 接口 | 枚举 内部类 | 接口 | 枚举
初始化块 初始化块
3. 输出表达式
<%= 表达式%> HttpServletRequest 输出表达式,最终转换成Servlet的service方法里的out.print(表达式);
可以说,输出表达式就是out.print();方式的简写!!
4. JSP脚本
<% %>
JSP脚本转换成Servlet中service方法的可执行性代码。
访问控制符、static不能修饰局部变量。
因此JSP脚本部分放的,就是局部成员:局部变量,局部内部类,执行性的代码。
JSP页面的所有静态内容,都会对应的Servlet里的service方法的
out.write()来执行输出。
JSP的4个基本语法:
1. 注释 <%-- --%>
2. 声明 <%! %> 转换成对应Servlet的成员部分。
3. 输出表达式 <%= %> 转换Servlet的service里的out.print();输出语句。
4. 脚本 <% %>
JSP的3个编译指令
编译指令是通知JSP引擎的消息,它不会直接生成输出。
<%@ 指令名 属性名1="val1" 属性名2="val2" %>
Page
include
taglib
page指令
<%@ page %>
import属性:用于导入包。与Java程序中的import语句类似
contentType属性:服务器向客户端发浏览器送响应。
服务器应该先送一个消息:响应内容是什么类型
mime类型, 在Tomcat的conf/web.xml文件中可以找到。
除了要给出mime类型之外,还应给出编码所用的字符集。
Extends 指定JSP页面编译所产生的类所继承的父类,功实现的接口
Info 可直接调用getServletInfo()方法获取此值 [W2]
所谓字符集:就是给现有的字符一套系统的编号。
gb2312 → GBK
errorPage
isErrorPage
include指令
包含:它会把目标页面插入到当前页面中
include编译指令,我们又叫:静态包含。 只生成一个class,不能带参数,同一个requeset对象
静态包含:
1. 被包含的页面内容被完全合并到了Servlet中。
2. 被包含页面的编译指令也会被导入。当两个页面的编译指令的属性值
冲突时,程序就会出错。
JSP的7个动作指令:
编译指令是通知JSP引擎的消息。
动作指令是可执行的脚本行为,也就是动作指令完全可以替换成JSP脚本。
因为JSP脚本往往比较丑陋,而JSP动作指令比较规范、好看。
<jsp:指令名 属性1="val1" 属性2="val2".../>
<jsp:forward page="".../> , page指定forward的页面。
forward是用page指定的页面替换当前页面的响应。
<jsp:include page="".../> , page指定include的页面。
incldue是用page指定的页面插入当前页面的响应中。
include编译指令,我们又叫:静态包含。 只生成一个class,不能带参数,同一个requeset对象
<jsp:include.../>是动态包含: 会产生多个class,可以带参数,不同的requeset对象
<jsp:include.../>是动态包含: 会产生多个class,可以带参数,不同的requeset对象
1. 被包含页面的编译指令不会被导入。
2. 动态包含不会把被包含页面的内容完全合并到当前页面中。
它不会导入被include页面的编译指令,仅仅将被导入页面的body内容插入本页面
<jsp:inlcude page="" flush="" > [W3]
还可额外增加参数,param
u[W4] seBean 在JSP页面中创建一个JavaBean的实例。初始化一个实例 javaDEMO jspDEMO
<jsp:useBean id= class= scope="page|request|session|application"> [W5]
setProperty 为JavaBean的实例设置属性。
<jsp:setProperty name[W6] = property= value=>
getProperty 访问并输出JavaBean实例的属性。
Web应用下有两个特殊的目录:
WEB-INF/lib
WEB-INF/classes
这两个目录的作用完全一样:当你把Java类的二进制文件丢到这两个目录下,
该Web应用就可以使用这些Java类了。
有一点小小的区别:如果是散的*.class,就放在classes目录下
如果是被打包后的JAR包,就放在lib目录下。
7个动作指令:
<jsp:forward page="" .../> [W7]
<jsp:include page="" .../>
<jsp:useBean id="" class="" />使用class指定的类来创建JavaBean的实例。
<jsp:setProperty name="beanName" property=" " value="val" />:为JavaBean设置属性。
<jsp:getProperty name="beanName" property=" " />:访问并输出JavaBean的属性。
<jsp:param .../>:一个param通常配置一个参数, DEMO
参数总是两部分:参数名和参数值。
它往往不会单独使用,它可以与<jsp:forward | include.../>一起使用。
这样就可以向被包含 或 是被forward的页面传入额外的参数
增加的请求参数的值可以通过HttpServletRequest 类的getParameter()方法获取,这 个方法也是获得表单传输数据的那个方法
<jsp:plugin .../>几乎不用了! javaDEMO jspDEMO
9个内置对象
为什么JSP中有9个可以直接使用的对象呢?
普通JSP页面里,能用的就是8个内置对象
PageContext pageContext = null; javax.servlet.jsp.
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
javax.servlet.jsp.JspWriter out = null;
Object page = this;
HttpServletRequest request,
HttpServletResponse response
这8个内置对象中,request、response是Servlet的service方法的形参,
而其他6个是Servlet的service方法里的局部变量。
只有JSP脚本部分和JSP输出表达式可以使用9个内置对象,
千万不要在JSP声明部分使用9个内置对象。
page :就是代表当前JSP页面。但实际上JSP页面并不能拿来使用。
所以page实际上代表Servlet的当前实例。
out :它代表JSP页面的基本输出流。 javax.servlet.jsp.JspWriter
可以向客户端的浏览器执行输出。
config :它代表了Servlet的配置,
因此可以通过config来获取Servlet的配置信息。
config对JSP来说,一般是没有用处的。
可以把JSP页面当成Servlet来配置
在web.xml文件的<servlet .../>元素中通过<init-param.../>可配置参数
Web.xml query.jsp config.getInitParameter("driver")
application: Web.xml query2.jsp
1.读取web应用的配置参数
getInitParameter(String name)
为web应用配置初始化参数用的<context-param.../>,它配置的参数对整个web应用有效
2.访问application scope的属性.
存出数据 application.setAttribute("app_name" , "疯狂Java联盟");
取出数据 application.getAttribute("app_logo")
从用户访问网站开始,直到他离开该网站为止,
只要他依然在访问该网站的任何页面,那么他与网站的会话就一直有效。
不会生成第二次的请求,并没再次向服务器发送请求
request HttpServletRequest的实例。
a. 获取请求参数或请求头。
Web应用,本质上是请求/响应架构的。
Enumeration getHeaderNames()
Enumeration getHeaders(String name)
String getHeader(String name)
Map getParameterMap() - 获取所有请求参数组成key-value对
Enumeration getParameterNames() - 所有所有的请求参数名
String[] getParameterValues(String name) - 这个方法功能更强大。
String getParameter(String name) - 这个方法可当成getParameterValues的特例。
Request.getDispatcher(“/[W1] a.jsp”).forward(request,response)
referer请求头可获取该请求的上一次的URL。
它们都是key-value对,都是由名字、值两部分组成。
区别在于请求参数是程序员可控制的,请求参数的名字通常是由表单域的name属性决定的。
请求头的名字和值不是由程序员可控制的,它是浏览器负责生成。
通过表单域和请求,Web应用就可以收集用户的输入信息了。
b . 访问request scope的属性。
request scope只对一次请求有效。
setAttribute();
getAttribute();
c . 执行forward或include
RequestDispatcher dispacher = request.getRequestDispatcher("/资源");
dispacher.forward(request , response);
dispacher.include(request , response);
Jsp页面/servlet并不会由程序员调用,
运行在web 容器里,由web容器调用,为了让不同的web组件之间可以共享数据,
Web应用就维护了4个类似银行的scope
Page
Request:代表用户的请求,
request.getParameter();
request.getParameterValues();
Session:如果是属于用户自定义的,就放在session里 Session.setAttribute
Application:对整个web应用都有效,只要web应用没有重启,那么存入此范围的数据都是有效的。
response 代表服务器响应。HttpServletResponse实例 response响应生成图片DEMO
1. 生成非文本响应。
如果生成普通文本输出,用out执行输出就可以了。
response.getOutputStream() 返回了一个字节输出流。
2. 添加Cookie DEMO
1. 创建Cookie对象
2. 设置Cookie的生存时间。
如果不设置,Cookie会随着浏览器关闭自动失效。
3. 调用response的addCookie方法来添加Cookie.
读Cookie使用request对象 DEMO
3. 执行重定向。
response.sendRedirect("页面"); [W2]
执行重定向:本质是服务器强制浏览器发送了第二次请求。
与浏览者直接在浏览器的地址栏里输入新的地址,然后回车请求的效果一样。
Forward和redirect对比 | |
转发(forward) | 重定向(redirect) |
依然是上一次请求 | 生成第二次请求 |
Forward的目标页面可以访问原来请求的请求参数, 因为依然是同一次请求,所有原请求的请求参数 、 Request范围的属性全部存在 | 不能 |
地址栏请求的URL不会改变 | URL改变,相当于重新输入了新的URL |
Response.setContType(“text/html;charset=gbk”)
javax.servlet.jsp.pageContext PageContext
pageContext它所代表的是当前页面的上下文,因此它的功能很强大:
1. 它可以获取其他的内置对象。
2. 它还可以访问4个scope的属性。
//默认情况下,pageContext将属性放入PAGE_SCOPE范围内
pageContext.setAttribute("user","孙");
//放入application scope范围内
pageContext.setAttribute("count",1000,PageContext.APPLICATION_SCOPE);
application scope内的属性, 用application(ServletContext)来读取
session scope内的属性, 用session(HttpSession)来读取
request scope内的属性, 用request(HttpServletRequest)来读取
page scope内的属性, 用pageContext(PageContext)来读取
实际上pageContext可以访问4个范围内的属性。
第9个内置对象:exception
并不是在所有JSP页面中都存在,只在特殊页面中才存在!!
为什么JSP脚本不需要处理异常?
JSP脚本都会被放入对应Servlet的service方法中try块里。
那么JSP声明中方法是否需要处理异常?要!!!
try
{
普通JSP页面的JSP脚本都位于此!
——通过@page编译指令的errorPage指定异常页面。
}
catch(Throwable t)
{
异常处理页面。
——通过@page编译指令的isErrorPage来自己就是异常处理页面
}
只有当一个JSP页面的@page编译指令的isErrorPage="true"时,
该页面中才存在exception内置对象,该对象就代表上一个页面的异常。
增加Cookie:
Servlet
直接编写Servlet
1. 继承HttpServlet Filter实现Filter接口。
2. 重写向客户端提供响应的方法。
3. 如果Servlet有初始化操作,那就要重写init()方法。
一般在init()方法中初始化了资源,那么应该在destroy()方法中回收资源。
开发servlet有三种方法: 需引入servlet-api.jar
实现servlet接口 DEMO
继承GenericServet 只需重写service方法即可 DMEO
HttpServlet用户登录DMEO
Servlet配置
<servlet>
<servlet-name> hello</servlet-name>
<!—如果是配置Servlet,这里用servlet-class -->
<!—如果是配置JSP,这里用jsp-file -->
<servlet-class>/hello</servlet- class >
</servlet>
<servlet-mapping>
<servlet-name> hello</servlet-name>
<servlet-pattern>/hello</servlet-pattern>
</servlet-mapping>s简单了,
而复杂的多线程处理、网络通信IO这些底层细节都是由Web容器来处理的。
request.getParameter("abc")
1. 你的Servlet是由Web容器负责调用的。
2. Servlet天生就是多线程。
3. 服务器永远调用Servlet的doGet/doPost/ service方法来生成响应。
Init方法最多只调用一次 如果重写init方法,要在第一行调用super.init(config)
Destory方法只调用一次
Service方法 每当用户访问时都会启动
测试已经有几人访问网站:
Servlet DEMO
load-on-startup Servlet demo
应用关闭之前运行它的destory方法
它的作用是随着Web的启动自动启动。
如果一个Servlet不需要对用户生成响应,那么就可以不重写service方法,
配置时也不需要为它配置<servlet-mapping.../>元素
load-on-startup只接收一个整型值,这个整型值越小,Servlet就越优先实例化
load-on-startup的Servlet,一般不会生成响应,
它一般可用于初始化某些资源,或启动某些后台监控线程。
<load-on-startup>1</load-on-startup>
//配置应用启动时,创建servlet实例
Filter
=========Servlet获取初始化参数,用ServletConfig的getInitParaemeter
init(
ServletConfig config)
==========
Filter类的要求:
a. 实现Filter接口。 Servlet继承HttpServlet
b. 重写doFilter方法
c. 如果它需要初始化,重写init()方法,如果它需要在销毁之前回收资源,重写destroy方法。
配置Filter
<filter>
<filter-name>
<filter-class>
<init-param.../>
</filter>
=========Filter获取初始化参数,用FilterConfig的getInitParaemeter
init(
FilterConfig config)
.=========
<filter-mapping>
<filter-name>
<url-pattern>
</filter-mapping>
它与Servlet的区别在于:Filter通常不会对用户请求生成响应(虽然也可以),
1. Filter对用户的请求进行预处理(Pre process)。
2. Servlet(JSP)对用户请求进行处理, 并生成相应。
3. Filter对服务器的响应进行后处理(Post process)。
我们认为它是Servlet一种变种,或者说它是“扩展”后的Servlet。
它和Servlet非常像!
Servlet类的要求。
a. 继承HttpServlet
b. 如果它响应用户请求,重写doGet/doPost/service方法。
c. 如果它需要初始化,重写init()方法,如果它需要在销毁之前回收资源,重写destroy方法。
配置Filter [W2] LogFilter.java AuthorityFilter.java web.xml
<filter>
<filter-name>
<filter-class>
<init-param.../>
</filter>
=========Filter获取初始化参数,用FilterConfig的getInitParaemeter.=========
<filter-mapping>
<filter-name>
<url-pattern>
</filter-mapping>
它与Servlet的区别在于:Filter通常不会对用户请求生成响应(虽然也可以),
1. Filter对用户的请求进行预处理(Pre process)。
2. Servlet(JSP)对用户请求进行处理, 并生成相应。
3. Filter对服务器的响应进行后处理(Post process)。
Filter的生命周期和Servlet的生命周期都非常像。
init() destroy()
实例 → 初始化完成 → 通过service来生成响应 → 销毁之前 → 被回收
init() destroy()
实例 → 初始化完成 → 通过doFilter来执行过滤 → 销毁之前 → 被回收
Servlet中,有一种特殊的Servlet,它叫做load-on-startup的Servlet。
listener启动时机比load-on-starup Servlet早,
这种Servlet它会Web应用的启动而自动初始化。
应用启动时,创建load-on-startup的Servlet,并执行它的init()方法。
应用关闭之前,执行它的destroy()方法。
从Servlet 2.4规范开始,引入了Listener规范来“代替”原有的load-on-startup
Listener并不能处理用户请求、对客户端生成响应。
创建Listener类的要求:
a。 实现ServletContextListener
b。 实现contextInitialized(ServletContextEvent sce)和
contextDestroyed(ServletContextEvent sce)两个方法。
配置Listener
比配置Servlet简单得多 DEMO
1。 Listener无需配置xxx-mapping。
2。 Listener无需配置初始化参数。
Listener的初始化时机,比所有的load-on-startup Servlet启动时机更早。
==========上面这种Listener用于监听整个Web应用=========
还有如下Listener:
ServletContextAttributeListener : 用于监听application scope内属性的改变。
当用application.setAttribute()这种方法就可以改变application scope内的属性。
HttpSessionAttributeListener :用于监听session scope内属性的改变。
ServletRequestListener:它用于监听客户端请求。
当客户端请求到达时,激发该监听器的requestInitialized(ServletRequestEvent sre)
当客户端处理完成时,激发该监听器的requestDestroyed(ServletRequestEvent sre)
HttpSessionListener :它用于监听客户端会话(Session) (用于监听在线用户好简单)
当客户端会话开始时,激发该监听器的sessionCreated(HttpSessionEvent se)
当客户端会话结束时,激发该监听器的sessionDestroyed(HttpSessionEvent se)
JSP 2在JSP 1.2的基础上进行了改进,使之更加简单。
Java EE 5 Java EE 6
JSP1.2 → JSP 2.0 → JSP 2.1 → JSP 2.2
Servlet 2.3 → Servlet 2.4 → Servlet 2.[W4] 5 → Servlet 2.6
相比JSP1.2,JSP2主要增加了如下新特性:
直接配置JSP属性
表达式语言
简化的自定义标签API
Tag文件语法
自定义标签库
目的就是为了取代JSP脚本。
7个动作指令就是为了代替JSP脚本。7个动作指令能完成的功能太有限了。
所有出现了自定义标签库,自定义标签库可以完全取代JSP脚本。
标签库属于视图组件,作用是取代JSP脚本!
前不要把标签和Servlet搞混!
Servlet是控制器组件。
Writer out = getJspContext().getOut();
Servlet2.5规范支持jsp2.0 2.1
开发标签库
1. 开发标签处理类。
a . 继承SimpleTagSupport
b . 重写doTag方法。该方法负责在页面上生成输出。
1 //使用JspWriter获得JSP的输出对象
2 JspWriter jspWriterOutput = pageContext.getOut();
3 jspWriterOutput.print("Hello Tag!");
2. 使用TLD文件定义标签库。
TLD文件的根元素是<taglib>
<taglib>元素下的<uri.../>指定该标签库的标识符。
<taglib>元素下的每个<tag.../>定义一个标签。
<div/>
//3.加到web.xml中
当然,我们还需要将我们自定义的标签添加到 web.xml 中,否则还是无法使用。
1 <taglib>
2 <taglib-uri>/tagTest </taglib-uri>
3 <taglib-location>/WEB-INF/tagTest-html.tld</taglib-location>
4 </taglib>
4.使用标签库
a. 使用taglib编译指令导入标签库。
<%@ taglib uri="http://www.crazyit.org" prefix="crazyit"%>
b. 使用标签:<prefix:标签名 属性名=属性值 .../>
==== 带属性的标签 ====
a. 标签处理类:为标签库处理类增加属性定义,并为每个属性提供getter和setter方法。
b. 在TLD文件中,为tag元素增加attribute子元素。
==== 带标签体的标签 ==== 见实例mvc_tag
a. 标签处理类中,使用getJspBody().invoke(null);来执行、输出标签体。
b. 在TLD文件中红,将body-content元素的值改为scriptless。
但实际上,普通开发者通常只要使用标签就够了。
标签库TLD文件中,
<required>true</required> 表此标签的此属性是必填的。
有一套非常出名的标签库,JSTL JSP标准标签库。
===========JSTL的常用标签==========
c:out 执行输出。学完JSP 2的EL之后这个没用。
c:if 判断。
c:choose
c:when
c:otherwise
c:forEach
c:redirect 重定向。
例子:
<c:redirect url="login.jsp">
<c:param name="id" value="888"/>
</c:redirect>
将参数888以id为名字传递到login.jsp页面,相当于login.jsp?id=888
${code:urlDecode(pub.phone)}
但不能这样用${code:urlDecode(${pub.phone})} 好像
C:foreach 时,可以用${requestScope.xxxx } 这样快点,可以直接编历requestScope里的
配置JSP属性:
<jsp-config>
<jsp-property-group>
<!-- 对哪些文件应用配置 -->
<url-pattern>/noscript/*</url-pattern>
<!-- 忽略表达式语言 -->
<el-ignored>true</el-ignored>
<!-- 页面编码的字符集 -->
<page-encoding>GBK</page-encoding>
<!-- 不允许使用Java脚本 -->
<scripting-invalid>true</scripting-invalid>
<!-- 隐式导入页面头 -->
<include-prelude>/inc/top.jspf</include-prelude>
<!-- 隐式导入页面尾 -->
<include-coda>/inc/bottom.jspf</include-coda>
</jsp-property-group>
<jsp-property-group>
<!-- 对哪些文件应用配置 -->
<url-pattern>*.jsp</url-pattern>
<el-ignored>false</el-ignored>
<!-- 页面编码字符集 -->
<page-encoding>GBK</page-encoding>
<!-- 允许使用Java脚本 -->
<scripting-invalid>false</scripting-invalid>
</jsp-property-group>
<jsp-property-group>
<!-- 对哪些文件应用配置 -->
<url-pattern>/inc/*</url-pattern>
<el-ignored>false</el-ignored>
<!-- 页面编码字符集 -->
<page-encoding>GBK</page-encoding>
<!-- 不允许使用Java脚本 -->
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
EL
11个内置对象。
pageContext 与JSP的pageContext内置对象相同
pageScope
requestScope
sessionScope
applicationScope
param 获取请求的参数
paramValues 数组
Header 用于获取请求头的属性值
headerValues 数组
initParam: 用于获取Web应用的初始化参数 相当于调用application.getinitParam..
Cookie: 指定的cookie值
Request.setAttribute(“re”,”request范围的属性”)
Request.getSession(true).setAttribute(“se”,”session范围的属性”)
getServletContext().setAttribute(“ap”,”application范围的属性”)
表达式对上面的应用:
${initParam.driver}
${param.user} //取得请求参数
${requestScope.re}
${sessionScope.se}
${applicationScope.ap}
${cookie["name"].value}
<!-- 使用两种方式获取请求参数值 -->
<td>取得请求参数值</td>
<td>${param.name} </td>
<td>取得请求参数值</td>
<td>${param["name"]} </td>
<!-- 使用两种方式获取指定请求头信息 -->
<td>取得请求头的值</td>
<td>${header.host}</td>
<td>取得请求头的值</td>
<td>${header["accept"]}</td>
<td>取得初始化参数值</td>
<td>${initParam["author"]}</td>
<td>取得session的属性值</td>
<td>/${sessionScope["user"]}</td>
<td>取得指定Cookie的值</td>
<td>${cookie["name"].value}</td>
自定义函数开发步骤
1. 定义一个类,或直接用系统已有的类也行——关键是该类里有静态方法即可。
2. 使用TLD文件来定义函数。 Functions.java useFunction.jsp
<!-- 定义 一个函数 -->
<function>
<!-- 定义函数名:reverse -->
<name>reverse</name>
<!-- 定义函数的处理类 -->
<function-class>lee.Functions</function-class>
<!-- 定义函数的实现方法-->
<function-signature>
java.lang.String reverse(java.lang.String)</function-signature>
</function>
<!-- 定义第二个函数: countChar -->
<function>
<!-- 定义函数名:countChar -->
<name>countChar</name>
<!-- 定义函数的处理类 -->
<function-class>lee.Functions</function-class>
<!-- 定义函数的实现方法-->
<function-signature>int countChar(java.lang.String)
</function-signature>
</function>
EL表达式语言:
为了获得集合中的属性,EL支持以下两种操作
1. 使用.操作符来获得有名字的属性。例如表达式${user.username}表明对象user的username属性
2. 使用[]操作符来获得有名字或按数字排列的属性。
表达式${user["username"]}和表达式${user. username }含义相同
表达式${row[0]} 表明row集合的第一个条目。
在这里user是一个类的对象,它的属性username必须符合标准JavaBean的规范,即必须为username属性定义相应的getter、setter方法。
计算除法
${3/4}
${3/0}
${3 div 4}
计算求余
${10 % 4}
${10 mod 4}
三目运算
${(1 == 2) ? 3 : 4}
使用逻辑运算符
==或eq 相等检查
!=或ne 不等检查
<或lt 小于检查
>或gt 大于检查
<=或le 小于等于检查
>=或ge 大于等于检查
<select >
<c:forEach items="${publishList}" var="pub" >
<option>
${pub.name}
</option>
</c:forEach>
</select>
Tag File支持
Java mail (先把防火墙关掉)
SMTP simple mail transaction protocol 简单邮件传输协议 主要用来发邮件 端口:25
POP3 邮局协议 ,离线接收邮件的协议,默认端口是110
IMAP4 交互邮件访问协议,与pop3协议不同的是,可以客观地
JavaMail ,JavaMail 1.4 ,除此之外,JavaMail依赖于另一个:JAF。
在应用程序中使用JavaMail,需要两个JAR包。javamail1.4, activation
Java.activation.*
常用API
-------------------代表连接邮件服务器,用于发送接收。。-----------------------------
JAVAX.mail.Session 代表邮件会话
Javax.mail.Transport 发送邮件
Javax.mail.Store 接收邮件
Javax.mail.Folder 收邮件时,不同类型的xx箱
---------------处理邮件本身-------------------------
Javax.mail.MimeMessage 邮件本身
Javax.mail.Address 收件人,发件人的地址
Javax.mail.Multipart 保存邮件内容的容器,用于组织邮件的。。
Javax.mail.BodyPart 代表邮件的一部分(邮件的正文是一个BodyPart,附件也是一个BodyPart)
------------- 处理附件------------------
Javax.activation.FileDataSource 需要发送附件时,用来读取本地磁盘文件,并将其为附件发送
Javax.activation.URLDataSource 读取远程资源,实际上用得少
发送步骤: DEMO
1. 创建session对象
2. 以session实例为参数创建MimeMessage对象--------代表一个空的邮件
3. 为MimeMessage[X1] 对象设置合适的属性和内容。--------填充的,设置邮件标题 ,正文。。
4. 使用抽象类Transport 的send或sendMessage方法发送邮件
可以指定多个人,多个抄送,多个暗抄
Message.RecipientType.TO 普通
Message.RecipientType.BCC 暗抄
Message.RecipientType.CC 抄送
接收步骤: DEMO
接收邮件的步骤:
(1)创建邮件Session实例。
(2)以Session实例获取邮件存储对象(即Store对象)。调用Store对象的connect()方法执行连接。
(3)调用Store对象的getFolder()方法来获取指定的邮件文件夹(例如收件箱、垃圾箱等,这取决于邮件服务器上的配置)。
(4)调用Folder的open()方法打开指定的邮件文件夹,接下来就可执行它的getMessages()方法来获取该文件夹内所有邮件。
(5)遍历每封邮件,提取邮件内容。