在前面的登錄案例中,登錄失敗后為了能夠響應登錄的錯誤信息。我特意創建了一個LoginErrorServlet用來動態地拼接錯誤信息。
【代碼如下】
arduino復制代碼 //3.給瀏覽器生成響應信息
boolean result = service.login(username,password);
String msg = result ? "用戶登陸成功" : "用戶登陸失敗";
request.setAttribute("msg",msg);
if (result){
//登陸成功
response.sendRedirect("/success.html");
}else {
//登陸失敗
//轉發到處理錯誤的servlet中
request.getRequestDispatcher("/loginErrorServlet").forward(request,response);
}
2. LoginErrorServlet:手動拼接html頁面,動態展示登錄錯誤信息。
scss復制代碼@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//響應給用戶
response.setContentType("text/html;charset=utf-8");
//接收錯誤的信息
String msg = (String) request.getAttribute("msg");
//獲取輸出流
PrintWriter writer = response.getWriter();
//拼接登錄的html頁面
response.getWriter().print("<html>");
response.getWriter().print("<body>");
response.getWriter().print("<form action='loginInterServlet' method='post'>");
response.getWriter().print(" <font style='color: red'>"+msg+"</font><br/>");
response.getWriter().print("用戶名:<input type='text' name='username'/><br/>");
response.getWriter().print("密碼:<input type='password' name='password'/><br/>");
response.getWriter().print("<input type='submit' value='登錄'/>");
response.getWriter().print("</form>");
response.getWriter().print("</body>");
response.getWriter().print("</html>");
}
說明:上述雖然能夠達到我的需求。但是他有以下兩個缺點:
問題:思考既然以前在servlet有上述缺點,為什么還要使用拼接呢?
因為如果我們想在html頁面顯示錯誤的信息,我們只能采用這種方式,html頁面不能夠書寫java代碼。而我們既不采用上述拼接標簽的方式,還想實現簡單的效果。我們可以使用jsp技術,在jsp中可以書寫java代碼同時還可以書寫html標簽。這樣 就能夠使用jsp技術在客戶端和服務端直接進行數據交互了。
JSP全名為Java Server Pages,中文名叫java服務器頁面,其本質是一個Servlet ,它是由Sun 公司倡導、許多公司參與一起建立的一種動態網頁 技術標準。其實就是一個既能書寫Servlet代碼又能書寫HTML代碼的文件。
sql復制代碼在web目錄下,新建一個jsp文件,點擊鼠標右鍵New --- JSP---給這個文件取個名字。
【圖1 創建JSP】
文件內容如下:
javascript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
</body>
</html>
jsp中既可以書寫java代碼,同時還可以書寫html標簽。我們完成練習如何在jsp頁面中書寫java代碼。
【需求】
說明:
1)jsp中的注釋:<%--注釋內容--%>,添加注釋的快捷鍵是:ctrl+/;
2)在jsp中書寫代碼有三種方式,我們這里先介紹一種,格式:
<%java代碼%>
【參考代碼】demo01.jsp
arduino復制代碼<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %><%--
Created by IntelliJ IDEA.
Date: 2018-01-09
Time: 19:15
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
jsp中的注釋
【需求】
1. 在jsp頁面上獲取當前日期,并將其格式化成字符串"yyyy-MM-dd HH:mm:ss";
2. 將這個字符串展示在瀏覽器上;
--%>
<%
//獲取當前系統時間
Date d = new Date();
//創建日期格式化解析器對象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//使用日期格式化解析器對象調用方法格式化日期對象d
String s_date = sdf.format(d);
//控制臺輸出
System.out.println("s_date = " + s_date);
//將這個字符串展示在瀏覽器上
response.getWriter().print(s_date);
%>
</body>
</html>
【運行結果】啟動tomcat,并且訪問這個jsp頁面。
在瀏覽器看到 format格式的日期:
【控制臺輸出】
ini復制代碼s_date = 2018-01-09 19:28:22
通過上面的jsp初體驗, 我們看到jsp中既可以編寫java代碼也可以直接編寫html代碼,相對servlet更加方便.并且我們通過瀏覽器訪問到的jsp頁面,最后在瀏覽器中看到了響應到瀏覽器中的結果。那么整個過程的執行流程是怎樣的呢,我們可以參考如下圖:
通過上面的執行流程,我們可以找到jsp生成的.java源文件,這樣就可以知道jsp的真正原理,同時可以看下jsp為什么是servlet。
如何查看生成的.java源文件呢?
我們可以到tomcat中查看一下上面案例中的jsp頁面是怎么樣的一種存在。IDEA借助tomcat發布web項目的機制:動態發布(為每一個web項目創建一個單獨的發布文件)。我們可以通過tomcat其中日志中的CATALINA_BASE路徑找到我們當前這個JSP頁面在tomcat中的位置:
【圖1 IDEA發布項目的路徑】
找到這個目錄后,會看到以下3個文件夾:
【圖2 文件目錄】
我們打開C:\Users\admin.IntelliJIdea2017.3\system\tomcat\Tomcat_8_5_311_day05目錄發現有兩個文件:
【圖3 JSP被翻譯后的代碼】
打開demo01_jsp.java文件后,代碼如下所示:
我們可以看到當前的jsp文件被翻譯成了一個類,這個類繼承HttpJspBase類,那么這個HttpJspBase類又是什么?
注意:jsp的翻譯由服務器完成,HttpJspBase類一定也是tomcat服務器的內容,所以我們需要找到org.apache.jasper.runtime.HttpJspBase這個類,這個類可以到tomcat的安裝目錄下的lib文件夾下找到jasper.jar,將其解壓,找如下目錄:org\apache\jasper\runtime,找到HttpJspBase.class。
使用反編譯工具打開,如下所示:
通過觀察源碼,根據我們所學習的繼承關系,我們發現JSP其實底層就是一個servlet。通過觀察源碼,我們發現我們剛剛編寫的所有代碼都在該Servlet里面的service方法內部。
swift復制代碼public final class demo01_jsp extends org.apache.jasper.runtime.HttpJspBase {
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write('\r');
out.write('\n');
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>Title</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write(" ");
out.write("\r\n");
out.write(" ");
//獲取當前系統時間
Date d = new Date();
//創建日期格式化解析器對象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//使用日期格式化解析器對象調用方法格式化日期對象d
String s_date = sdf.format(d);
//控制臺輸出
System.out.println("s_date = " + s_date);
//將這個字符串展示在瀏覽器上
response.getWriter().print(s_date);
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
。。。。
}
}
總結:
1.<% %>中書寫的代碼被直接解析成java代碼;
2.jsp之所以可以編寫html代碼,其實本質上也是類似我們使用Servlet直接輸出的。也就是說底層還是像我們之前做法一樣進行標簽拼接。html部分都被out.write("")方法以字符串的形式拼接,然后響應給瀏覽器;
3.在這個java文件中有個_jspService,這個方法有兩個參數request,response;
4.由于我們自己編寫的代碼全部都落入到了service方法內部一開始就已經聲明了request,response,session,application(ServletContext)等對象了,這些對象成為之jsp內置對象。
在JSP頁面的body標簽中,可以直接書寫html代碼和JS代碼。但是,如果在JSP頁面中書寫java代碼。必須遵循固定的格式,才能夠生效;JSP頁面中書寫java代碼有三種方式:1.腳本片段;2.腳本聲明;3.腳本表達式;
腳本片段指的是一段java代碼。書寫格式:<% java 代碼 %>
【示例】 demo02.jsp
javascript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
//書寫java代碼,向瀏覽器輸出數據
response.getWriter().println("hello jsp");
%>
</body>
</html>
【被翻譯后的源碼】
swift復制代碼 out.write("\r\n");
out.write(" ");
response.getWriter().println("hello jsp");
out.write("\r\n");
【頁面結果】:
erlang復制代碼腳本片段雖然可以嵌入java代碼,但是如果,我們要給當前的jsp中定義一些成員方法或者成員變量,就需要一個新的技術——腳本聲明.
說明:通過查看jsp的源代碼我們發現,腳本片段的代碼都會存在service方法中,而方法中是不可以定義一個方法的。
腳本聲明的格式:<%! 書寫Java代碼 %>
【示例一】聲明成員變量 demo03.jsp
javascript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%!
int num = 10;
public void method(){}
%>
</body>
</html>
【被翻譯后的代碼】成員變量
雖然腳本聲明和腳本片段已經可以書寫Java代碼了,但是如果我們要使用java代碼向頁面輸出一些內容,還是需要 使用原來的response對象,比較繁瑣,因此,我們需要一個更加簡便的方式,可以代替response向頁面輸出內容 ——這個就是腳本表達式。
腳本表達式的格式:<%= 向瀏覽器輸出的內容 %> 等價于:out.print( 向瀏覽器輸出的內容)
【示例】在頁面輸出信息
bash復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%="我愛摸魚"%>
<%="上海程序員摸魚"%>
<%
response.getWriter().print("response");
%>
</body>
</html>
注意:
上面代碼中,我們書寫代碼的順序是先:
arduino復制代碼<%="我愛摸魚"%>
<%="上海程序員摸魚"%>
再:
vbscript復制代碼response.getWriter().print("response");
可是瀏覽器查看數據的結果是
vbscript復制代碼response 我愛摸魚 上海程序員摸魚
原因:response.getWriter()獲取的輸出流是:PrintWriter。而腳本表達式<%=%> 等價于:out.print( 向瀏覽器輸出的內容).并且這種方式獲取的輸出流是:JspWriter。其實導致上述輸出結果前后順序就是PrintWriter和JspWriter。
JspWriter:將輸出的內容先放到jsp內置的緩沖區中,然后再刷新輸出。
PrintWriter:是不使用jsp內置的緩沖區,直接將內容寫到網頁中。
總結:
1.不要同時使用腳本表達式和response同時往頁面輸出信息,會出現順序不一致。現象:response會出現在最前面。使用一種輸出即可。
2.腳本表達式<%= str %> :在頁面輸出內容,在service方法中起作用;
3.腳本片段<% %> :在service方法中,原樣輸出的代碼片段;屬于局部為,放在_jspService方法中
4.腳本聲明:<%! String str = "程序員" %> :定義成員變量;
JSP指令(directive)是為JSP引擎而設計的,它們并不直接產生任何可見輸出效果,而只是告訴引擎如何處理JSP頁面中的其余部分。
指令用來聲明JSP頁面的一些屬性,比如編碼方式,文檔類型。我們在servlet中也會聲明我們使用的編碼方式和響應的文檔類型的,而JSP就是用指令來聲明的。
css復制代碼a) page:頁面
<%@page contentType="text/html;charset=utf-8" %>
說明:聲明jsp頁面的編碼方式
b) taglib:引入標簽庫
c) include:包含
swift復制代碼<%@指令名 屬性名="屬性值"%>
【作用】
復制代碼用于在JSP頁面中導入JSTL標簽庫;
【格式】
ini復制代碼<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
說明:表示引入外部的jstl標簽庫的。
prefix="c" 表示前綴
uri="http://java.sun.com/jsp/jstl/core" 表示jstl標簽庫的地址
【作用】
復制代碼在一個JSP頁面中靜態包含另外一個JSP頁面;
【格式】
ini復制代碼<%@include file="URL" %> 指定要導入頁面的地址
【使用示例】
需求:課后的原型中的頁面放到web文件夾下面。然后打開主頁index.jsp.在主頁中引入header.jsp頁面。
xml復制代碼<!--引入頭部-->
<div id="header">
<%@include file="header.jsp"%>
</div>
【效果】
三大指令是什么?分別的作用是?
page是jsp中必須使用的一個指令,用于設置JSP上各種頁面的屬性,告訴tomcat如何將一個JSP翻譯成Servlet
css復制代碼<%@page 屬性名="屬性值" %>
可以放在JSP中任何位置,一般建議放在頁面的最頂部
ini復制代碼language="java" 當前頁面使用的語言,不寫默認是java
import="java.util.*" 導入java.util下所有類,導包
方式一: 每個page指令導入一個類
less復制代碼<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.util.Date"%>
方式二: 一個page指令的import屬性導入所有的包,包之間使用逗號分隔
ini復制代碼<%@page import="java.util.Date,java.text.SimpleDateFormat"%>
作用:相當于導包
【代碼演示】
ini復制代碼<%--<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.ArrayList" %>--%>
<%@ page import="java.util.*,java.text.SimpleDateFormat" %>
<%--
Created by IntelliJ IDEA.
Date: 2018-10-10
Time: 14:59
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
//創建日期對象
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
ArrayList<String> list = new ArrayList<>();
%>
</body>
</html>
ini復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java"%>
【作用】設置響應編碼
vbscript復制代碼response.setContentType("text/html;charset=UTF-8");
ini復制代碼1、errorPage="錯誤頁面的URL":
用于指定如果當前頁面出錯,轉發到哪個頁面去:<%@ page language="java" errorPage="error.jsp"%>
2、isErrorPage="false":默認是false,指定true表示是錯誤頁面
當前這個頁面是否是一個錯誤頁面,錯誤頁面可以多使用一個內置對象。exception:<%@ page isErrorPage="true"%>
1、通過page指令的errorPage屬性指定:如果頁面出錯,轉發到error.jsp這個頁面
ini復制代碼<%@ page errorPage="error.jsp"%>
代碼演示:
typescript復制代碼<%--跳轉到錯誤頁面--%>
<%@page errorPage="../error.jsp" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int i = 1 / 0;
%>
hello world
</body>
</html>
typescript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--聲明是錯誤頁面--%>
<%@page isErrorPage="true" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>錯誤頁面</h2>
<%=exception.getMessage()%>
</body>
</html>
頁面效果:
2、通過web.xml文件指定錯誤碼:響應狀態碼為404則跳轉到404.jsp頁面
如果不指定,那么按照以前報錯方式,會出現如下錯誤頁面:
我們可以在web.xml進行配置跳轉到更加好看一些的頁面。
xml復制代碼<!-- 指定錯誤頁面 -->
<error-page>
<!-- 指定錯誤碼 -->
<error-code>404</error-code>
<!-- 出錯以后跳轉到哪個頁面 -->
<location>/404.jsp</location>
</error-page>
404.jsp頁面代碼:
javascript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<img src="/404.jpg"/>
</body>
</html>
3、通過web.xml文件指定錯誤類型:發生空指針,則跳轉到null.jsp頁面
xml復制代碼<!-- 指定錯誤的類型 -->
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/null.jsp</location>
</error-page>
demo02.jsp
javascript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
String s = null;
s.length();
%>
</body>
</html>
報空指針異常后的頁面:null.jsp
javascript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>發生空指針異常了</h2>
</body>
</html>
瀏覽器效果:
屬性名 | 作用 | |
language="java" | 指定JSP頁面使用語言 | |
**import="{package.class | package.*}"** | 導入包: 1. 每個import包入一個包 2. 一個import導入多個包,使用逗號分隔 |
errorPage="relative_url" | 當前頁面出錯,轉發到哪個錯誤頁面 | |
**isErrorPage="true | false"** | 當前是否是一個錯誤頁面 |
contentType="mimeType [ ;charset=characterSet ]" | 指定頁面類型和編碼,不指定會有亂碼 | |
**isELIgnored="true | false"** | 是否忽略EL表達式,true表示EL不起作用 |
javascript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="true"%>
<html>
<head>
<title>Title</title>
</head>
<body>
${3*5}
</body>
</html>
JSP動作標簽利用XML語法格式的標記來控制Servlet引擎的行為 。利用JSP動作標簽可以動態包含其他jsp頁面、把用戶跳轉到另外的頁面、為Java插件生成HTML代碼。
JSP頁面動作標簽很多,常用的主要有以下3種:
makefile復制代碼<jsp:include/>:動態包含
<jsp:forward/>:跳轉 類似之前學習的轉發技術
<jsp:param/>:參數設置
【作用】
復制代碼用于一個JSP頁面動態包含另一個JSP頁面
【語法】
ini復制代碼<jsp:include page="URL"/> URL是被包含的JSP頁面
【使用示例】
a.jsp
javascript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>我是A頁面</h1>
<%int m1=10; %>
<!-- 靜態包含: -->
<%@include file="b.jsp" %>
<!-- 動態包含 -->
<%-- <jsp:include page="b.jsp"/> --%>
</body>
</html>
b.jsp
javascript復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>我是B頁面</h2>
<%int m=20; %>
</body>
</html>
【動態包含和靜態包含】
靜態包含include指令 | 動態包含include動作 | |
語法格式 | <%@include file="URL"%> | <jsp:include page="URL"/> |
包含的方式 | 靜態包含包含的是頁面的內容。如果A包含B,則先將B的頁面內容復制到A頁面中,再運行A頁面。 B頁面中不能出現與A頁面同名的變量 | 動態包含包含的是頁面的執行結果,如果A包含B,則先將B執行,再將B執行的結果包含到A頁面中,執行A頁面。 B頁面中可以出現與A頁面中同名的變量 |
生成Servlet個數 | 只能生成了一個Servlet | 生成了兩個Servlet |
說明:
如果只是引入jsp,不需要改變,那么使用靜態引入。如果引入的jsp頁面是變化的,那么使用動態引入。
用于頁面的轉發,與request.getRequestDispatcher("/URL").foward(request,response);功能一樣的
ini復制代碼<jsp:forward page="URL"/> 轉發
用于給<jsp:forward>和<jsp:include>提供參數
ini復制代碼<jsp:param value="張三" name="user"/>
ini復制代碼<jsp:forward page="/頁面地址"/>
javascript復制代碼<%--
Created by IntelliJ IDEA.
Date: 2018-10-10
Time: 16:41
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>c頁面</h2>
<%
//解決中文亂碼問題 <jsp:param name="username" value="張三"/> 是在d.jsp后面攜帶數據跳轉到d.jsp頁面的,通過瀏覽器的,需要先按照UTF-8編碼之后在進行傳遞。然后在d.jsp頁面使用request.getParameter("username")獲取數據
request.setCharacterEncoding("UTF-8");
//向域對象request中存儲數據
request.setAttribute("age",19);
%>
<%--轉發動作,攜帶的參數,可以在d.jsp上接收這參數,通過瀏覽器轉發過去的,所以要想獲取param攜帶的數據必須使用getParameter()方法獲取數據--%>
<jsp:forward page="d.jsp">
<jsp:param name="username" value="張三"/>
</jsp:forward>
</body>
</html>
d.jsp頁面:
javascript復制代碼<%--
Created by IntelliJ IDEA.
Date: 2018-10-10
Time: 16:41
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>d頁面</h2>
<%--獲取request域對象中的數據--%>
<%=request.getAttribute("age")%>
<%--獲取轉發param標簽通過瀏覽器攜帶的數據--%>
<%=request.getParameter("username")%>
</body>
</html>
我們發現,我們在JSP頁面中書寫的代碼最終都會翻譯到_jspService()方法中,我們發現這個方法中有兩個形參:HttpServletRequest對象 ,HttpServletResponse對象 。所以說,JSP的本質就是一個Servlet。我們可以直接在JSP頁面上使用這兩個對象。
改造登錄后的頁面,用戶登陸失敗以后,跳轉到login.jsp,在jsp頁面中動態顯示用戶登陸錯誤中的信息。
【思路】
【LoginServlet代碼】
說明:LoginServlet中,登錄失敗之后,直接轉發到login.jsp頁面。
ini復制代碼protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解決中文亂碼問題
request.setCharacterEncoding("utf-8");
//獲取用戶名和密碼
String username = request.getParameter("username");
String password = request.getParameter("password");
UserServiceInter service = new UserServiceInterImpl();
boolean result = service.login(username,password);
String msg = result ? "用戶登陸成功" : "用戶登陸失敗";
request.setAttribute("msg",msg);
if (result){
response.sendRedirect("/success.html");
}else {
//轉發到login.jsp頁面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
【login.jsp頁面】
xml復制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>登錄頁面</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/login.css" rel="stylesheet">
<script src="js/jquery.js"></script>
<script src="js/bootstrap.js"></script>
</head>
<body>
<%
String msg = (String) request.getAttribute("msg");
%>
<div class="container text-center">
<form class="form-signin" action="/loginInterServlet" method="get">
<h2 class="form-signin-heading">登錄頁面</h2>
<font color="red"><%=msg%></font>
<input type="text" name="username" class="form-control" placeholder="用戶名" required autofocus>
<input type="password" name="password" class="form-control" placeholder="密碼" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">登錄</button>
</form>
</div>
</body>
</html>
說明:上述代碼中:
css復制代碼<font color="red"><%=msg%></font>
能夠使用msg獲取數據,因為編譯之后存在于同一個類中,編譯jsp如下所示:
效果圖:瀏覽器訪問login.html頁面
登錄密碼輸入錯誤:
小結:
壓圖片
徹底解決亂碼
1.1 @ResponseBody 注解亂碼
這種亂碼是由于JSON字符串和對象進行序列號和反序列化的時候用出現的問題,String轉換的時候默認用的編碼是ISO-8859-1。
解決辦法1: 在 @RequestMapping 請求映射的注解中屬性 produces="text/html;charset=UTF-8"
解決辦法2: 一勞永逸的辦法 在spring配置中配置下
<mvc:annotation-driven >
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
解決辦法3: 如果還不能解決GET出現的亂碼,就在JSP頁面添加配置:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
1.2 數據庫亂碼
創建數據庫的時候,一般都會選擇 UTF-8的字符編碼方式來創建數據庫。一般不會出現來亂碼問題,但是在配置 jdbc的時候,不注意沒有添加上配置,也可能出現亂碼:
jdbc.url= jdbc:mysql://localhost:3306/testdb?characterEncoding=UTF-8
1.3 control 層編碼格式問題
如果使用:request.setCharacterEncoding("UTF-8");
響應也使用:response.setContentType("application/json;charset=UTF-8");
1.4 IDE默認編碼問題
IDEA默認時UTF-8,eclipse則是GBK
eclipse需要配置下IDE默認編碼: General->Workspace->Text file encoding
1.5 tomcat 出現亂碼情況
tomcat 一般會先亂碼情況,但是tomcat也可以配置,可以預防這種亂碼的可能性。 在conf -> server.xml 中進行配置
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" /> -
1.6 tomcat 如還繼續出現亂碼,繼續處理
這次在啟動腳本中添加 utf-8編碼方案,來徹底解決亂碼問題
windows catalina.bat:
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Dfile.encoding="UTF-8"
linux catalina.sh:
JAVA_OPTS="-Dfile.encoding=UTF-8"
臺PHP頁面(頁面編碼為UTF-8或者已經把字符轉為UTF-8)使用json_encode將PHP中的array數組轉為JSON字符串。例如:
<?php
$testJSON=array('name'=>'中文字符串','value'=>'test');
echo json_encode($testJSON);
?>
查看輸出結果為:
{“name”:”\中\文\字\符\串″,”value”:”test”}
可見即使用UTF8編碼的字符,使用json_encode也出現了中文亂碼。解決辦法是在使用json_encode之前把字符用函數urlencode()處理一下,然后再json_encode,輸出結果的時候在用函數urldecode()轉回來。具體如下:
<?php
$testJSON=array('name'=>'中文字符串','value'=>'test');
//echo json_encode($testJSON);
foreach ( $testJSON as $key => $value ) {
$testJSON[$key] = urlencode ( $value );
}
echo urldecode ( json_encode ( $testJSON ) );
?>
查看輸出結果為:
{“name”:”中文字符串”,”value”:”test”}
到此,成功地輸出了中文字符。隨意使用json_encode吧。這樣子在PHP后臺輸出的JSON字符串在前臺javascript中Ajax接收后eval出來也不會出現中文亂碼,因為js在處理JSON格式數據是也是以UTF8的形式進行的,與PHP類似,故接收PHP頁面的JSON字符串不會出現問題。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。