JavaWeb: jsp

主要内容:两个指令page,include,jsp九大内置对象,内省,BeanUtils的使用,el表达式

原理: 本质就是一个servlet.主要用于显示页面;访问jsp页面,就相当于访问一个servlet

运行过程: 第一次访问jsp时 => jsp 编译成.java => java生成字节码 => 加载到虚拟机运行.


jsp脚本

jsp中的脚本:用来在jsp中嵌入java代码.

<% %> 嵌入在service方法中

<%! %> 嵌入在类中.

<%= %> 嵌入在service方法中,并使用out.write();方法包裹. 就是输出.

JSP中的 注释:<%-- --%> 多行注释. 被注释的代码不会参与编译.

 

1.JSP中指令(一个指令可以具备多个属性

JSP 指令:用来设置整个JSP页面相关的属性,如网页的编码方式脚本语言。指令可以有很多个属性,它们以键值对的形式存在,并用逗号隔开。

语法格式:<%@ directive attribute="value" %>

<%@ page contentType="text/html;charset=UTF-8"language="java"pageEncoding="UTF-8" %>

页面保存到硬盘的编码方式为utf-8,表示页面中使用的语言为java语言,发给浏览器的编码方式,*import="java.util.*"  就是导包. 是所有属性中唯一一个可以在页面中出现多次的属性.

以上两个码表最好一致. 但是一般设置一个属性即可.另外一个属性自动设置.

 

缓冲区属性:

autoFlush="true" 如果缓冲区装满是否自动刷新到浏览器. 如果装满并没有选择自动刷新,那么会抛出异常.

buffer="8kb" 决定jsp输出缓冲区大小为8kb

 

如果访问当前页面报错,就会跳转到指定的页面(demo2.jsp)

errorPage="/demo2.jsp"  配置当前页面的错误页面

isErrorPage="true" 指定当前页面是否是一个错误页面(在demo.jsp中应该配置此属性,然后就可以使用exception对象,获取前一个报错页面的错误信息;使用exception对象的前提条件是什么?在错误页面打印出报错信息)

 

开发中,我们可以使用如下配置统一配置错误页面(考虑到代码的复用性),比上面的方式要省事(上面的每个配置使用不方便,几乎每个jsp页面都需要配置):

在web.xml中统一进行配置错误页面,当遇到500错误时,显示如下页面

<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>

    <!--统一配置错误页面,当遇到500错误时,跳转到如下页面-->
    <!--考虑到代码的复用性,这是一个比较好的解决方案-->
    <!--最好不要把错误页面暴露给用户,这样用户体验差-->
    <error-page>
        <error-code>500</error-code>
        <location>/error.jsp</location>
    </error-page>

extends="" 决定当前jsp的父类是谁.父类必须是servlet的子类.

isELIgnored="false"  决定当前页面能否使 EL表达式.默认值就是支持EL.

isThreadSafe="true"  指定当前的jsp是否线程安全(废弃). 实现一个标记性接口. STM => SingleThreadModel

session="true" 当前jsp页面是否可以直接使用session对象.默认值就是true.


include 静态包含指令

include 属于静态包含 , 现将两个jsp的代码合并.然后在共同编译成一个java文件.在编译成class ,然后执行.

因为存在合并代码,所以变量可以共享. 键名为file。

使用: <%@ include file="/include/B.jsp" %>  将该指令加入到需要引入的位置即可.


2.JSP中的9大内置对象(每个对象都对应一个类型

指的在jsp中不加以声明就可以直接使用的9个对象(因为它也是Servlet对象).

原理: 因为我们的代码是写在jsp对应java文件的service方法中的.所以在service方法中声明的变量,我们可以直接使用.(运行之后查看.java文件中的_jspService方法)

public void _jspService(HttpServletRequest request, HttpServletResponse response)

        throws java.io.IOException, ServletException {

对象名称 对象类型

request HttpServletRequest

response HttpServletResponse

session HttpSession

exception Throwable

application ServletContext

config ServletConfig

page Object

out JspWriter

pageContext PageContext

 

1、out 对象是jsp当中的输出对象,页面显示,可以直接显示字符串.

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<% out.write("c"); %>
<% response.getWriter().write("b");%>
<% out.write("c");%>
<% response.getWriter().write("d");%>
</body>
</html>

输出: bd ac

原理:在输出到浏览器时,会先把两个流合并,再输出.合并时response的字符流在前.JSPWriter在后. 所以不管代码书写顺序如何.最终response流的内容总会在JSPwriter流的内容之前显示。

结论: 在jsp中输出使用out(JSPWriter)输出,不要使用response.getWriter输出.

 

2、page对象:page对象指向的就是 this(当前jsp生成Servlet对象);

一般是在开发框架时,框架需要用到JSP对象,进行一些页面的操作时,将page对象传过去即可.

3、pageContext对象(域对象,域对象底层都是map集合)(3个知识点)

身是一个域对象. 在pageContext对象上有一个map. 这个Map就是Page域.

操作: 4个操作.

域范围: 就只在当前页面中有用.

作用: 在jsp中应避免在页面上书写任何java代码.

pageContext.setAttribute(name, value);
pageContext.getAttribute(name);
pageContext.removeAttribute(name);
//获取某个域中的所有键
pageContext.getAttributeNamesInScope(scope);

pageContext对象还可以操作其他3个域,目的就是为了方便.(从其他三个域中取值,想其他三个域中存入值,清除其他三个域中的数据,就这三个操作)
pageContext.setAttribute("name","applicationTom",PageContext.APPLICATION_SCOPE );
pageContext.setAttribute("name", "sessionTom",PageContext.SESSION_SCOPE );
pageContext.setAttribute("name", "requestTom",PageContext.REQUEST_SCOPE );
pageContext.getAttribute(name, scope);
pageContext.removeAttribute(name, scope);
pageContext.getAttributeNamesInScope(scope);

pageContext.findAttribute("name") 会从所有域中查找键name 的值. 从小到大,返回最小域的值 pageContext到application域

持有其他8个内置对象的引用.根据这个对象可以获得其他8个内置对象。(如果需要其他八个内置对象,直接传递pageContext对象,然后从此对象中获取其他对象,主要是简化代码和复用)

pageContext.getRequest();
pageContext.getResponse();
pageContext.getSession();
pageContext.getServletContext();
pageContext.getException();
pageContext.getServletConfig();
pageContext.getOut();
pageContext.getPage();

3.JSP中的动作标签(动作标签是干什么用的) 在jsp当中调用外部类的方法

动作标签出现的年代是在JSP model1 .

<jsp:forward page="/index.jsp"></jsp:forward> 主要用于请求转发forward。现在可以直接使用request对象进行实现。

<jsp:include page="/index.jsp"></jsp:include>  ==>  将来可能会使用.

<% request.getRequestDispatcher("").include(request, response); %>

上面的包含就是之前学习的request的请求包含. 这种包含也叫做动态包含.动态包含的两个页面会分别编译成两个java.class.分别执行. 只是在最后输出时将输出结果合并.所以页面中的变量不会共享.


4.JAVA中内省以及在项目中的应用

java中的内省. 内省是基于java中反射技术的一套工具API.

功能: 用来操作javaBean的属性的(用来操作java对象的属性,设置值和取值,特别简单,经常用的).

javaBean: 就是类. 只要符合以下规则就可以称这个类为javaBean. 比如Student这个类(类和对象是不一样的,javaBean不是对象,一定要记得)

javaBean的规则:

1.必须有空参的构造方法.

2.所有属性提供共有的Get/Set方法.

3.所有属性对应的字段私有.

4.(可选)实现串行化接口.

属性指的就是提供get/set方法的.

而类的中成员变量不能称为属性.

如果你的类符合javabean规则. 那么久可以使用内省这套api来操作你的bean.

//----------------------------------------------------------------------------------------------

//使用内省操作bean的例子.

//功能: 使用内省技术将User对象的name属性设置为rose;

//使用内省的应用: 可以将表单中的参数封装到JavaBean

//上面的方法是模拟BeanUtils工具类的对应方法.

BeanUtils.populate(u, request.getParameterMap());

注意: 表单的参数的键必须与Bean中属性名称对应.

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //解决乱码问题
        request.setCharacterEncoding("UTF-8");
        //获取用户输入的用户名和密码并封装成对象
        //凡是通过表单提交的参数,都要进行这样的处理特别麻烦。使用内省进行操作
        //String name = request.getParameter("name");
        //String password = request.getParameter("password");
        //LoginEntity loginEntity = new LoginEntity();
        //loginEntity.setName(name);
        //loginEntity.setPassword(password);

        //思路:自动将表单信息封装到Bean中
        //遍历Bean中国的属性,从封装表单的map集合中,以属性名为键进行查找提交上来的值,
        //如果找到值,那么就将值封装到Bean对应的属性中
        //如果能够取到值,,就放进去
        LoginEntity loginEntity = new LoginEntity();
        //Map<String, String[]> paras = request.getParameterMap();
        try {
            //processMethod(loginEntity, paras);
            //使用BeanUtils进行处理
            //注意:集合不能事String的泛型
            BeanUtils.populate(loginEntity,request.getParameterMap());
            //打印属性的值,基础好便于对框架原理的理解
            System.out.println(loginEntity.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void processMethod(LoginEntity loginEntity, Map<String, String[]> paras) throws Exception {
        BeanInfo beanInfo = Introspector.getBeanInfo(LoginEntity.class);
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
        //遍历属性数组,判断当前遍历的属性是否是name属性
        for (PropertyDescriptor pd : pds) {
            String name = pd.getName();
            String[] values = paras.get(name);
            //表示在map中找到了对应的提交信息
            if (values != null && values.length > 0) {
                Method method = pd.getWriteMethod();
                //将用户提交的信息封装到对应的属性当中
                method.invoke(loginEntity, values[0]);
            }
        }
    }

BeanUtils 工具类的使用:(需要导入jar包)

BeanUtils 可以自动帮你转换8个基本数据类型. 如果遇到自定义类型需要转换.我们要自己写一个转换器并注册:实现Converter接口

转换器注册

注册我们自定义的转换器

参数1 自定的转换器;参数2 注册转换的类型

ConvertUtils.register(new MyDateConverter(), Date.class);

完成如上两步即可.


5. EL表达式与EL函数 :${ var } 主要用于获取变量的值,并进行输出

EL表达式为了替代页面上的java代码 .

<%= %>输出脚本    ==> el表达式为了替换该脚本, EL表达式就是用来输出的.

格式: ${}

主要有三个知识点:1)内置对象,2)使用el表达式操作array,list,map,javabean等,3)EL在输出的同时还可以对输出的内容进行简单的判断。

1)EL中有11个内置对象,常用的5个,pageScope,requestScope,sessionScope,applicationScope,pageContext(这就是对象的名字)

2)EL可以显示 JavaBean,Map,List,Array 当中的内容或属性

3)EL在输出的同时还可以对输出的内容进行简单的判断

注意:empty 运算符 判断的时候是根据判断的内容标准变化.

<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="com.tniu.app.entity.LoginEntity" %><%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2017/7/8
  Time: 17:55
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL的学习</title>
</head>
<br>

<!--往四大域中存入值-->
<% request.setAttribute("name", "requestTom"); %>
<% session.setAttribute("name", "sessionTom");%>
<% application.setAttribute("name", "applicationTom");%>
<% pageContext.setAttribute("name", "pageContextTom");%>

<!--取出域中对象的值,可以成功-->
<%=request.getAttribute("name")%>
<%=session.getAttribute("name")%>
<%=application.getAttribute("name")%>
<%=pageContext.getAttribute("name")%>

<% Cookie cookie = new Cookie("name", "tomCookie");
    response.addCookie(cookie);
%>
<!------------------------------------------------------------------------------------->
<!--el表达式中的几个常用对象,都是以Scope结尾的-->
<!--通过el表达式实现,与上面的操作是等价的-->
${requestScope.name} --</br>
${sessionScope.name} --</br>
${applicationScope.name} --</br>
${pageScope.name} --</br>

<!--el表达式和输出脚本的区别:如果el表达式取不到值,就什么也不输出,但是如果是输出脚本,就直接输出null-->
${requestScope.password} 什么也不输出--</br>
<%=request.getAttribute("password")%> --</br>

<!--输出项目路径,项目路径是空的,pageContext对象的使用--> 
${pageContext.request.contextPath}/AServlet
<!--打印客户端ip地址-->
${pageContext.request.remoteAddr}

<!--获取表单提交的参数,键为name的值-->
${param.name} </br>
<!--获取表单提交的参数,键为name的数组-->
${paramValues.name} </br>
<!--获取键为name的cookie值-->
${cookie.name.value}  </br>
<!------------------------------------------------------------------------------------->
<!--使用EL表达式操作集合、数组、javabean-->
<!--把数组,集合,放入域对象当中,一直在使用requestScope这个EL对象-->

<!--使用EL表达式从数组中取出值-->
<% String[] arr = {"test1", "test2"};
    request.setAttribute("arr", arr);
%>
${requestScope.arr[0]} </br>
${arr[0]} </br>

<!--使用EL表达式从集合中取出值:取出集合当中第二个元素-->
<% ArrayList list = new ArrayList();
    list.add("rose1");
    list.add("rose2");
    request.setAttribute("list", list);
%>

${requestScope.list[1]} </br>
${list[1]} </br>

<!--使用EL表达式从map集合中取出值-->
<% Map map = new HashMap<>();
    map.put("name.n", "test");
    map.put("age", 99);
    request.setAttribute("map", map);
%>
${requestScope.map.name} </br>
${requestScope.map.age} </br>
<!--如果键中有.进行分割,就使用下面这种方式,上面的方法可能就不能用了-->
${requestScope.map["name.n"]} </br>

<!--使用EL表达式从javaBean中取出值-->
<%
    LoginEntity loginEntity = new LoginEntity();
    loginEntity.setName("response");
    request.setAttribute("loginEntity", loginEntity);
%>
${requestScope.loginEntity.name} </br>
${loginEntity.name} </br>

<!------------------------------------------------------------------------------------->
<!--使用EL表达式对输出结果进行判断操作-->
<% request.setAttribute("age1", 33);
    request.setAttribute("age2", 22);
%>
${requestScope.age1>request.age2} </br>
${requestScope.age1>=request.age2} </br>
${requestScope.age1<request.age2} </br>
${requestScope.age1<=request.age2}  </br>
${requestScope.age1!=request.age2} </br>
${true||false} </br>

<!--判断数组是否有值-->
<% String str = "";
    request.setAttribute("str", str);
%>
判断字符串是否有值--->${empty requestScope.str}
返回true,表示是空的

</body>
</html>


Cookie&Session都是属于会话技术.都是用来保存会话状态的技术.其中客户端保存信息的技术是cookie. 服务器端是session.

Cookie原理: 服务器发送 set-Cookie的响应头. 要求浏览器记住(键值对). 在浏览器的后续访问中,如果访问路径符合cookie的规则,那么浏览器会使用.Cookie 请求头将键值对发送给服务器.

服务器端操作: 新建一个cookie,并发送给客户端

Cookie cookie = new Cookie(键,值); response.addCookie(cookie);

客户端操作:获得浏览器发送的cookie: Cookie[] cookies = request.getCookies();  //之后遍历并筛选要找到的cookie.

 

Cookie的细节:

1、 cookie的保存时间. 该有效时间是绝对的. 设置为2周,那么不受其他因素影响,只能存在2周.除非覆盖修改成其他时间.

cookie.setMaxAge(int 秒); 正整数 : 设置有效时间;0 : 到了浏览器端就删除. 为了覆盖之后删除;-1: 默认值, 关闭浏览器时删除.

2、Cookie的路径api:cookie.setPath

默认值: 发送cookie的资源所在路径..

访问时: 访问的路径属于浏览器记录的cookie的子路径.那么浏览器将会发送cookie.

3、浏览器端保存cookie的数量有限制.

例子:访问历史记录

例子:记住用户名.

 

Session

服务器端保存信息的技术.一个会话可能有多个请求。

原理: 浏览器连接到服务器时,如果没有携带sessionID那么服务器会创建一个session对象并产生一个唯一的ID. 响应时服务器会把sessionID发送给

浏览器要求浏览器记住sessionID(Cookie), 浏览器下次访问时携带sessionID.服务器就可以找到与之对应的session对象. 

如何判断浏览器是否是第一次访问服务器?看看是否携带SessionId或者Cookie

获得session: request.getSession();

session细节:

1、 session的有效时间:默认值: tomcat中默认是30分钟.修改web.xml中的

<session-config> <session-timeout>30</session-timeout> <session-config>

以上配置可以加在 tomcat下的web.xml 或 项目下的web.xml. 影响的范围不同.

 

2、 session生命周期

session的创建: 浏览器第一次访问.

session的销毁: 1> session过期时 自动销毁.2、手动调用销毁方法 session.invalidate();

Cookie与Session的模板性代码


案例:(把案例记到脑子里面)

Jsp中page指令

Jsp错误页面的配置:exception对象的使用

Jsp的静态包含指令include,合并效果的实现,变量共享的实现

Jsp中的九大内置对象,每个对象都有不同的作用:session、request、application、pageContextout(四个域对象)、exception、

Jsp中的out对象特征,与Response.getWrite()进行对比

pageContext域对象的使用:三个方法

什么是动态包含? 一定要记得 

使用过的jar包,每个jar包都是做什么用的,框架名一般都小写 Beanutilslogging。

如果是通过maven下载的依赖,要在pom.xml文件中配置

BeanUtils没有转化成功, 乱码问题还是没有得到解决。

 

J2EE的工作很简单:

前端就写一些JSP页面,后台就写Servlet。

 

热更新的注意事项:

Tomcat热更新功能的使用:修改完jsp代码之后,需要进行编译,才能访问,否则会报出异常:org.apache.jasper.JasperException: Unable to compile class for JSP(未能期编译)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值