pageEncoding 和contentType的预设都是 ISO8859-1. 而随便设定了其中一个, 另一个就跟着一样了
平时中文乱码问题设置pageEncoding就可以只是刚好也设置了contentType,实际并不需要关心PageEncoding,设对PageEncoding只是为了IDE能正确编译jsp,而且IDE更会检查你是否设对,需要关心的是:
Content-Type,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件
设置contentType的两种方法:
1.
<%@ page contentType="text/html;charset=utf-8" %>
2.
response.setContentType("text/html;charset=gb2312");
解决中文乱码问题的代码解释:
request.setCharracteEncoding("gb2312”);//设置了服务器解码客户端(浏览器)发过来的请求中的数据用GB2312;
response.setContentType(“text/html;charset=gb2312");
//设置了 客户端(浏览器)用GB2312编码数据发送请求到服务器
(HTTP协议的内容,暂时不知道为什么这样设置conten-type后,表单内容的提交也是用这个编码)
这样一解一编都是gb2312,就不会乱码。
| 我 |
utf-8 | E6 88 |
gb2312 | CE D2 |
iso-8859-1 | %26%2325105%3B |
../page.jsp
当前页面的上一级目录的page.jsp
如何查看jsp转译成servlet后的源代码
tomcat目录\work\Catalina\localhost\项目名\包名
有Tomcat生成的.java和.class文件
jsp程序段:
<%Java 代码%>
jsp程序段中的一种<%!代码 %>声明:
方法,页面全局变量,类 的声明都可以放在jsp声明部分;(可以先使用后声明)
不能在jsp程序段中定义方法。
html:
××××××(html代码,大概就是除了jsp表达式和java代码那些,比较不知道html有哪些奇怪的格式)
等价于
<%out.print(××××××);%>
jsp表达式:
<%=变量/返回值/表达式%>
等价于
<%out.print(msg);%>
JSP表达式的内容一定是字符串类型,或者能通过toString()函数转换成字符串的形式
可以看到jsp表达式和html都可以等价于out.print,所以对于一个jsp页面,把jsp表达式和html都想象成out.print之后,jsp页面就只剩下java代码。这份java代码输出的html就是out.print的内容。
JSP基础
JSP看似比Servlet内容多而且复杂,其实学习JSP时只要关注两件事:
哪些代码是编译时用的,哪些是运行时执行。
各种标签在编译成Servlet代码后变成了什么样。
1.指令<%@
指令是编译期间执行的代码,常用的有:page、include、taglib。语法是<%@page ... %>。
page用法:导入包,jsp输出内容的类型,指定处理异常的错误页面(相当于捕捉页面异常)
include用法:等价于代码复制(所以有可能出现相同变量错误,但编译器不会发现)
2.声明
声明的变量和方法最终编译成Servlet中的成员变量和方法。语法是<%! ... %>。这里的代码
都会生成在service()方法外,所以声明的变量是编译后Servlet的成员变量,而且可以声明方法。
这是声明与后面将要介绍的普通JSP代码的区别。
3.动作 <jsp: 使用xml格式控制服务器的行为
动作是运行期执行的代码。<jsp:include>、<jsp:forward>、<jsp:useBean>等等。<jsp:include>
是动态引入其他文件,如果代码不执行到这里就不会引入,一定要与include指令区分开。
<jsp:forward>与Servlet中的forward方法功能相同,而<jsp:useBean>、<jsp:property>稍后在JSP
转换成的Servlet源文件中会看到它们的真身。
include:与include指令不同的是,include动作只把文件的输出包含进来(所以没有java代码,也就不会出现相同变量的情况)。而且,由于include指令是编译期的,所以进入运行期后就算改变include进来的文件,被include的内容仍然是编译期include进来的文件的内容;而include动作是运行期的,每次页面被请求时都被引入,所以include进来的文件是可以在运行期改变的,改变后重新请求include进来的就是改变后的文件。
forward:相当于不要现有页面内容的include动作,跳转后地址栏仍然是跳转前的地址。forward后其实仍然在当前页面,只是显示的是forward的页面的内容(即跳转没有重新请求,自然request的内容仍然是当前页面的内容(即共享request))
4.JSP代码
编译后会生成到service()方法中,因此在这里声明的变量是局部变量,也就不能在这里声明方法了。
语法是<% ... %>。
表单:
get:把parameter放到URL中
post:把parameter放到请求体(HTTP协议)中,用该请求(重新请求,区别去jsp forward)请求服务器,服务器里的parseParameter()函数解释请求体(获得请求的InputStream())获得parameter后放到parameterMap.
表单GET
我们知道通过URL方式提交数据是很容易产生乱码问题的,所以我们更加倾向于通过表单形式。当用户点击submit提交表单时,浏览器会更加设定的编码来编码数据传递给服务器。通过GET方式提交的数据都是拼接在URL后面(可以当做query String??)来提交的,所以tomcat服务器在进行解码过程中URIEncoding就起到作用了。tomcat服务器会根据设置的URIEncoding来进行解码,如果没有设置则会使用默认的ISO-8859-1来解码。假如我们在页面将编码设置为UTF-8,而URIEncoding设置的不是或者没有设置,那么服务器进行解码时就会产生乱码。这个时候我们一般可以通过new String(request.getParameter("name").getBytes("iso-8859-1"),"utf-8") 的形式来获取正确数据。
表单POST
对于POST方式,它采用的编码也是由页面来决定的即contentType。当我通过点击页面的submit按钮来提交表单时,浏览器首先会根据ontentType的charset编码格式来对POST表单的参数进行编码然后提交给服务器,在服务器端同样也是用contentType中设置的字符集来进行解码(这里与get方式就不同了),这就是通过POST表单提交的参数一般而言都不会出现乱码问题。当然这个字符集编码我们是可以自己设定的:request.setCharacterEncoding(charset) 。
response.sendRedirect(url) 相当于帮客户执行重新请求url的操作
设置cookie的存活时间(cookie只能存字符串):
//设置Cookie的存活期为600秒
cookie.setMaxAge(600); -1
indicating the cookie will persist until browser shutdown.
session的默认存活时间是30分钟。重启后sessionID变了
通过cookie的方式存储信息,可能会存在一点定的安全性,因为所有的信息都是写在客户端的,客户可能会对这些信息进行修改或清除。然后就又出现session的方式用于保存用户行为
-WEB容器默认的是用Cookie机制保存SessionID到客户端,并将此Cookie设置为关闭浏览器失效,Cookie名称为:JSESSIONID
Cookies 与session一个很大的不同是,Cookies不是键值对(不能通过键直接获得(request.getAttritbute("x")),但可以通过手动getname()查找获得。
session失效的两个原因:cookie(sessionID)丢失,或者(存在于服务端的)session丢失
如果两次调用session.setAttribut(String name,Object obj)后面的会覆盖前面的
判断是否第一次访问购物车:
ArrayList books = (ArrayList)session.getAttribute("books");
if(books==null){
books = new ArrayList();
session.setAttribute("books",books);
}
转义字符的使用
for (int i = 0; i < items.length; i++) {
out.println(items[i] + "<a href=\"addToCart.jsp?item="+items[i]
+"\">加入购物车</a><br>");
}
另一种写法
<a href="addToCart.jsp?item=<%=items[i] %>">加入购物车</a><br>
application作为对所有客户端都一样的变量,实际是Servlet的成员属性。通过它可以获得很多服务器的信息,如资源在项目中的路径getRealPath
关于JavaBean规范:
符合JvavBean规范的类的属性名字应该由getter/setter方法中的名字决定,而不是真正的成员变量名字。
<jsp:useBean id="student" class="beans.Student"></jsp:useBean scope = "page|request|session|application">
相当于 Student student=new Student();
scope ----对象的可用范围
- 在servlet中默认情况下,无论你是get还是post 提交过来 都会经过service()方法来处理,然后转向到doGet
-
- 或是doPost方法,我们可以查看HttpServlet 类的service方法: 我在tomcat的lib目录下,解压servlet-api.jar,然后用反编译软件把lib\javax\servlet\http下的HttpServlet.class反编译,看里头的service()方法的原代码:
重写Servlet的destory()方法来执行服务器被用shutdown(并不是stop)关闭后Servlet执行的清理工作来节省资源(如释放数据库连接)。
设置局部变量
<servlet>
<servlet-class>servlets.WelcomeServlet</servlet-class>
<!-- 局部参数 -->
<init-param>
<param-name>driverClassName</param-name>
<param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>
</init-param>
</servlet>
请求传值:
request.getAttribute("msg",msg)//用hashMap实现
过滤器:
定义;比Servlet先一步接过request和response,并进行设置后交还request和response给Servlet,理论上跟在Servlet里执行一样;
过滤器的运行时在服务器运行的时候自动运行
应用场景:在多个Servlet里相同的代码段
在WEB.xml配置处理异常:
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error.jsp</location>