【Web】 Java考点对策

Http协议

请求

一个http请求代表客户端浏览器向服务器发送的数据。一个完整的http请求消息,包含一个请求行若干个消息头(请求头)换行实体内容
Alt text

请求头(消息头)包含(客户机请求的服务器主机名,客户机的环境信息等):

  • User-Agent:客户机通过这个头告诉服务器,客户机的软件环境(操作系统,浏览器版本等)
  • Connection:告诉服务器,请求完成后,是否保持连接
  • If-Modified-Since:客户机通过这个头告诉服务器,资源的缓存时间
  • Accept: 告诉服务器可以接收的文件类型
  • Accept-Charset:用于告诉服务器,客户机采用的编码格式
  • Accept-Encoding:用于告诉服务器,客户机支持的数据压缩格式
  • Accept-Language:客户机语言环境
  • Host: 客户机通过这个服务器,想访问的主机名
  • Referer:客户机通过这个头告诉服务器,它(客户端)是从哪个资源来访问服务器的(防盗链)

实体内容:
就是指浏览器端通过http协议发送给服务器的实体数据。例如:name=dylan&id=110
Alt text
cookies间用:

回应

一个http响应代表服务器端向客户端回送的数据,它包括:
一个状态行若干个消息头,以及实体内容
Alt text

响应头(消息头)包含:
Allow:允许哪些请求方法,post get等

  • Location:这个头配合302状态吗,用于告诉客户端找谁
  • Server:服务器通过这个头,告诉浏览器服务器的类型
  • Content-Encoding:告诉浏览器,服务器的数据压缩格式 gzip,deflate, sdch….
  • Content-Length:告诉浏览器,回送数据的长度
  • Content-Type:告诉浏览器,回送数据的类型
  • Last-Modified:告诉浏览器当前资源缓存时间,只有改动时间迟于该时间的才会返回。否则304 一般与与If-Modified-Since一起用
  • Refresh:告诉浏览器,隔多长时间刷新
  • Content-Disposition:告诉浏览器以下载的方式打开数据。例如: context.Response.AddHeader(“Content-+ Disposition”,”attachment:filename=aa.jpg”); context.Response.WriteFile(“aa.jpg”);
    Transfer-Encoding:告诉浏览器,传送数据的编码格式
  • ETag:缓存相关的头,类似一个资源hash函数的存在。可以发现资源是否有变化
  • Expries: 过期时间,绝对= max-age+请求时间
  • Cache-Control:控制浏览器缓存 如

          Cache-Control: public, max-age:350000
    
  • max-age:是HTTP/1.1中的 过期时间。是个相对的值(相对于请求时间)

  • Connection:响应完成后,是否断开连接。 close/Keep-Alive
  • Content-Disposition
    Date:告诉浏览器,服务器响应时间

》通过AddHeader函数可以为HTTP消息头加入我们自定义的内容。使用这种方法可以强制让浏览器提示下载文件,即使这个文件是我们已知的类型,基于是HTML网页。如果想要让用户下载时提示一个默认的文件名,只需要在前面一句话后加上“filename=文件名”即可。例如:

Response.AddHeader("Content-Disposition: attachment; filename=mypage.htm");

!!Http缓存

http缓存有强缓存,协商缓存
步骤1. 浏览器先根据这个资源的http头信息来判断是否命中强缓存。如果命中则直接加在缓存中的资源,并不会将请求发送到服务器。(返回200)
2.如果未命中强缓存,则浏览器会将资源加载请求发送到服务器。服务器来判断浏览器本地缓存是否失效*。若可以使用,则服务器并不会返回资源信息,浏览器继续从缓存加载资源。
3.如果未命中协商缓存,则服务器会将完整的资源返回给浏览器,浏览器加载新资源,并更新缓存。

在页面设置 如

<meta http-equiv="Cache-Control" content="no-cache"/>

强缓存

利用http的回应头中的Expires或者Cache-Control两个字段来控制的。

Cache-Control:

 Cache-Control: max-age=30  也可以填 no-cache(每次用缓存前都会发请求), no-store 不缓存 public private(不允许任何web代理进行缓存,)
 Expires: Wed, 21 Oct 2015 07:28:00 GMT

同时启用的时候Cache-Control优先级高

协商缓存

服务器根据http头信息中的Last-Modify/If-Modify-SinceEtag/If-None-Match来判断是否命中协商缓存。如果命中,则http返回码为304,浏览器从缓存中加载资源。
Alt text

http状态码:

2xx OK
—>200 OK
—>201 创建
—>202 接收
—>203 和200一样,不过是说未经认证。。可能是复制得到的

3xx 重定向
—>301 代表永久性转移(Permanently Moved) 302是暂时
—>302 Object Moved Alt text 要根据Location重新发请求
—> 303 当请求者应对不同的位置进行单独的 GET 请求以检索响应时,服务器会返回此代码`
—>304 未修改

4xx 客户端错误
—>400 请求语法错误
—>401 (访问拒绝)客户端证书无效,账号密码错误
—>403 Access Forbidden 请求结构正确。但是服务器不想处理.403暗示了所请求的资源确实存在。跟401一样,若服务器不想透露此信息,它可以谎报一个404
—>404 资源不存在
—>405 请求方法错误。比如用了不支持的协议,或者不支持get,结果用了get
—>410 资源曾经存在

5xx:服务器端错误
502 代理错误
500 异常
501 服务器不能识别一个方法。类似405,但是405是能够被服务器识别,但是资源不支持该方法.
503 目前服务器处理不了,一段时间后可能正常
101表示服务器已经理解了客户端的请求,并将通过Upgrade消息头通知客户端采用不同的协议来完成这个请求。

COOKIES

Set-Cookie: key=haha; expires=Sun, 31-Dec-2006 16:00:00 GMT; path=/
Set-Cookie: ASPSESSIONIDCSQCRTBS=KOIPGIMBCOCBFMOBENDCAKDP; path=/ (会话)

媒体类型

Alt text
text/xml忽略xml头所指定编码格式而默认采用us-ascii编码,而application/xml会根据xml头指定的编码格式来编码:

URL

三部分: schema协议 主机地址 资源路径

post和get的区别:

都包含请求头请求行,post多了请求body。
get多用来查询,请求参数放在url中,不会对服务器上的内容产生作用。post用来提交,如把账号密码放入body中。
GET是直接添加到URL后面的,直接就可以在URL中看到内容,而POST是放在报文内部的,用户无法直接看到。
GET提交的数据长度是有限制的,因为URL长度有限制,具体的长度限制视浏览器而定。而POST没有。
超限返回414
GET能被缓存,POST不能
GET只允许ASCII字符,POST没有限制

当客户端仅希望看到响应的头部时,例如Content-Type或Content-Length,它发送一个HEAD请求。HTTP HEAD方法对响应中的输出字节进行计数,以便准确地设置Content-Length报头。

Put

把消息本体中的消息发送到一个URL,跟POST类似,但不常用。
向指定资源位置上传其最新内容。一般是用来数据更新

TRACE

回显请求。一般用来测试

HTTP特点

  • 无连接
    每次连接只处理一个请求,处理完请求并受到客户端应答后即断开连接
    1.1版本后可以用Connnection: KeepAlive 长连接,一段时间后才会断开 (1.0默认关闭,1.1默认打开)
    如何判断请求已完成:
    Content-Length,Transfer-Encoding:chunked 或者gzip,chunked,当收到大小为0的chunked时代表接收完成
  • 无状态
    对事物处理没有记忆能力,因此出现了一些方式进行会话追踪
    4种会话追踪技术:
    • cookies
    • 隐藏域。把数据存储在一个隐藏域里

             <input type='hidden' value='xxx'/>
      
    • session(本质也是用cookies实现的)
    • url重写: 在url尾部添加额外一些数据,标识当前会话
  • 支持C/S模式

数据压缩

标签

SimpleTag接口

继承了JspTag

  • setJspContext方法
      用于把JSP页面的pageContext对象传递给标签处理器对象
    setParent方法
      用于把父标签处理器对象传递给当前标签处理器对象
    getParent方法
      用于获得当前标签的父标签处理器对象
    doTag方法
      用于完成所有的标签逻辑

Tag接口

  • doEndTag()
  • doStartTag()
  • setPageContext(PageContext pc)
  • setParent(Tag t)

TagSupport

public class TimeTag extends TagSupport{
public int doStartTag() throws JspException{ //现在可以就用doTag()  simpleTagSupport  //不能抛IOException
        JspWriter out=pageContext.getOut();
        //try{
            out.println(xxxx);
        //}catch(...){}
    }
}

//TagHandler
public class ResetTag extends TagSupport{
    public void getColor(){
    }
    public void setColor(){
    }

    public int doEndTag() throws JspException{
        NumberGuessBean numberguessbean=(..)pageContext.get
    }
}

配置文件tld

<tag-lib>
    <uri>.............</uri>  //考试会考    打包后再Jar包里找不到的。。copy一遍扔到jsp
    <tag>
        <short-name>t</short-name>
        <name>time</name>   <!--重要,标签名-->
        <tag-class>a.TimeTag</tag-calss>  <!--重要,标签类-->
        <body-content></body-content>
        <!--重要,定义参数-->
        <attribute>
            <name>color<name>
            <Type>java.lang.String</>
            <required>false</required>
        </attribute>
    </tag>
</tag-lib>

引入且使用

<%@ taglib uri="..." prefix="t"%>
<t:time />

执行顺序:

  • WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象。
  • WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法。
  • 如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。
  • 如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。

doStartTag()方法是遇到标签开始时执行,其合法的返回值是EVAL_BODY_INCLUDESKIP_BODY,前者表示将显示标签间的内容,后者表示不显示标签间的内容;doEndTag()方法是在遇到标签结束时执行,其合法的返回值是EVAL_PAGESKIP_PAGE,前者表示处理完标签后继续执行以下的JSP网页,后者是表示不处理接下来的JSP网页
预定的处理顺序是:doStartTag()返回SKIP_BODY,doAfterBodyTag()返回SKIP_BODY,doEndTag()返回EVAL_PAGE.

doAfterBody()

这个方法是在显示完标签间文字之后呼叫的,其返回值有EVAL_BODY_AGAIN与SKIP_BODY,前者会再显示一次标签间的文字,后者则继续执行标签处理的下一步。

如果继承了TagSupport之后,如果没有改写任何的方法,标签处理的执行顺序是:
doStartTag() ->不显示文字->doEndTag()->执行接下来的网页

HttpSession

HttpSession生命周期:
1.什么时候创建HttpSession
1).对于JSP:
是否浏览器访问服务端的任何一个JSP或Servlet,服务器都会立即创建一个HttpSession对象呢?
不一定。
①. 若当前的JSP或(Servlet)是客户端访问的当前WEB应用的第一个资源,且JSP的page指定的
session属性为false,则服务器就不会为JSP创建一个HttpSession对象;
②.若当前JSP不是客户端访问的当前WEB应用的第一个资源,且其他页面已经创建一个HttpSession对象,
则服务器也不会为当前JSP创建一个新的HttpSession对象,而会把和当前会话关联的那个HttpSession对象返回给当前的JSP页面。
2).page指令的session=”false” 到底表示什么意思:
当前JSP页面禁用session隐含变量!但可以使用其他的显式的对象

3).对于Servlet而言:
若Servlet是客户端访问的第一个WEB应用的资源,则只有调用了request.getSession()或request.getSession(true) 才会创建HttpSession对象

4). 在Servlet中如何获取HttpSession对象?
request.getSession(boolean create):create为false,若没有和当前JSP页面关联的HttpSession对象
则返回null;
若有返回true create为true一定返回一个HTTPSession对象。若没有和昂前JSP页面关联的HttpSession对象,
则服务器创建一个新的HttpSession对象返回,若有,则直接返回关联。

request.getSession()等同于request.getSession(true)

2.什么时候销毁HttpSession对象:
1).直接调用HttpSession的invalidate()方法:使Httpsession失效
2).服务器卸载了当前WEB应用。
3).超出HttpSession的过期时间。
设置HttpSession的过期时间:单位为S

当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个)

request.getSession(true); //如果没有session会创建一个新session
request.getSession(); //如果没有session会创建一个新session

JSP文件在编译成Servlet时将会自动加上这样一条语句 HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的session对象的来历,但如果页面的设置Session=false;是当前页面禁用session隐含的变量,但可以显示的定义其他session变量

关于Servlet和Filter

对于使用传统的部署描述文件 (web.xml) 配置 Servlet 和过滤器的情况,Servlet 3.0 为 <servlet> 和 <filter> 标签增加了 <async-supported> 子标签,该标签的默认取值为 false,要启用异步处理支持,则将其设为 true 即可。以 Servlet 为例,其配置方式如下所示:
<servlet> 
    <servlet-name>DemoServlet</servlet-name> 
    <servlet-class>footmark.servlet.Demo Servlet</servlet-class> 
    <async-supported>true</async-supported> 
</servlet>

Alt text
如果从errorpage过来的会走ERROR
异步请求会async

JSP

九个内置对象

reuqest,response,session,application,pageContext,out,exception,page,config

3个指令

都是%@%形式

1.Page指令

import=”..” //引入包
session=”false” 等价于 request.getSession(false); 如果一个seesion不存在,不会创建它。这个指令会禁用jsp的隐藏session对象。但可以显式定义其他session.
contentType=”text/html;charset=utf-8” 等价于response.setContentType(“”)
pageEncoding=”utf-8”

pageEncoding是jsp文件本身的编码
contentType的charset是指服务器发送给客户端时的内容编码(也就是显示出来的内容的编码)

isELIgnored: 是否支持EL表达式。 默认是false
isErrorPage: 是否创建throwable对象。默认是false;
errorPage: 如果页面中有错误,则跳转到指定的资源。
isThreadSafe 默认true,线程安全下servlet可以并行访问

2. Include指令

<!--动态包含,会编译生成两个servlet,把另一个servlet的结果拿过来用-->
<jsp:include page="/include/header.jsp"></jsp:include>
<!--静态包含,只编译生成1个servlet,拿另一个的jsp代码过来用-->
<%@include file="/include/header.jsp"%>

3.taglib指令

<%@taglib uri="xxx" prefix="xx"%> 引入一个标签库

6个动作

param

传递参数

一般配合include forward之类的使用。servlet可以用request.getParameter获取到

<jsp:param name="xx" value="yy"/>  

forward

jsp本质也是servlet,和reuqest.getRequestDispatcher(“,,”).forward(reuqest,response);一样

<jsp:forward page="...">
    <jsp:param name="p1" value="12"/>
</jsp:forward>

include

jsp本质也是servlet,和reuqest.getRequestDispatcher(“,,”).include(reuqest,response);一样

<jsp:include>
    <jsp:param name="p1" value="12"/>
</jsp:include>

useBean,setProperty,getProperty

这三个指令都是与 JavaBean 相关的指令,其中 useBean 指令用于在 JSP 页面中初始化一个 Java 实例;setProperty 指令用于为 JavaBean 实例的属性设置值;getProperty 指令用于输出 JavaBean 实例的属性。

<jsp:useBean id="beanA" class="com.a.BeanA" scope="session"/> <!--scope可以是 reuqest,session,application,page-->
<jsp:setProperty property="name" name="beanA" value="12"/>
也可url参数传参
<jsp:setProperty property="name" name="beanA" param="age"/>
<%=beanA.getName()%>
<jsp:getProperty property="name" name="beanA"/>

EL表达式

11个内置对象

pageScope, sessionScope, applicationScope, requestScope, pageContext 四大域+一个context
param,paramValues,cookie,header,headerValues, init-param

结构上都是

${....}



${sessionScope.user.sex} //相当于 <%=session.getAttribute("user").getSex()%>
直接使用,符号可以调用get函数 也可以用定位符号[]
${sessionScope.userB["sex"]}
有特殊符号是只能用[]
${sessionScope.userB[data]}  //data是一个变量

EL变量
${username} 这是让他找出某一范围内的名为username的变量
其会按域的从小到大找 page->request->session->applicaiton   也可以直接用xxxScope取出
相当于 <%=xxxScope.getAttribute("username")%>
[]可以从数组中取值(填下标),也可以从map中取值(填key)

EL能够自动类型转换
EL还能算术运算,逻辑运算(字符间也能比较

${ param.password1 = =param.password2 }
Empty 运算符:
<c:if test="${! empty key}">${key}</c:if>

empty运算符规则:
1若key为null时,返回true
2若key为空String时,返回true
3若key为空Array时,返回true
4若key为空Map时,返回true
5若key为空Collection时,返回true
6否则,返回false

EL表达式是在服务端执行的,服务端执行完成后再传给客户端的,js是在客户端执行的,el在js前就被执行了

连接池配置

Tomcat连接池

可以在应用的web.xml也可以在Tomcat的conf/context.xml,也可以在Tomcat的conf/server.xml(GlobalNamingResources标签)中配置,也可以在应用的context.xml中配置。

<Context>
<Resource name="jdbc/mysqlds" 
    auth="Container" //验证方式为容器
    type="javax.sql.DataSource"     //数据源类
    username="root" 
    password="root" 
    maxIdle="30"   //最多维持几个空闲连接 minIdel:最少维持几个空闲连接(即使没有需求)
    maxWait="10000"  //最大等待时间(毫秒) 借出连接的最长期限
    initialSize="20" //初始化时创建多少个连接
    maxActive="100" //最大连接数

    driverClassName="com.mysql.jdbc.Driver" //数据库驱动
    url="jdbc:mysql://127.0.0.1:3306/db_blog" //数据库url地址
    logAbandoned="true" />
</Context>

url 后面还可以?加一些参数 比如serverTimezone=UTC&useSSL=false&useSSL=false

Spring

Aware

aware接口就一个函数 名字叫 XXAware那就一个 setXX(XX obj)

Bean

/*@PostConstruct:在Bean中的某个方法上加上@PostConstruct注解,则该方法将会在Bean初始化之后被Spring容器调用 等同于bean标签init-method属性
@PreDestroy  destroy-method
*/

获取BeanFactory,ApplicationContext的方法

1.Aware  (BeanFactoryAware,ApplicationContextAware接口)都有getBean

代码

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
class AServlet extends HttpServlet{
@Override
public void doGet(HttpServletReuqest request,HttpServletResponse) throws IOException,ServletException{
this.doPost(request,response);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse) throws IOException,ServletException{
PrintWriter writer = response.getWriter();
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
request.getRequestDispatcher("/bs").forward(request,response); //***记得url是在getdispatcher时填的,forward要带两个参
request.getRequestDispatcher("/bs").include(request,response);
response.sendRedirect("/a.jsp");
this.getServletContext();
request.getServletContext();
request.getSession().getServletContext();
this.config.getServletContext();
ServletContext sc=getServletConfig.getServletContext();
config.getInitParameter("p1");
sc.getInitParam("p2"); //注意

request.getParameter("aaa");
request.getParameterValues("aaa"); //string[]
request.getRealPath("/"); //不推荐 use ServletContext.getRealPath(java.lang.String) instead.
request.getProtocol("/");

}
}


@WebServlet(name="BServlet",urlPatterns={"/bse"},init-params={@WebInitParam(name="p1",value="123")} )
@MultipartConfig(localtion="c:\aaa",fileSizeThreshold=0,maxFileSize=102400, maxRequestSize=102400)
/*fileSizeThreshold默认0,多少字节后存到文件系统上,mfs:最大文件大小 mrs:最大请求的multipart form大小*/
class BServlet extends HttpServlet{
@Override
public void doGet(HttpServletReuqest request,HttpServletResponse) throws IOException,ServletException{
this.doPost(request,response);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse) throws IOException,ServletException{
PrintWriter writer = response.getWriter();
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
response.addCookie(new Cookie("akb","111")); //不是set是add
Cookie c1=new Cookie("a","1");
c1.setMaxAge(2000); //秒
response.addCookie(c1);
response.sendError(500);
writer.print(request.getProtocol());
//4个路径
request.getRequestURI();
reuqest.getRequestURL();
request.getContextPath();
request.getServletPath();

request.getDispatcherType(); //FORWARD, INCLUDE, REQUEST, ASYNC, ERROR

long l=this.getLastModified(request);
HttpSession hs= request.getSession();
hs.getID();
hs.setMaxInactiveInterval(1000); //s

//上传
Part part=request.getPart("file"); //寻找指定名称的part
part.write("c:\aa");

}
}

class AFilter implements Filter { //也可以extends HttpServlet
FilterConfig config;
@Override
public void init(FilterConfig c){
this.config=c;
}

@Override
public void destroy(){
}

@Override
public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain){ //注意第三个参数
c.getInitParameter("p1"); //完整的param
c.getServletContext();

chain.doFilter(request,response); //往下传

}
}

@WebFilter(name="BFilter", initParams={@WebInitParam(name="p1",balue="1") }, urlPatterns={"/a/*.css"}, servletName={"AServlet"})
class BFilter implements Filter{
@Override
public void init(FIlterConfig c){}
@Override
public void destroy(){}
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain ){
request.getRequestDispatch("/login").forward(request,response);
Cookie c=new Cookie("c1","1");
c.setDomain(".kk.com"); //必须.开头
c.setPath("/");
chain.doFilter(request,response);
}
}



/*
<form action="/HelloWorld/UpLoad" method="post" enctype="multipart/form-data">//注意
<input type="file" name="file">
<input type="submit" name="upload" value="上传">
</form>
*/



/*Listener*/ /*Event都是EventObject子类 Listener都是 EventListener 子接口*/
//监听三大域的初始化和销毁
@WebListener
public class A implements ServletContextListener{
@Override
public void contextInitializated(ServletConetxtEvent s){ //注意名字
s.getServletContext();
}
@Override
public void contextDestroyed(ServletContextEvent s)
}
@WebListener
public class B implements HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent session){
session.getSession();
}
@Override
public void sessionDestroyed(HttpSessionEvent session){}
}
@WebListener
public class C implements ServletRequestListener{ //名字不是http
@Override
public void requestInitializated(ServletRequestEvent s){
s.getServletContext();
s.getServletRequest(); //httprequest是其子接口
}
@Override
public void sessionDestroyed(ServletRequestEvent s){}
}
//监听三大域的属性变更
@WebListener
public class D implements SerlvetContextAttributeListener{
@Override
public void attributeAdded(ServletAttributeEvent e){
e.getName();
e.getValue();
}
@Override
public void attributeRemoved(ServletAttributeEvent e){}
@Override
public void attributeReplaced(ServletAttributeEvent e){}
}
public class implements HttpSessionAttributeListener{
@Override
public void attributeAdded(HttpSeesionBindingEvent e){ //注意事件名
e.getSession(); //HttpSession
e.getName();
e.getValue();
}
@Override
public void attributeRemoved(HttpSeesionBindingEvent e){
}
@Override
public void attributeReplaced(HttpSeesionBindingEvent e){}
}
public class implements ServletRequestAttriuteListener{
@Override
public void attributeAdded(ServletRequestAttributeEvent e){ //注意事件名
e.getName();
e.getValue();
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent e){
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent e){}
}
//session的属性绑定与
public class implements HttpSessionBindingListener{
public void valueBound(HttpSessionBindingEvent event){} //属性绑定
public void valueUnbound(HttpSessionBindingEvent event) //属性解绑
}
public class implements HttpSessionActivativationListener{
public void sessionDidActivate(HttpSessionEvent se); //会话激活后
public void sessionWillPassivate(HttpSessionEvent se) //会话将失效
} //**


/*执行顺序:
+ WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象。
+ WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法。
+ 如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。
+ 如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。*/
/*doStartTag()方法是遇到标签开始时执行,其合法的返回值是EVAL_BODY_INCLUDE与SKIP_BODY,前者表示将显示标签间的内容,后者表示不显示标签间的内容;
doEndTag()方法是在遇到标签结束时执行,其合法的返回值是EVAL_PAGE与SKIP_PAGE,前者表示处理完标签后继续执行以下的JSP网页,后者是表示不处理接下来的JSP网页*/
public class TagA extends TagSupport{
String n="";
public String getN(){return n;}
public void setN(String n){
this.n=n;
}

@Override
public int doStartTag() throws JspException{ //注意抛的异常
this.pageContext.getServletContext(); //pageContext是TagSupport的属性,可以直接用
return Tag.EVAL_BODY_INCLUDE; //不跳过body
}
@Override
public int doAfterBody() throw JspException{

return Tag.SKIP_BODY;
}
@Override
public int doEndTag() throws JspException{
return Tag.EVAL_PAGE; //不跳过剩下的页面
}
}



public class TagB extends SimpleTagSupport{
String account="";
String passwd="";
public void setAccount(String a){this.account=a;}
public void setPasswd(String p){this.passwd=p;}
public String setAccount(String a){return account;}
public String setPasswd(String p){return passwd;}
@Override
public void doTag() throws JspException{
PageContext pc=(PageContext)this.getJspContext; //重要,获取pageContext的方式
JspWriter out=pc.getOut();
pc.getRequest();
pc.getResponse();
pc.getSession();
pc.getServletContext();
pc.getServletConfig();
pc.forward("url");
pc.include("/aaa",true); //第二个参数flush
pc.setAttribute("a",pc,PageContext.SESSION_SCOPE); //第三个参数可选。在哪个域中写入属性。session,application,request,不写的话是在pagecontext
pc.release();
}
}

/*struts 1*/
public class Action1 extends Action{
@Override
public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request, HttpServletResponse response){
form.getServlet() //ActionServlet
return mapping.findForward("success");
}
}

public class Action2 extends DispatchAction{
public ActionForward add(ActionMapping mapping,ActionForm form, HttpServletRequest request, HttpServletResponse response){
return null;
}
public ActionForward delete(ActionMapping mapping,ActionForm form, HttpServletRequest request, HttpServletResponse response){
return null;
}
public ActionForward find(ActionMapping mapping,ActionForm form, HttpServletRequest request, HttpServletResponse response){
return null;
}
}
public class Action3 extends MappingDispatchAction{
public ActionForward add(ActionMapping mapping,ActionForm form, HttpServletRequest request, HttpServletResponse response){
return null;
}
public ActionForward delete(ActionMapping mapping,ActionForm form, HttpServletRequest request, HttpServletResponse response){
return null;
}
public ActionForward find(ActionMapping mapping,ActionForm form, HttpServletRequest request, HttpServletResponse response){
return null;
}
}


@Controller
public class MyController{
@RequestMapping("/calc/add")
public String add(@RequestParam(value="v1")String v1, @RequestParam(value="v2") String v2){
}
@RequestMapping("/calc/substract")
public String substract(@RequestParam(value="v1") String v1,@RequestParam(value="v2") String v2){
}
}

@Controller
@RequestMapping("/calc")
public class MyController2{
@Value("${account}")
int account;

@RequestMapping("/add",method=RequestMethod.GET)
public ModelAndView add(@RequestParam(value="v1")String v1, @RequestParam(value="v2") String v2){
ModelAndView modelAndView =new ModelAndView();
modelAndView.setViewName("视图名");
modelAndView.addObject("属性名",new Object());
return modelAndView;
}
@PostMapping("/substract") //相当于 @RequestMapping("/subtract",RequestMethod.POST)
public String substract(@RequestParam(value="v1") String v1,@RequestParam(value="v2") String v2){
}
}

@Bean
@Scope(value="singleton") //prototype application request session page
public CacheManager{
@Autowired(required=false)@Qualifier("bb")
BeanA ba;
@Resource("bb")
BeanB bb;
}

@Controller
class studentManagement{
@RequestMapping("/{stuid}/modify")
public String modify(@PathVariable("stuid")String stuid){
}
}

@Configuration
@ComponentScan(value="com.xx.aa", useDefaultFilter= true, basePackageClass=HelloController.class) /*扫描指定包+某个类所在的包*/
@ComponentScan(basePackages={"com.sad.xx","com.aa.fc"}) /*扫描多个包*/

@ComponentScan(value = "com.xhx.spring",
useDefaultFilters = false,
includeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {HelloController.class}) /*按类型扫描*/
}
)
@ComponentScan(value = "com.xhx.spring",
useDefaultFilters = false,
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}) /*扫描带注解的*/
}
)


public class MyConfig{

}


/*
HttpSession
getCreateTime() 返回距离1970,1 的时间 毫秒
getLastAccessedTime() 返回上一次客户端的请求与这session有关的时间
getMaxInactivative() 保留会话的最大非活动时间
isNew()

ServletRequest
doDelete() doPut() doGet() doTrace() doOptions()
getLastModified() 距离1970,1的毫秒级时间 HttpServletRequest 对象变动的时间

HttpServletRequest
changeSessionId() 改变成一个新ID
getContextPath() 请求的URI部分
getCookies() cookies[]
getDateHeader(String name) //long
getHeader(String name)
getHeaders(String name) 迭代器
getMethod()
isUserInRole(String role)
isRequestedSessionIdFromURL()
isRequestedSessionIdFromCookie()
getSession(false);

HttpServletResponse
setStatus(int sc); //返回代码
set/getHeader()
sendRedirect();
addCookie();

Cookie

*/


/*javaBean 的属性 :simple,indexed, bound, constrained*/


/*Action接口常量 : success error login input none*/

Xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/*部署app在tomcat*/
<Host>
</Host>

<!--部署-->
<Host name="localhost" appBase="webapps">
<Context path="/a" docBase="/s/f"/>
<Context path="/b" docBase="/s/b"/>
<Context path="" docBase="/u/a"/>
...
</Host>

<!--web.xml-->
<context-param>
<param-name>p2</param-name>
<param-value>123</param-value>
</context-param>

<web-app>
<servlet>
<servlet-name>AServlet</servlet-name>
<servlet-class>com.a.AServlet</servlet-class>
<init-param>
<param-name>p1</param-name>
<param-value>123</param-value>
</init-param>
</servlet>


<serlvet-mapping>
<servlet-name>AServlet</servlet-mapping>
<url-pattern>/hello</url-pattern>
</servlet-mapping>


<fliter>
<fliter-name>AFilter</filter-name>
<fliter-class>com.a.AFilter</fliter-class>
<init-param>
<param-name>f1</param-name>
<param-value>v1</param-value>
</init-param>
</filter>

<fliter-mapping>
<filter-nmae>f1</filter-name>
<url-pattern>/a/*</url-pattern>
</filter-mapping>
</web-app>





ta.tld
<taglib...>
<description>d</description>
<short-name>aaa</short-name> <!--前缀-->
<uri>http://java.xx.aaa/aa/core</uri> <!--等下引入会用到-->

<!--下面是各种标签的定义-->
<tag>
<name>hello</name>
<tag-class>com.akb.TagB</tag-calss>
<body-content><body-content>

<!--属性定义-->
<attribute>
<name>account</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>passwd</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>

<tag>
<name>tagb</name>
<tag-calss>com.a.TagA</tag-calss>
<body-content></body-content>
<attribute>
<name>n</name>
<required>false</required>
</attribute>
</tag>
</taglib>


引入
<%@ page taglib uri="http://java.xx.aaa/aa/core" prefix="aaa">
使用
<aaa:hello account="4442ss" passwd="123"/>
<aaa:tagb n="111" />



JSP2.0更简便的办法
创建tag文件 在/WEB-INF/tags下
time.tag
<%@ tag import="java.util.*" import="java.text.*" %> <!--在这里引入需要的包-->
<%
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
Date d = new Date(System.currentTimeMillis());
out.println(df.format(d));
%>

repeater.tag

<%@ attribute name="count" type="java.lang.Integer" required="true" %>

<%@ attribute name="value" type="java.lang.String" required="true" %>

<%!
private String repeater(Integer count, String s) {

int n = count.intValue();
StringBuffer sb = new StringBuffer();

for (int i = 0; i < n; i++) {
sb.append(s);
}

return sb.toString();
}
%>

<%
out.println(repeater(count, value));


使用
<%@ taglib prefix="util" tagdir="/WEB-INF/tags" %> <!--直接用tagdir指定文件夹-->
<util:repeater count='${3 * 10}' value='zzz'/>




/*Struts1 配置*/
<web-app>
<servlet>
<servlet-name>struts1</servlet-name>
<serlvet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-name>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>struts1</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>




<!--struts-config.xml-->
<global-forwards> </global-forwards>
<action-mappings>
<action
path="/login.do"
name="LoginForm",
type="com.a.Action1" //注意是type
>
<forward name="sucess" path="/success.jsp" />
</action>

<action path="/data" type="com.a.Action2" parameter="method">
<!--省略forward-->
</action>


<action path="/adddata" type="com.a.Action3" parameter="add"/>
<action path="/deletedata" type="com.a.Action3" parameter="delete"/>
<action path="/finddata" type="com.a.Action3" parameter="find"/>
</action-mappings>

<!--JSP 9大对象 request response session application pageContext config page exception out -->
<!--EL 11个内置对象 pageScope requestScope sessionScope applicationScope pageContext 4大域+一个context
param paramValues cookie header headerValues init-param-->


<!--a.jsp-->
<!--非jsp的知识点。不过在html中可以这么写来设置请求头-->
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">



<!--3大指令-->
<%@ page import="java.io.*","java.util.*","java.awt.*" %>
<%@ page isELIngnore="false" %>
<%@ page session="true" %>
<%@ page error="error.jsp" %>
<%@ page isErrorPage="false" %>
<%@ page contentType="text/html;charset=utf-8" pageEncoding="utf-8" %>

<%@ include page="/sss.jsp" %>
<%@ taglib uri="xcasdfdasf" prefix="xxx" %>

<!--6大动作-->
<jsp:include file="/include/h.jsp">
<jsp:param name="p1" value="123"/>
</jsp:include>

<jsp:param name="pname" value="pvalue"/>

<jsp:forward file="/include/h2.jsp">
<jsp:param name="p2" value="234"/>
</jsp:forward>

<jsp:useBean id="b1" class="com.a.BeanA" scope="session"/>
<jsp:setProperty name="b1" property="age" value="123"/>
<jsp:setProperty name="b1" property="age" param="age"/>
<jsp:getProperty name="b1" property="age"/> <!--会输出-->
<%= b1.getAge()%>

${param.username} <!--获取参数-->
${sessionScope.p1} <!--获取session的属性-->
${header.Cache-Control} <!--获取请求头属性-->
${b1.username} <!--获取javaBean属性-->
....



<--Tomcat连接池-->
<Context>
<Resource name="jdbc/mysqlds"
auth="Container" //验证方式为容器
type="javax.sql.DataSource" //数据源类
username="root"
password="root"
maxIdle="30" //最多维持几个空闲连接 minIdel:最少维持几个空闲连接(即使没有需求)
maxWait="10000" //最大等待时间(毫秒) 借出连接的最长期限
initialSize="20" //初始化时创建多少个连接
maxActive="100" //最大连接数

driverClassName="com.mysql.jdbc.Driver" //数据库驱动
url="jdbc:mysql://127.0.0.1:3306/db_blog" //数据库url地址
logAbandoned="true" />
</Context>


<!--spring连接池-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:com/something/jdbc.properties"/>
</bean>
<!----使用配置文件注入的方式--->
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>



<!--spring mvc配置-->
<web-app>
<!--导入spring框架-->
<listener>
<listener-class>org.springframework.web.context.ContentLoaderListener</listener-class> <!--会创建 applicationcontext 是parent-->
</Listener>
<content-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</content-param>

<absolute-ordering />

<!--配置DispatcherServlet-->
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframwork.web.servlet.DispatcherServlet</servlet-class> <!--会创建 applicationcontext-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-start-up>
</servlet>

<servlet-mapping>
<servlet-name>app</servlet-mapping>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>



<!--spring配置-->
<mvc:annotation-driven />
<context:component-scan base-package="com.abc.project.controller" /> <!--扫描包-->
<context:property-placeholder location="classpath:test.property" />

<beans>
<mvc:resource mapping="/js/**" location="/WEB-INF/js/" />
<mvc:resource mapping="/css/**" location="WEB-INF/css/" />


<bean id="t1" class="com.aaa.xx.BeanA">
<constructor-arg type="int" value="111333">
</bean>
<bean id="b2" class="com.aaa.xx.BeanB">
<property name="p1">
<ref bean="anotherExampleBean"/>
</property>
<property name="integerProperty" value="1"/>
</bean>

</beans>

<!--java.lang.* javax.servlet.* javax.severlet.jsp.* 三个是jsp已加载的基本类-->

<!--JSP的翻译过程
<%! %>声明语句,可以声明成员变量,语句块,自定义方法, 翻译方法:转换成servlet的成员属性或者成员方法的声明
<% %>脚本段,不能声明,定义静态语句块,方法 原封不动地成为servlet的一部分

-->

<!--
<package name="demo1" extends="struts-default" namespace="/">
<action name="*_*" class="com.xxx.{1}" method="{2}" >
<result name="hello">/jsps/aaa/jsp</result>
</action>
</package>
-->
-------------End of this passage-------------