java2ee java web_javaWeb2之Jsp

Java Server Page

放在除WEB-INF(放web项目的隐私文件)外的其他任何目录中。

Java服务器端网页,实现在HTML页面编写Java代码实现动态内容,一种简化Servlet编写的技术(不用在java里拼写html)

本质上是一个Servlet,每个JSP页面在第一次被访问时,JSP引擎会将它翻译成一个Servlet程序(java文件),接着编译为class文件,然后由web容器(Servlet引擎,tomcat)去装载、执行。

workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\项目名\org\apache\jsp\xxx_jsp.java

5272a50decd0d608d0613180d8f37651.png

HttpJspBase看源码知,它继承了HttpServlet!

运行tomcat后,被装载在:

tomcat_home\work\Catalina\localhost\项目名\org\apache\xxx_jsp.java

整个过程在Servlet容器的控制下将请求的JSP资源转变为Servlet之后,同样会经历Servlet的实例化、初始化、就绪、销毁四部分的生命周期。从图中可以看到,之所以第一次请求一个JSP页面会比之后的请求响应慢一些,就是要经过转译成Servlet,编译成class这样一个过程。

df4824b210b52cce211dfccc4fd0d81f.png

JSP页面的隐含对象

没有声明就可以引用的,源码:

public void _jspService(HttpServletRequest request, HttpServletResponse response)

throws java.io.IOException, ServletException {

PageContext pageContext = null;

HttpSession session = null;

ServletContext application = null;

ServletConfig config = null;

JspWriter out = null;

Object page = this;

//...

//使用 编写的代码会出现在此位置. 可以用到 request, response, pageContext, session

//application, config, out, page 这 8 个隐含对象. (实际上还可以使用一个叫 exception 的隐含对象)

}

1.request:HttpServletRequest,属性的作用范围仅限于同一个请求。

2.response:HttpServletResponse,JSP页面里几乎不用。

3.pageContext:PageContext,页面的上下文,可以从该对象中获取其他8个隐含对象和当前页面其他信息(标签),属性作业范围仅限于当前JSP页面。

4.session:HttpSession,代表浏览器和服务器的一次会话(浏览器打开直到关闭即一次会话)

5.application:ServletContext,代表当前Web应用,属性作业范围仅限于当前Web应用。只要在一处设置属性, 在其他各处的 JSP 或 Servlet 中都可以获取到。

6.config:当前JSP对应的Servlet的ServletConfig对象(几乎不用)。若需访问当前JSP配置的初始化参数,需要通过映射地址(url-pattern,如果你给这个jsp文件在web.xml配了的话)。

7.out:JspWriter对象,调用out.print(),直接把字符串打印在浏览器上。

8.page:指向当前JSP对应的Servlet对象的引用(this),但为Object类型,只能调用Object类的方法(几乎不用)。

9.exception:在声明了page指令的isErrorPage="true"时才可用。

pageContext, request, session, application(对属性的作用域的范围从小到大) ,都有这些方法!这四个对象也称之为域对象:

void setAttribute(String name, Object o): 设置属性

Object getAttribute(String name): 获取指定的属性

Enumeration getAttributeNames(): 获取所有的属性的名字组成的 Enumeration 对象

removeAttribute(String name): 移除指定的属性

pageContext, request, session, application 对象

JSP模版元素:

JSP页面中的静态HTML内容称 。

JSP脚本片断(scriptlet)

是指嵌套在之中的一条或多条Java程序代码。 多个脚本片断中的代码可以相互访问。

String ageStr = request.getParameter("age");

Integer age = Integer.parseInt(ageStr);

if(age >= 18){

%>

成人...

}else{

%>

未成人...

}

%>

JSP表达式

提供了将一个 java 变量或表达式的计算结果输出到客户端的简化方式,它将要输出的变量或表达式直接封装在之中。

Date date = new Date();

out.print(date);

%>

JSP 声明

JSP 声明将 Java 代码封装在之中,它里面的方法声明代码将被插入进 Servle t的 _jspService 方法的外面,不然报错!(在 JSP 页面中几乎从不这样使用)。

JSP指令

eclipse新建jsp文件的第一、二行,在目前的JSP 2.0中,定义了page、include 和 taglib这三种指令。

e4864156af8aaeeeeeb4941270361ea2.png

page指令

1861a96aa6f302d2ec098662bcac9194.png

1). page指令用于定义JSP页面的各种属性, 无论page指令出现在JSP页面中的什么地方, 它作用的都是整个JSP页面, 为了保持程序的可读性和遵循良好的编程习惯, page指令最好是放在整个JSP页面的起始位置。

2). page 指令常用的属性:

①. import 属性: 指定当前 JSP 页面对应的 Servlet 需要导入的类。

查看jsp翻译成的servlet文件源码可知,这些包已经导入过:

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

②. session 属性: 取值为 true 或 false, 指定当前页面的 session 隐藏变量是否可用, 也可以说访问当前页面时是否一定要生成 HttpSession对象.

③. errorPage 和 isErrorPage:

errorPage 指定若当前页面出现错误的实际响应页面时什么. 其中 / 表示的是当前 WEB 应用的根目录.

在响应 error.jsp 时, JSP 引擎使用的请求转发的方式!

isErrorPage 指定当前页面是否为错误处理页面, 可以说明当前页面是否可以使用 exception 隐藏变量. 需要注意的是: error.jsp 中,若指定 isErrorPage="true", 并使用 exception 的方法了, 一般不建议能够直接访问该页面。直接访问,exception是null!只能出错情况才让看!

那如何使客户不能直接访问某一个页面呢 ? 对于 Tomcat 服务器而言, WEB-INF 下的文件是不能通过在浏览器中直接输入地址的方式来访问的(直接访问404)。 但通过请求的转发是可以的,所以把通常它们放WEB-INF文件夹里!

还可以在 web.xml 文件中配置错误页面:

404

/WEB-INF/error.jsp

java.lang.ArithmeticException

/WEB-INF/error.jsp

④. contentType: 指定当前 JSP 页面的响应类型. 实际调用的是 response.setContentType("text/html; charset=UTF-8");

通常情况下, 对于 JSP 页面而言其取值均为 text/html; charset=UTF-8. charset 指定返回的页面的字符编码是什么(服务器发送给客户端时的内容编码), 通常取值为 UTF-8。

⑤. pageEncoding: 指定当前 JSP 页面的字符编码(把jsp翻译成utf-8的java代码时的编码),通常情况下该值和 contentType 中的 charset 一致。

pageencoding是规则的遵循者,chartset是规则的制定者

ps:head标签里这里的charset的意思?

2c5a868725be89c10ddaa18a12e4154d.png

⑥. isELIgnored: 指定当前 JSP 页面是否可以使用 EL 表达式. 通常取值为 false,表示不忽略el表达式。

include 指令

1). include 指令用于通知 JSP 引擎在翻译当前 JSP 页面时将其他文件中的内容合并进当前 JSP 页面转换成的 Servlet 源文件中,这种在源文件级别进行引入的方式称之为静态引入, 当前JSP页面与静态引入的页面紧密结合为一个Servlet。

58710239b96bc863b957ef64203697be.png

静态引入:用于通知JSP引擎在翻译当前JSP页面时将其他文件中的内容合并进当前页面转换成的servlet源文件中。最终只有一个.java文件。

查看原文件:

663b095cf4b55aa5e8acd8e0d8c86c13.png

2). file属性的设置值必须使用相对路径

3). 如果以 / 开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件

taglib 指令

JSP注释

区别: JSP 注释可以阻止 Java 代码的执行.。

JSP标签

JSP标签可代替java代码,使JSP文件变得简洁,便于维护和代码复用。

include标签

动态引入: 并不是像 include 指令生成一个 Servlet 源文件, 而是生成两个 Servlet 源文件, 然后通过一个方法的方式把目标页面包含进来:

org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "b.jsp", out, false);

forward标签

相当于.

request.getRequestDispatcher("/include/b.jsp").forward(request, response);

%>

但使用 jsp:forward 可以使用 jsp:param 子标签向 b.jsp 传入一些参数. 同样 jsp:include 也可以使用 jsp:param 子标签.

OR

在 b.jsp 页面可以通过 request.getParameter("username") 获取到传入的请求参数.

9e124100b0dd7c097b928813054663dd.png

自定义JSP标签

926f6f97f4203d2471bf2781f5e04459.png

EL表达式

EL(Expression Language) 是为了使JSP写起来更加简单。用于给jsp标签的属性赋值,也可以直接输出。

表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法,让Jsp的代码更加简化。

1.访问bean的属性

如果该属性没有被赋过值(或是null)或取值时对象绑定名写错,会输出"",而非null。但属性名写错,会报错。

${user.name}

容器会依次从pageContext、request、session、application中查找绑定名为user的对象(getAttribute),找到之后,调用该对象的getName()方法,找不到,输出""。

如果要查指定范围的,可以使用pageScope等xxScope,如${requestScope.user.name}

${user['name']}

等价于上面的。

2.读取请求参数值

${param.username}

等价于 request.getParameter("username");

${paramValues.username}

等价于 request.getParameterValues("username");

jstl(java standard taglib)标签

5a0dec27a202ee07ea88939e145a9f14.png

请求转发与重定向

请求到达容器,容器会创建request和response对象。当响应发送完毕,容器会删除request和response对象,即request和response对象的生存时间是一次请求与响应期间。

重定向

浏览器发送请求访问A,A可以发送状态码302和Location消息头到浏览器,于是浏览器立即向Location发新的请求。重定向之前,容器会清空response对象上存放的数据。一件事情已经做完了,再坐下一件事。

321d0af2adcb3ec57f945a4d5b37eca3.png

response.sendRedirect(path);

特点:

重定向的地址是任意的;

重定向后浏览器地址会变为重定向地址。

转发

浏览器请求访问A,A通知容器去调用B,是一件事情没有做完,调用另一个组件继续做。转发涉及的各个Web组件共享一个request和response对象。

b5f27aa1a1912e53d7d9a246fa4fe603.png

//请求的转发.

//1. 调用 HttpServletRequest 的 getRequestDispatcher() 方法获取 RequestDispatcher 对象

//传入要转发的地址

String path = "testServlet";

RequestDispatcher requestDispatcher = request.getRequestDispatcher("/" + path);

//2.进行请求的转发.

requestDispatcher.forward(request, response);

特点:

发生在服务器端(由容器实现),客户端只发了一个请求,浏览器不知道转发过程,所以地址栏没有变化。

转发的地址必须是同一个web应用内部某个地址。

转发过程里涉及到的web组件共享同一个reqest、response

forward之后的其他语句还是会执行。

本质区别:

请求的转发只发出了一次请求, 而重定向则发出了两次请求.

①. 请求的转发: 地址栏是初次发出请求的地址.

请求的重定向: 地址栏不再是初次发出的请求地址. 地址栏为最后响应的那个地址

②. 请求转发: 在最终的 Servlet 中, request 对象和中转的那个 request 是同一个对象.

请求的重定向: 在最终的 Servlet 中, request 对象和中转的那个 request 不是同一个对象.

③. 请求的转发: 只能转发给当前 WEB 应用的的资源

请求的重定向: 可以重定向到任何资源.

④. 请求的转发: / 代表的是当前 WEB 应用的根目录

请求的重定向: / 代表的是当前 WEB 站点的根目录.

7e1095eca02a262c165d0c1bac2777c1.png

中文乱码问题

jsp编码设置

54f3dccb2cdd368d97dabb5ef2a7eb03.png

1). JSP 页面上有中文, 请求页面展示中文信息时不出现乱码:

保证 contentType="text/html; charset=UTF-8", pageEncoding="UTF-8" charset 和 pageEncoding 的编码一致, 且都支持中文. 通常建议取值为UTF-8。

另外还需保证浏览器的显示的字符编码也和请求的 JSP 页面的编码一致!

2). 通过页面输入框获取中文参数值,再进行展示不出现乱码:

默认参数在传输过程中使用的编码为 ISO-8859-1

①. 对于 POST 请求: POST请求参数在请求体中,只要在获取请求信息之前(在调用 request.getParameter 或者是 request.getReader 等), 调用 request.setCharacterEncoding("UTF-8")。

②. 对于 GET 请求: 前面的方式对于 GET 如果无效。

可以通过先解码后编码的方式:

String val = request.getParameter("username");

String username = new String(val.getBytes("iso-8859-1"), "UTF-8");

out.print(username);

也可以通过修改 Tomcat 的 server.xml 文件的方式,使得前面的方式对于 GET 起效:

参照 http://localhost:8989/docs/config/index.html 文档的 useBodyEncodingForURI 属性,

为 Connector 节点添加 useBodyEncodingForURI="true" 属性,或者添加URIEncoding=utf-8。

本地的和映射到eclipse的server的都改:

e3e6253625ddd847e10298b6d4413352.png

3).浏览器以get方式提交数据时,参数有中文的情况

(RFC3986文档规定)首先url的编码格式采用的是ASCII码,如果url包含中文,客户端浏览器会按照操作系统的字符集进行编码提交到服务器,服务器会按照配置的字符集进行解码,所以如果两者不一致就会导致乱码。解决如下:

encodeURI函数采用UTF-8对URL进行编码。如果只进行一次encodeURI,得到的是UTF-8形式的URL,服务器端通过request.getParameter()解码查询参数(通常是iso-8859-1)就会得到乱码。

如果进行两次encodeURI,第一次编码得到的是UTF-8形式的URL,第二次编码得到的依然是UTF-8形式的URL,但是在效果上相当于首先进行了一次UTF-8编码(此时已经全部转换为ASCII字符),再进行了一次iso-8859-1编码,因为对英文字符来说UTF-8编码和ISO-8859-1编码的效果相同。在服务器端,首先通过request.getParameter()自动进行第一次解码(可能是gb2312,gbk,utf-8,iso-8859-1等字符集,对结果无影响)得到ascii字符,然后再使用UTF-8进行第二次解码,通常使用java.net.URLDecoder("","UTF-8")方法。

两次编码两次解码的过程为:

UTF-8编码->UTF-8(iso-8859-1)编码->iso-8859-1解码->UTF-8解码,编码和解码的过程是对称的,所以不会出现乱码。

参考:https://blog.csdn.net/zqd_java/article/details/53924769

路径问题

javaWeb中的"/"

什么情况下”/“表示当前web应用的根路径即http://localhost:8080/Dive/

需要交由servlet容器处理的时候

1)请求转发时

request.getRequestDispatcher("/jspDir/b.jsp").forward(request,response);

2)配置web.xml文件中映射servlet访问路径时

什么情况下”/“表示表示web站点的根路径即http://localhost:8080/

需要交由浏览器处理的时候

1)超链接href的值;

2)表单中的action值;

3)请求重定向

开发过程中,建议写“绝对路径”,"/"代表的是站点的根目录时,在后面直接加contextPath(request或application获取);

如果不愿意写,也可以通过head元素里的base标签指定基本 URL 来解析所有的相对 URL。

Java EE 项目的目录结构可以根据具体的需求进行灵活设计,但一般情况下,推荐使用以下的标准目录结构: ``` project ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── example │ │ │ ├── controller │ │ │ ├── dao │ │ │ ├── entity │ │ │ ├── service │ │ │ └── util │ │ ├── resources │ │ │ ├── mapper │ │ │ └── db.properties │ │ └── webapp │ │ ├── WEB-INF │ │ │ ├── classes │ │ │ ├── lib │ │ │ └── web.xml │ │ ├── css │ │ ├── js │ │ ├── images │ │ └── index.jsp │ └── test │ ├── java │ └── resources ├── target ├── pom.xml └── README.md ``` 其中,各个目录的作用如下: - `src/main/java`:存放项目的 Java 源代码,按照包名分层,一般包括 `controller`、`dao`、`entity`、`service` 和 `util` 等包; - `src/main/resources`:存放项目的配置文件和资源文件,一般包括数据库连接配置文件 `db.properties`、MyBatis 的 mapper 文件等; - `src/main/webapp`:存放 Web 应用的 Web 资源,包括 JSP 页面、CSS 样式表、JavaScript 脚本等; - `src/test/java`:存放项目的测试代码; - `src/test/resources`:存放测试代码所需要的资源文件; - `target`:存放编译后的 .class 文件、打包后的 .war 文件等; - `pom.xml`:Maven 项目管理工具的配置文件; - `README.md`:项目说明文件。 以上是一种常见的 Java EE 项目目录结构,但并不是唯一的标准。在实际开发中,可以根据项目的具体需求进行合理的调整和修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值