JSP基本使用

初识JSP

JSP(Java Server Pages )Java服务器页面,是一种动态网页开发技术。它使用JSP标签在HTML网页中插入Java代码。 JSP本质是servlet,

创建JSP之后内容先写一个头信息

<%@page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8"%>
标记含义
<%@ %>说明性的标记 通常会放在文件的顶部
<%! %>包含普通的Java代码,_jspService方法外部
<% %>包含普通的Java代码, _jspService方法内部
<%= %>包含普通的Java代码,通常是用来赋值和展示
<%-- --%>jsp文件中注释内容

JSP编译

.jsp文件编译后存放的位置默认是在IDEA
C:\Users\个人电脑用户名.IntelliJIdea2019.3\system\tomcat\Tomcat_8_5_60_Servlet1\work\Catalina\localhost\Servlet1\org\apache\jsp

:设计一个登录页面查询展示金额的例子

部分代码:
文件名称:showBalance.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
    <head>
        <script type="text/javascript">
            window.onload = function(){
                var inputButton = document.getElementById("back");
                inputButton.onclick = function(){
                    window.history.back();
                }
            }
        </script>
    </head>
    <body>
		<%--1.声明类属性--%>
		<%!
		    private String name;
		    private String sex;
		    private Integer age;
		%>
		<%--2.声明类方法--%>
		<%!
		    public int add(int a ,int b) {
		        return a+b;
		    }
		%>

        <%--获取内置对象中的值--%>
        <%
            String aname = (String) session.getAttribute("aname");
            Float abalance = (Float)request.getAttribute("abalance");
        %>
        尊敬的${requestScope.aname}>用户,您的可用余额为:${requestScope.abalance}元<br>
        <input id="back" type="button" value="回去">
    </body>
</html>

showBalance.jsp经过JSP解析引擎会生成一个showBalance_jsp.java,编译生成showBalance_jsp.class文件

showBalance_jsp.java部分代码:

package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class showBalance_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  private String name;
  private String sex;
  private Integer age;

  public int add(int a ,int b) {
       return a+b;
  }
  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  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\n");
      out.write("<html>\r\n");
      out.write("    <head>\r\n");
      out.write("        <script type=\"text/javascript\">\r\n");
      out.write("            window.onload = function(){\r\n");
      out.write("                var inputButton = document.getElementById(\"back\");\r\n");
      out.write("                inputButton.onclick = function(){\r\n");
      out.write("                    window.history.back();\r\n");
      out.write("                }\r\n");
      out.write("            }\r\n");
      out.write("        </script>\r\n");
      out.write("    </head>\r\n");
      out.write("    <body>\r\n");
      out.write("        ");

            String aname = (String) session.getAttribute("aname");
            Float abalance = (Float)request.getAttribute("abalance");
        
      out.write("\r\n");
      out.write("        尊敬的");
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${requestScope.aname}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
      out.write(">用户,您的可用余额为:");
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${requestScope.abalance}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
      out.write("元<br>\r\n");
      out.write("        <input id=\"back\" type=\"button\" value=\"回去\">\r\n");
      out.write("    </body>\r\n");
      out.write("</html>\r\n");
    } catch (java.lang.Throwable t) {
      //抛出异常
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

JSP常用脚本

常用脚本作用
<%! %>可以声明类属性、方法、代码块、静态代码块 被翻译到对应的Java类全局范围中
<% %>被翻译到对应的Java类的_jspService()方法中
<%=表达式 %>在浏览器的JSP页面上输出数据,被翻译到对应的Java类的_jspService()方法中

JSP的本质

JSP页面本质上是一个Servlet程序,第一次访问JSP页面时,Tomcat服务器中的JSP解析引擎会将xxx.JSP页面解析成为一个Java源文件,并对其进行编译成为.class字节码文件(一个.java,一个.class),当打开.java文件时发现其中的内容是:

public final class showBalance_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

而HttpJspBase类直接继承HttpServlet类,即JSP文件翻译出来的Java类间接继承于HttpServlet类,证明JSP页面是一个Servlet程序

JSP生命周期

  1. JSP进行初始化

当一个JSP网页加载到容器时,执行先执行_jspInit方法,初始化

  public void _jspInit() {
  }
  1. JSP摧毁

当一个JSP网页从容器中被移除时执行_jspDestroy方法

 public void _jspDestroy() {
  }
  1. JSP执行

JSP网页完成初始化后,会执行_jspService方法

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    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\n");
      out.write("<html>\r\n");
      out.write("    <head>\r\n");
      out.write("        <script type=\"text/javascript\">\r\n");
      out.write("            window.onload = function(){\r\n");
      out.write("                var inputButton = document.getElementById(\"back\");\r\n");
      out.write("                inputButton.onclick = function(){\r\n");
      out.write("                    window.history.back();\r\n");
      out.write("                }\r\n");
      out.write("            }\r\n");
      out.write("        </script>\r\n");
      out.write("    </head>\r\n");
      out.write("    <body>\r\n");
      out.write("        ");

            String aname = (String) session.getAttribute("aname");
            Float abalance = (Float)request.getAttribute("abalance");
        
      out.write("\r\n");
      out.write("        尊敬的");
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${requestScope.aname}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
      out.write(">用户,您的可用余额为:");
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${requestScope.abalance}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
      out.write("元<br>\r\n");
      out.write("        <input id=\"back\" type=\"button\" value=\"回去\">\r\n");
      out.write("    </body>\r\n");
      out.write("</html>\r\n");
    } catch (java.lang.Throwable t) {
     //抛出异常
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }

JSP9大内置对象

对象含义
javax.servlet.http.HttpServletRequest request客户端一次请求
javax.servlet.http.HttpServletResponse response服务器响应
final javax.servlet.jsp.PageContext pageContextJSP当前上下文页面
javax.servlet.http.HttpSession session = null一次会话
final javax.servlet.ServletContext application全局上下文对象
final javax.servlet.ServletConfig config配置对象
javax.servlet.jsp.JspWriter out = null输出流输出到浏览器
final java.lang.Object page = thisJSP当前页面
java.lang.Throwable exception捕获程序中出现的错误展示到页面
javax.servlet.jsp.JspWriter _jspx_out = null;//后面添加的
javax.servlet.jsp.PageContext _jspx_page_context = null;后面添加的

HttpServletRequest request

常用的方法

方法含义返回值
getParameter(key)获取携带的参数String
setAttribute(key,value)添加携带的参数转发void
getAttribute(key)获取setAttribute()添加的参数Object
setCharacterEncoding(“uft-8”)用来设置接受请求参数时的字符集(POST)void
getRequestDispatcher(path)用来设置转发的资源位置RequestDispatcher
getParameterNames()获取全部的keyEnumeration
getParameterValues()获取全部的valueString[]
getSession()获取HttpSession对象HttpSession
getHeaderNames()获取所有的头信息Enumeration
getHeader(“Accept-Language”)获取协议头传递的信息String
getRequestURL()获取URLStringBuffer
getRequestURI获取 /工程名/资源名String
getCookies()获取所有的cookieCookie[]

国际化

internationalization –简记 I18N
获取头信息可以做国际化效果,如创建一个中文库(.properties)和一个英文库(.properties),根据浏览器的第一语言展示不同的效果可以利用req.getHeader(“Accept-Language”) ,来获取到浏览器可用的语言,进行解析,服务器找到对应的.properties文件进行展示。

  //获取src下文件内信息
       InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("test.properties");

       Properties properties = new Properties();
       properties.load(in);

 

浏览器的状态码

状态码含义
1xx消息接收的请求正在处理
2xx成功请求正常处理完毕
3xx重定向需要进行附加操作以完成请求
4xx客户端错误服务器无法处理请求
5xx服务器错误服务器处理请求出错

request和response区别

request是代表HTTP请求信息的对象,response是代表HTTP响应信息的对象。

:获取请求参数时的中文乱码问题?

如果请求是GET提交,中文不会乱码,
如果请求是POST提交,中文会乱码,默认编码的iso8859-1
可以使用request.setCharacterEncoding(“utf-8”);来设置编码
!!! tomcat是7.0及以前的版本,GET提交的中文参数,在获取时也会出现乱码问题!

转发和重定向的区别

forwardsendRedirect
RequestDispatcher类HttpServletResponse类
rd.forward(req,resp);response.sendRedirect(“path”);
转发是在服务器内部完成,浏览器不知道重定向是服务器告知浏览器,让浏览器重新再发一个请求
服务器内部传递req resp服务器需要解析新的请求 获得新的req resp
最终的展示可以获取请求的信息(一次请求)刚才的req没有了 刚才的参数获取不到(两次请求)
转发的时候浏览器URL不会改变重定向的时候浏览器的URL会发生改变

请求转发的简易流程图
在这里插入图片描述

请求重定向的简易流程图

在这里插入图片描述

JSP四大域对象

对象作用域
pageContext当前页
request一次请求
session一次会话(打开浏览器至关闭浏览器)
application全部会话(在不同浏览器中打开都可以访问)

作用域从小到大依次
pageContext<request<session<application

session常用的方法

常用场景:浏览器访问服务器时长,Tomcat 服务器默认的Session超时时间是30分钟
setMaxInactiveInterval()方法可以设置

        session.setAttribute("key",Object);
		Object = session.getAttribute("key");
		session.removeAttribute("key"); 
		//获取全部的key
		Enumeration en = session.getAttributeNames();
		//设置最大活跃时间 单位是 s ,超过时间处于不活跃状态并没有销毁session对象
		session.setMaxInactiveInterval(100);
		//销毁session对象
		session.invalidate();

ServletConfig对象、ServletContext对象

ServletConfig对象

servlet配置对象

       ServletConfig config = getServletConfig();
        //1.请求资源名
        System.out.println(config.getServletName());
        //2.web.xml定义的init-param  初始化参数
        String valueL = config.getInitParameter("zhangs");
        System.out.println(valueL);
        //3.获取全部的初始化参数
        Enumeration en = config.getInitParameterNames();
        //4.获取ServletContext 域对象
        ServletContext context = config.getServletContext();

String valueL = config.getInitParameter(“zhangs”);获取的是下面web.xml中的 key

    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>controller.LoginController</servlet-class>
        <!--init-param放在 servlet-class标签下面 -->
        <init-param>
            <param-name>zhangs</param-name>
            <param-value>123</param-value>
        </init-param>
    </servlet>

ServletContext对象

       /获取ServletConfig对象
       ServletConfig config= getServletConfig();
       //获取ServletContext对象
       ServletContext context= servletConfig.getServletContext();
       //1.往ServletContext域中,存值
       servletContext.setAttribute("zhangs",123);
       //2.获取全局上下文域中的参数值
       int val = (int) context.getAttribute("zhangs");
       //3.将ServletContext域中指定名称的参数移除;
       context.removeAttribute("zhangs")//4.获取真实的路径 
       //如:D:\ideaProject\ServletTest\out\artifacts\ServletTest_war_exploded\login
       String loginRealPath = context.getRealPath("login");

全局初始化参数

    getInitParameter():获取指定参数名称的全局参数值
    getInitParameterNames():获取所有的全局初始化参数名称
web.xml
    <context-param>
        <param-name>zhangs</param-name>
        <param-value>123</param-value>
    </context-param>

Exception

Exception内置对象只有在出现异常的时候才会出现

//1.可以写一个新的jsp	比如error.jsp 
//2.在error.jsp头信息上设置     isErrorPage="true"
//3.在任意正常的jsp中设置头信息   errorPage="error.jsp" 如果404没有找到资源,就会跳转到 error.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>

JSP指令标签

xxx.jsp
//指令标签通常放在.jsp头部
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file=".html/.jsp"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
指令标签解释
<%@ page %>当前页说明
<%@ taglib %>引入 core 、function、format 、自定义Tag
<%@ include%>用来在当前JSP中引入已经写好的资源

<%@ page %>

属性解释
contentType=“text/html;charset=UTF-8”告知浏览器解析时遵循的规则
language=“java”JSP中含有的语言(默认)目前只能是java
import=“”在JSP中导入的Java文件的包
isErrorPage=“true”设置当前JSP作为一个异常页
errorPage=“xxx.jsp”当前页发生异常跳转xxx.jsp
isThreadSafe表示最终生成的servlet是否具有线程安全性。

<%@ taglib %>

用到JSTL (Jsp Standard Tag Library) jsp标准标签库

属性解释
uri=“http://java.sun.com/jsp/jstl/core”导入的uri
prefix=“c”前缀

后面会用到

<%@include file=“” %>

用来在当前JSP中引入已经写好的JSP资源 file=“” 所在文件路径

EL表达式

表达式语言(Expression Language )
该技术的出现原因解决的是:代替原来Java程序取值的过程,使得jsp中的不再出现java代码
作用:

  1. 取值;
  2. 调用方法

直接上手测试
测试项目


public class User {

    private String uname;
    private String usex;
    private Integer uage;
     public User(){}

    public User(String uname, String usex, Integer uage) {
        this.uname = uname;
        this.usex = usex;
        this.uage = uage;
    }

    //省略了get/set方法
    。。。
}

index.jsp


<%-- index.jsp--%> 
<a href="el?wd=jyl&pwd=123456">EL测试</a> 

查找web.jsp 找到 el请求名,再而找到controller类

//EL测试的controller类部分代码
        String wd = request.getParameter("wd");
        String pwd = request.getParameter("pwd");
        System.out.println("wd = "+wd+",pwd = "+pwd);//第一次请求参数
        //测试一个对象 , 
        User user = new User("zhangs","nan",19);
        request.setAttribute("user",user);
        

    
        request.setAttribute("user",user);  //中间添加的转发的参数
        request.getSession().setAttribute("user",user);//会话
        this.getServletContext().setAttribute("user",user);//全局上下文

        //List
        ArrayList<User> userList = new ArrayList<User>();
        userList.add(new User("zhangsan","nan",18));userList.add(new User("lisi","nv",19));
        request.setAttribute("userList",userList);
        // 上述List集合
        //  通过${xxxScope.集合名.get(index)}    如果index越界则会产生异常

       //Set
        HashSet<User> userSet = new HashSet<User>();
        userSet.add(new User("wanwu","nan",22));
        userSet.add(new User("qianqi","nv",23));
        request.setAttribute("userSet",userSet);
        //上述是Set集合
        // 可以获取集合对象 可以获取size 但不能通过get()方法获取set集合中的内容 需要JSTL

        // Map
        HashMap<String,String> strMap = new HashMap<String,String>();
        strMap.put("mapName1","aaa");
        strMap.put("mapName2","bbb");
        request.setAttribute("strMap",strMap);
         //转发el.jsp
         
         
        request.getRequestDispatcher("el.jsp").forward(request,response);
<%--el.jsp--%>
<body>
requestScope<br>
	${requestScope.user.uname}<br>
	${requestScope.user.usex}<br>
	${requestScope.user.uage}<br>
<hr>
sessionScope<br>
	${sessionScope.user.uname}<br>
	${sessionScope.user.usex}<br>
	${sessionScope.user.uage}<br>
<hr>
applicationScope<br>
	${applicationScope.user.uname}<br>
	${applicationScope.user.usex}<br>
	${applicationScope.user.uage}<br>
<hr>
param<br>
	${param.wd}<br>
	${param.pwd}<br>
	 <hr>
userList<br>
	${requestScope.userList.get(0).uname}--${requestScope.userList.get(0).usex}--${requestScope.userList.get(0).uage}<br>
	${requestScope.userList.get(1).uname}--${requestScope.userList.get(1).usex}--${requestScope.userList.get(1).uage}<br>

<hr>
userSet<br>
	${requestScope.userSet}<br>
	${requestScope.userSet.size()}<br>


<hr>
strMap<br>
	${requestScope.strMap}<br>
	${requestScope.strMap.size()}<br>
	${requestScope.strMap.get("mapName1")}--${requestScope.strMap.get("mapName2")};
</body>

输出结果

requestScope
  zhangs
   nan
  19
sessionScope
  zhangs
   nan
  19
applicationScope
  zhangs
   nan
  19
param
   jyl
  123456
userList
	zhangsan--nan--18
	lisi--nv--19
userSet
	[domain.User@3496e06f, domain.User@3a51188d]
	2
strMap
	{mapName1=aaa, mapName2=bbb}
	2
	aaa--bbb; 

隐式内置对象有:

作用域对象范围
param第一次请求参数
requestScope中间添加的转发的参数
sessionScope一次会话
applicationScope全局上下文
cookie默认是一次会话

隐式内置对象获取到User中的属性, 原理是利用了反射技术获取到公有的get方法

可以验证,我们将User中的私有属性的get方法和set方法 删除那么内置对象就无法获取到user对象属性,并且浏览器会报出javax.el.PropertyNotFoundException: 类型[domain.User]上找不到属性的异常

EL其他不常用内置隐式对象

  1. ${paramValues.xxx)
  2. ${initParam.xxx}
  3. ${header[accept-language]}

做简单的计算

算数 逻辑 比较 ${取值 计算}

        ${requestScope.value mod 2}<br>
        ${requestScope.value + "10"}<br>  //字符10 会转化成数字10
        ${requestScope.value >= 10}<br>
        ${requestScope.value < 10}<br>
        ${requestScope.value ge 10}<br>
        ${requestScope.value ne 10}<br>

0
20
true
false
true
false

JSTL

JSTL (Jsp Standard Tag Library) jsp标准标签库
需要引入jstl.jar、standard.jar包
大体上提供了三个包
核心(流程控制core) 函数(处理String) 格式化(Date Time)
1.核心(流程控制core)
2.函数(处理String)
3.格式化(Date Time)

<%@ taglib 
	uri="http://java.sun.com/jsp/jstl/xxxx" 
	prefix=""
%>

核心标签

<%@ taglib
uri=“http://java.sun.com/jsp/jstl/core”
prefix=“c”
%>
主要是做选择判断,循环遍历
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<c:out value="hello"></c:out>   输出 hello
<c:out value="${requestScope.coreValue}"></c:out>
<hr>
        <c:if test="${3>2}">   相当于if()
            满足条件
        </c:if><br>
        <c:choose>  相当于switch()
            <c:when test="${requestScope.day == 1}">
                monday
            </c:when>
            <c:when test="${requestScope.day == 2}">
                tuesday
            </c:when>
            <c:when test="${requestScope.day == 3}">
                wednesday
            </c:when>
            <c:otherwise>
                error
            </c:otherwise>
        </c:choose>
		<%--遍历集合  下面代码相当于 java   for( : )--%> 
		<c:forEach items="${requestScope.userList}" var="u">  
		     ${u.uname}--${u.usex}--${u.uage}<br>
		</c:forEach>

        <%--相当于字符串 .split("-") 拆分字符串的方法--%> 
	    <c:forTokens var="value" items="${requestScope.str}" delims="-">
	            ${value}
	    </c:forTokens>

函数(处理String)

<%@ taglib
uri=“http://java.sun.com/jsp/jstl/functions”
prefix=“fn”
%>
很少会再视图层处理字符串, 所以很少会去使用
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
       <%--相当于字符串, --%> 
        ${fn:length(requestScope.user.uname)}<br>
        ${requestScope.strValue}<br>
        ${fn:length(requestScope.strValue)}<br>
        ${fn:contains(requestScope.strValue,"c")}<br>
        ${fn:indexOf(requestScope.strValue,"c")}<br>
        ${fn:replace(requestScope.strValue,"c","Z")}<br>


格式化(Date Time)

<%@ taglib
uri=“http://java.sun.com/jsp/jstl/fmt”
prefix=“fmt”
%>
这个标签库也不常使用,做格式化的作用
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
处理时间
<fmt:formatDate value="${requestScope.date}" pattern="yyyy-MM-dd kk:mm:ss"></fmt:formatDate>

自定义标签库

可以模范jstl.jar包自定义标签库

在这里插入图片描述

  1. 自定义方法
  2. 自定义标签

自定义方法

创建类 ,设计一个两位数之和的int add(int a , int b)方法

myfn.MyFunctions//设计一个方法  可以计算两个整数的和
    public static int add(int a,int b){
        System.out.println("我自己定义的方法执行啦啦啦啦");
        return a + b;
    }

在 WEB-INF文件夹下创建 fn.tld文件

<?xml version="1.0" encoding="UTF-8"?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
        version="2.1">

    <tlib-version>1.0</tlib-version>
    <!-- 前缀 -->
    <short-name>myFn</short-name>
    <!-- uri -->
    <uri>http://www.xxx.com/myFn</uri>

    <!-- Invoke 'Generate' action to add tags or functions -->
    <function>
      <!--类方法名(最好同步)-->
        <name>add</name>   
        <!--类所在的位置-->
        <function-class>myfn.MyFunctions</function-class>
        <!--类中的方法(方法是静态的)-->
        <function-signature>int add(int,int)</function-signature>
    </function>

</taglib>

使用:myFn函数

<%@ taglib uri="http://www.xxx.com/myFn" prefix="myfn"%>

函数执行的结果为:${myFn:add(3,4)}<br>

自定义标签

同样自定义标签也需要创建一个类和对应的 mytag.tld文件

:设计一个输出的功能 <myTag:out value=“”> </myTag:out>

//实现Tag 
public class MyOut implements Tag {

    //<c:out value="值">
    //    body
    //</c:out>
    //    page

    private String value;  //输出的值
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }

    //创建标签前使用的方法
    public int doStartTag() throws JspException {
        return Tag.EVAL_BODY_INCLUDE;
        //return Tag.SKIP_BODY;
    }
    //创建标签后使用的方法
    public int doEndTag() throws JspException {
        try {
            //可以获取out对象
            JspWriter out = this.pageContext.getOut();
            out.write(value);//打印输出
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Tag.EVAL_PAGE;
        //return Tag.SKIP_PAGE;
    }


    //============================================
    private Tag parent;  //父标签
    public void setParent(Tag parent) {
        this.parent = parent;
    }
    public Tag getParent() {
        return this.parent;
    }

    private PageContext pageContext;
    public void setPageContext(PageContext pageContext) {
        this.pageContext = pageContext;
    }
    public PageContext getPageContext(){
        return this.pageContext;
    }

    public void release(){}
}

创建 myTag.tld文件

<?xml version="1.0" encoding="ISO-8859-1"?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
        version="2.1">

    <tlib-version>1.0</tlib-version>
    <short-name>myTag</short-name>
    <uri>http://www.xxx.com/myTag</uri>

    <!-- Invoke 'Generate' action to add tags or functions -->
    <tag>
        <name>out</name>
        <tag-class>mytag.MyOut</tag-class>
        <body-content>JSP</body-content>
        <attribute>  <!--设置属性-->
            <name>value</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

</taglib>


文件上传和下载

本质 : I/O读写
客户端(浏览器)发送文件 协议
服务器(Web容器)接受文件 协议

可以使用别人写好的包来进行文件上传
常用的是apache组织提供的一个包
commons-fileupload.jar
commons-io.jar
去官方网站下载
链接: www.apache.org

文件上传

需要创建表单
必须使用form表单
必须是post方式提交
必须添加enctype属性 multipart/form-date

upload.jsp
<body>
	<form action="saveFile" method="post" enctype="multipart/form-data">
	    请输入名字:<input type="text" name="username" value=""><br>
	    请选择文件:<input type="file" name="testFile" value=""><br>
	    <input type="submit" value="确定">
	</form>
</body>
web.xml
<servlet>
        <servlet-name>saveFile</servlet-name>
        <servlet-class>controller.SaveFileController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>saveFile</servlet-name>
        <url-pattern>/saveFile</url-pattern>
    </servlet-mapping>
 
public class SaveFileController extends HttpServlet {
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	        try {
	 
	            //创建一个工厂
	            DiskFileItemFactory factory = new DiskFileItemFactory();
	            //创建一个ServletFileUpload对象(构造方法中需要factory帮忙)
	            ServletFileUpload upload = new ServletFileUpload(factory);
	            //通过upload解析request对象(解析目的是因为请求携带的信息都在request对象中)
	            //上传的进度
		        upload.setProgressListener(new ProgressListener(){
	                public void update(long l, long l1, int i) {
	                    //  第一个参数表示 已经上传的字节个数   4096个字节
	                    //  第二个参数表示 上传文件的总字节数
	                    //  第三个参数表示 正在上传第几个组件
	                    System.out.println("正在上传第"+i+"个组件,已经上传"+((((double)l/(double)l1)*100))+"%");
	                    try {
	                        Thread.sleep(300);
	                    } catch (InterruptedException e) {
	                        e.printStackTrace();
	                    }
	                }
	            });
	            List<FileItem> itemList = upload.parseRequest(request);
	            //将list中所有的item元素遍历
	            for(FileItem item : itemList){
	                if(item.isFormField()){//是一个普通的组件
	                    //注意不能使用request.getParameter("key");来获取   request对象已经被解析了
	//                    System.out.println(request.getParameter("username"));
	                    String key = item.getFieldName();//获取组件的name属性
	                    String value = item.getString("UTF-8");//使用重载方法传递处理字符集的key
	                    System.out.println(key+"--"+value);
	                }else{//是一个file文件
	              
	                    String key = item.getFieldName();//获取组件的name属性
	                    String realFileName= item.getName();//获取上传文件的真实文件名
 
	                    //如果传递的文件真实中文名有问题
	                    //request.setCharacterEncoding("UTF-8");
	                    //upload.setHeaderEncoding("UTF-8");
	          
	                    //当前工程下的真是路径
	                    //D:\ideaProject\TestupLoad\out\artifacts\TestupLoad_war_exploded\ 
	                    String serverCurrPath = this.getServletContext().getRealPath("/");
	                    //保存到服务器中
	                    item.write(serverCurrPath +realFileName));
	
	                   
	                }
	            }
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	  }
}

上传文件中重要的类

DiskFileItemFactory

常用方法解释
setSizeThreshold(long)设置缓冲区大小
setRepository(new File(“”))设置缓冲区位置

DiskFileItemFactory 部分代码:

public class DiskFileItemFactory implements FileItemFactory {
	public DiskFileItemFactory(int sizeThreshold, File repository) {
	        this.sizeThreshold = 10240;  //缓冲区默认大小10240
	        this.defaultCharset = "ISO-8859-1"; //默认字符
	        this.sizeThreshold = sizeThreshold;
	        this.repository = repository;
	}
    public void setRepository(File repository) {
        this.repository = repository;
    }

    public int getSizeThreshold() {
        return this.sizeThreshold;
    }

    public void setSizeThreshold(int sizeThreshold) {
        this.sizeThreshold = sizeThreshold;
    }
    public void setDefaultCharset(String pCharset) {
        this.defaultCharset = pCharset;
    }

}	 

ServletFileUpload

常用方法解释
parseRequest(request)解析request对象
setFileSizeMax(long)单个文件上传大小
setSizeMax(long)设置上传总文件大小
setRepository(new File(“”))设置缓冲区位置
setHeaderEncoding(“UTF-8”)处理传递的文件真实中文名

问题:为什么表单必须要用POST请求?

ServletFileUpload类中设置了不可变属性来控制
private static final String POST_METHOD = “POST”;

常用的属性和方法都是从FileUploadBase抽象方法中继承的使用了缺省适配器模式
ServletFileUpload extends FileUpload
FileUpload extends FileUploadBase

FileUploadBase部分代码:

public abstract class FileUploadBase {
    public static final String CONTENT_TYPE = "Content-type";
    public static final String CONTENT_DISPOSITION = "Content-disposition";
    public static final String CONTENT_LENGTH = "Content-length";
    public static final String FORM_DATA = "form-data";
    public static final String ATTACHMENT = "attachment";
    public static final String MULTIPART = "multipart/";
    public static final String MULTIPART_FORM_DATA = "multipart/form-data";
    public static final String MULTIPART_MIXED = "multipart/mixed";
    /** @deprecated */
    @Deprecated
    public static final int MAX_HEADER_SIZE = 1024;
    private long sizeMax = -1L;
    private long fileSizeMax = -1L;
    private String headerEncoding;
    private ProgressListener listener;

    public FileUploadBase() {
    }
    public long getSizeMax() {
        return this.sizeMax;
    }

    public void setSizeMax(long sizeMax) {
        this.sizeMax = sizeMax;
    }

    public long getFileSizeMax() {
        return this.fileSizeMax;
    }

    public void setFileSizeMax(long fileSizeMax) {
        this.fileSizeMax = fileSizeMax;
    }

    public String getHeaderEncoding() {
        return this.headerEncoding;
    }

    public void setHeaderEncoding(String encoding) {
        this.headerEncoding = encoding;
    }
    public List<FileItem> parseRequest(HttpServletRequest req) throws FileUploadException {
        return this.parseRequest((RequestContext)(new ServletRequestContext(req)));
    }

   protected String getFieldName(FileItemHeaders headers) {
        return this.getFieldName(headers.getHeader("Content-disposition"));
    }
}

FileItem

常用方法解释
isFormField()是一个普通组件
getFieldName()获取组件的name属性
getString(“UTF-8”)获取组件的value属性

文件下载



public class DownLoadController extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取请求传递的文件名(需要下载的文件)
        String realPathPre = this.getServletContext().getRealPath("/");
        fileName = realPathPre + fileName;
        //2.通过fileName找到一个服务器中的真实文件(固定位置 当前工程内部)
        //      找到文件需要一个输入流读取文件中的内容
        InputStream inputStream = new FileInputStream(fileName);
        //3.如果文件名含有中文,通过以下方式处理
        fileName = URLEncoder.encode(fileName,"UTF-8");
        //4.设置响应的contentType
        //  ServletFileUpload--->FileUpload--->FileUploadBase
        //  调用静态常量进行拼接字符串
        response.setContentType("application/x-msdownload");
        response.setHeader("Content-disposition","attachment;filename="+fileName);
        //5.将内容响应回浏览器
        OutputStream outputStream = response.getOutputStream();
        byte[] b = new byte[1024];
        int length = inputStream.read(b);
        while(length!=-1){
            outputStream.write(b,0,length);
            outputStream.flush();
            length = inputStream.read(b);
        }
    }
}

Filter

作用:请求进行拦截和响应进行处理(一般不会去做响应处理)。
常见场景:权限检查,日记操作、拦截请求、过滤操作、对请求字符设置编码

Filter过滤器基本使用

  1. 自己定义一个类,继承HttpFilter
  2. 重写方法,doFilter方法
  3. 在web.xm配置filter信息

设计一个登录页面,测试的Filter

public class TestFIlterOneController extends HttpFilter {

    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {


        System.out.println("doFilter开始执行了");

        chain.doFilter(request,response);

        System.out.println("doFilter结束了");
    }
}

登录界面

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <form action="login" method="post">
            请输入账号:<input type="text" name="aname" value=""><br>
            请输入密码:<input type="password" name="apassword" value=""><br>
            <input type="submit" value="登录">
        </form>
    </body>
</html>

测试的Controller


public class TestOneLoginController extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.告诉request才用如下的字符集进行组合
        request.setCharacterEncoding("UTF-8");//get请求也没有影响
        //1.获取请求发送过来的账号和密码
        String aname = request.getParameter("aname");
        String apassword = request.getParameter("apassword");
        System.out.println("接受到了浏览器发送过来的请求信息:"+aname+"--"+apassword);
        //2.负责处理一个业务判断---调用业务层的登录方法
        AtmService service = MySpring.getBean("service.AtmService");
        String result = service.login(aname,apassword);
        System.out.println("业务逻辑的判定结果最终为:"+result);
        //3.根据业务方法的执行结果  给予响应
        if(result.equals("登录成功")){
              

            //转发
            RequestDispatcher rd = request.getRequestDispatcher("welcome.jsp");//告知
            rd.forward(request,response);//真正转发走啦
        }else{
            //控制响应信息是重新登录
            request.getRequestDispatcher("index.html").forward(request,response);
        }
    }
 

欢迎界面

welcome.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>welcome</title>
</head>
<body>

     Hello!!!
</body>
</html>

web.xml配置文件

    <filter>
        <filter-name>testOne</filter-name>
        <filter-class>filter.TestFIlterOneController</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>testOne</filter-name>
        <!-- 全部拦截-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- 登录 -->
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>controller.TestOneLoginController</servlet-class>
    
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

服务器打印:
在这里插入图片描述

简单总结:filter会在拦截servlet前做一些事情,也会在servlet执行完毕后做一些事情。
filter也可以获取到HttpServletRequest request 和HttpServletResponse response对象,所以filter也可以做servlet事情,如请求转发、请求重定向等等 ,filter具有servlet的绝大部分的性质和作用 filter≈servlet,但实际中filter只做拦截作用

上面代码简易流程图
在这里插入图片描述

Filter生命周期

   public class XXXFilter extends HttpFilter {
	    //初始化  服务器启动工程的时候就会初始化执行下面init方法
	    public void init(FilterConfig config) throws ServletException {
	     
	    }
	
	    //销毁  工程被停止,Filter就会被销毁
	    public void destroy() {
	        
	    }
	
	    //执行 拦截到请求,就会执行doFilter方法
	    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
	    }

}

FilterConfig config

Filter 过滤器的配置文件类。
获取在Filter 中 wen.xml 配置的 init-param初始化参数
获取ServletContext application全局上下文对象

Filter管理机制

可以类比servlet的管理机制进行学习

过滤器继承与实现关系部分代码

//普通类直接继承HttpFilter
public class XXXFilter extends HttpFilter {}
//将无协议的参数强制转化成Http协议的参数
public abstract class HttpFilter extends GenericFilter {
//过滤器Fitler具体实现 ,使用到了缺省适配器
public abstract class GenericFilter implements Filter, FilterConfig, Serializable {
//真正的Filter(过滤器接口)
public interface Filter {
//Filter配置类
public interface FilterConfig {
    String getFilterName();//请求名字

    ServletContext getServletContext();//全局上下文

    String getInitParameter(String var1);//初始化的key

    Enumeration<String> getInitParameterNames();//初始化的keys
}
//序列号
public interface Serializable {
		default void init(FilterConfig filterConfig) throws ServletException {
	    }
	
	    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
	
	    default void destroy() {
	    }
}

filter对象是一个单例的
filter对象的单例的 ,采用生命周期托管的方式实现的
filter对象是一个立即加载的方式 不能通过配置load-on-startup来进行修改

过滤器链

多个filter使用了责任链设计模式来管理

index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>FILTER</title>
  </head>
  <body>
    <form action="login" method="post">
      <input type="text" name="aname" value=""><br>
      <input type="password" name="apassword" value=""><br>
      <input type="submit" value="login">
    </form>
  </body>
</html>

//请求名  one
public class FilterOne extends HttpFilter {

    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("我是FilterOne放行之前的事情,执行啦");
        chain.doFilter(request,response);
        System.out.println("我是FilterOne放行之后的事情,结束啦");
    }
}
//请求名  two
public class FilterTwo extends HttpFilter {

    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("我是FilterTwo放行之前的事情,我执行啦");
        chain.doFilter(request,response);
        System.out.println("我是FilterTwo放行之后的事情,结束啦");

    }
}
//请求名  three
public class FilterThree extends HttpFilter {

    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("我是FilterThree放行之前的事情,我执行啦");
        chain.doFilter(request,response);
        System.out.println("我是FilterThree放行之后的事情,结束啦");

    }
}
    <!--filter标签用于配置第一个Filter过滤器-->
    <filter>
        <!--为filter 起别名-->
        <filter-name>three</filter-name>
        <!--配置filter 全类名-->
        <filter-class>filter.FilterThree</filter-class>
    </filter>
    <!--配置 filter 拦截路径-->
    <filter-mapping>
        <!--拦截filter的名字  -->
        <filter-name>three</filter-name>
        <!--拦截工程下全部路径
        http://ip:port/工程路径/
        -->
        
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--filter标签用于配置第二个Filter过滤器-->
    <filter>
        <filter-name>one</filter-name>
        <filter-class>filter.FilterOne</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>one</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--filter标签用于配置第三个Filter过滤器-->
    <filter>
        <filter-name>two</filter-name>
        <filter-class>filter.FilterTwo</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>two</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>



    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>controller.LoginController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

filter配置的顺序是:three one two

web.xml中配置filter 的顺序(默认)就是执行顺序 <下面看结果就可以知道了>

服务器段打印结果:

先执行 FilterThree再 执行FilterOne,然后执行FilterTwo过滤器,最后执行目标对象
类似于对象先入栈后弹栈

在这里插入图片描述默认filter执行的顺序和配置文件读写的顺序一致

简易流程图
在这里插入图片描述

Filter 的拦截路径

精确匹配
表示请求地址必须为:
http://ip:port/工程路径/login
http://ip:port/工程路径/welcome.jsp

    <filter-mapping>
        <filter-name>testOne</filter-name>
        <url-pattern>/login</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>testOne</filter-name>
        <url-pattern>/welcome.jsp</url-pattern>
    </filter-mapping>

目录匹配
表示请求地址必须为:http://ip:port/工程路径/jsp/*

    <filter-mapping>
        <filter-name>testTwo</filter-name>
        <url-pattern>/jsp/*</url-pattern>
    </filter-mapping>

后缀名匹配

    <filter-mapping>
        <filter-name>testThree</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>testThree</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>testThree</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>

监听器Listener

作用:

  1. 监听域对象产生和销毁的
  2. 监听域对象存值、修改 、删除
可监听域对象含义
javax.servlet.http.HttpServletRequest request客户端一次请求
javax.servlet.http.HttpSession session = null会话
final javax.servlet.ServletContext applicationJSP当前上下文页面

监听器类需要实现的接口

接口含义
ServletRequestListener监听request对象生命周期
ServletRequestAttributeListener监听request对象存值、修改 、删除
HttpSessionListener监听session对象生命周期
HttpSessionAttributeListener监听session对象存值、修改 、删除
ServletContextListener监听application对象生命周期
ServletContextAttributeListener监听application对象存值、修改 、删除

servlet规范

监听request*对象

普通监听器类需要实现ServletRequestListener和ServletRequestAttributeListener接口并重写接口中的方法


public class TestRequestListener implements ServletRequestListener, ServletRequestAttributeListener {

    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("request对象销毁啦");
    }

    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("request对象创建啦");
    }

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

    public void attributeAdded(ServletRequestAttributeEvent srae) {
        System.out.println("request添加了数据");
    }

    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        System.out.println("request删除了数据");
    }

    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        System.out.println("request修改了数据");
    }

}

添加监听器配置文件


    <listener>
        <listener-class>listener.TestRequestListener</listener-class>
    </listener>
request对象方法含义
setAttribute()存值或修改值
removeAttribute()删除值

request对象创建,当浏览器访问服务器的时候,就会创建request对象并触发监听器执行requestInitialized方法

request对象销毁 ,当完成一次请求的时候(服务器回写到浏览器),request就会被销毁并触发监听器执行requestDestroyed方法

request对象存储值

//会触发监听request对象的监听器,触发器执行attributeAdded方法监听request对象添加值
request.setAttribute("xxx",xxx);

session对象修改值

//会触发监听request对象的监听器,触发器执行attributeReplaced方法监听request对象修改值
request.setAttribute("xxx",sss);

request对象删除值

//会触发监听request对象的监听器,触发器执行attributeRemoved方法监听request对象删除值
request.removeAttribute("xxx");

监听session*对象

普通监听器类需要实现HttpSessionListener和HttpSessionAttributeListener 接口并重写接口中的方法

public class TestSessionListener implements HttpSessionListener, HttpSessionAttributeListener {

    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("session对象创建啦");
    }
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("session对象销毁啦");
    }
    //----------------------------------------------------
    public void attributeAdded(HttpSessionBindingEvent se) {
        System.out.println("session存储了值");
    }
    public void attributeRemoved(HttpSessionBindingEvent se) {
        System.out.println("session删除了值");
    }
    public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("session修改了值");
    }
}

添加监听器配置文件

    <listener>
        <listener-class>listener.TestSessionListener</listener-class>
    </listener>
    
session对象方法含义
setAttribute()存值或修改值
removeAttribute()删除值
invalidate()session对象销毁

session对象的创建,服务器创建一个session对象,并会给定一个唯一的sesionId

//会触发监听session对象的监听器,触发器执行sessionCreated方法监听创建session对象

HttpSession session = request.getSession();  

session对象的销毁

//会触发监听session对象的监听器,触发器执行sessionDestroyed方法监听销毁session对象
session.invalidate();

session对象存储值

//会触发监听session对象的监听器,触发器执行attributeAdded方法监听session对象添加值
session.setAttribute("xxx",xxx);

session对象修改值

//会触发监听session对象的监听器,触发器执行attributeReplaced方法监听session对象修改值
session.setAttribute("xxx",sss);

session对象删除值

//会触发监听session对象的监听器,触发器执行attributeRemoved方法监听session对象删除值
session.removeAttribute("xxx");

监听application对象

普通监听器类需要实现ServletContextListener和ServletContextAttributeListener接口并重写接口中的方法


public class TestApplicationLinstener implements ServletContextListener, ServletContextAttributeListener {

    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("application创建了");
    }

    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("application销毁了");
    }


    //--------------------------------------------------------------
    public void attributeAdded(ServletContextAttributeEvent scae) {
        System.out.println("application添加值");
    }

    public void attributeRemoved(ServletContextAttributeEvent scae) {
        System.out.println("application删除值");
    }

    public void attributeReplaced(ServletContextAttributeEvent scae) {
        System.out.println("application修改值");
    }

}

添加监听器配置文件

    <listener>
        <listener-class>listener.TestApplicationLinstener</listener-class>
    </listener>

application对象的创建,程序部署完毕后服务器就会创建appliction对象并且是单例的

application对象的销毁,关闭服务器的时候application会被销毁

application对象存储值

//会触发监听application对象的监听器,触发器执行attributeAdded方法监听application对象添加值
getServletContext().setAttribute("xxx",xxx);

application对象修改值

//会触发监听application对象的监听器,触发器执行attributeReplaced方法监听application对象修改值
getServletContext().setAttribute("xxx",sss);

application对象删除值

//会触发监听application对象的监听器,触发器执行attributeReplaced方法监听application对象删除值
getServletContext().removeAttribute("xxx");

Session管理机制

  1. 服务器里面有个管理者来管理所有的session对象
  2. 服务器创建一个session对象并服务器会分配一个唯一的sessionId作为标识(是一个16进制数,长度位32),服务器会将(name为JSESSIONID的固定值,value为session对象的ID)创建的cookie发送给浏览器端。cookie可以存储在浏览器端的(本地文件中,一般会设置过期时间),下一次请求的时候请求的时候会携带者cookie(可以有多个)访问服务器

下面是模拟(猜想)服务器管理session对象代码

	public class SessionManager{//负责管理session   
		//集合管理所有session对象,键位SessionId
		private static Map<SessionId,session> sessionMap = new HashMap();
		public static HttpSession getSession(SessionId){
			return sessionMap.get(SessionId);
		}
	}
 
public class HttpSession{ 
		//集合存储session添加的参数
		private Map<String,Object> attributeMap = new HashMap();
		
		public void setAttribute(String key,Object value){
			attributeMap.put(key,value);
		}
		public Object getAttribute(String key){
			return attributeMap.get(key);
		}
		public void removeAttribute(String key){
            attributeMap.remove(key);
        }
	}

使用session,从SessionManageer中获取

	HttpSession session = SessionManager.getSession("标识");
	session.setAttribute("key",objcet);//添加参数
	Object value = session.getAttribute("key");//获取参数
	session.removeAttribute("key");

Cookie

中文名:储存在用户本地终端上的数据
作用:辨别用户身份
储存:如果cookie设置了有效值,cookie数据会保存在本地客户端
生命周期:只要不关闭浏览器,cookie变量就会一直有效
安全性:使用cookie被攻击的可能性比较大,安全性较低

测试Cookie

index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <%
    //添加一个cookie
    Cookie testCookie = new Cookie("TestCookie","123879798432abcdef");
    response.addCookie(testCookie);
  %>
  <body>
    <a href="test?uname=CookieTest">测试Cookie</a>
  </body>
</html>

/test
public class TestCookieController extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String uname= request.getParameter("uname");
        System.out.println("参数:"+uname);
        //获取cookie
        Cookie[] cookies = request.getCookies();
        for(Cookie cookie : cookies){
            String name = cookie.getName();//获取cookie的key
            String value = cookie.getValue();//获取cookie的value
            System.out.println(name+"-------"+value);
        }
        request.getRequestDispatcher("welcome.jsp").forward(request,response);

    }
}

第一次访问服务器会产生一个JESSSIONID的cookie,还有我们自己添加的Cookie一起写回浏览器
在这里插入图片描述

服务器打印
在这里插入图片描述

cookie对象常用方法

方法含义对应浏览器字段
getName()获取cookie的keyName
getValue()获取cookie的valueValue
setMaxAge(int )设置cookie的失效时间,以秒为单位的void
setDomain(String pattern)决定Cookie在哪个域是有效的,参数必须以点(“.”)开始Domain
setPath(String uri)Path是Cookie的有效路径,需要使用符号“/”结尾Path
setMaxAge(int expiry)Expires和Max-age均为Cookie的有效期,若Max-age设置为0,则立刻失效,设置为负数,则在页面关闭时失效Expires/Max-age
setSecure(boolean flag)Secure为Cookie的安全属性Expires/Secure

简易流程图
简易流程图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以为您解答关于 JSP 基本语法登录程序的问题。 首先,您需要创建一个 JSP 文件,接着在该文件中编写以下代码: ``` <html> <head> <title>登录页面</title> </head> <body> <h2>用户登录</h2> <form action="login.jsp" method="post"> <table> <tr> <td>用户名:</td> <td><input type="text" name="username"/></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="password"/></td> </tr> <tr> <td colspan="2"><input type="submit" value="登录"/></td> </tr> </table> </form> </body> </html> ``` 这段代码会生成一个简单的登录表单,其中包括用户名和密码输入框以及一个登录按钮。接着,您需要创建一个名为 "login.jsp" 的 JSP 文件,用于处理用户提交的表单数据。 在 "login.jsp" 文件中,您可以编写以下代码: ``` <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% String username = request.getParameter("username"); String password = request.getParameter("password"); if(username.equals("admin") && password.equals("admin123")) { out.println("登录成功!"); } else { out.println("用户名或密码错误!"); } %> ``` 在该代码中,首先使用 request.getParameter() 方法获取用户在登录表单中输入的用户名和密码。然后通过一个 if-else 语句判断用户名和密码是否正确,正确则输出 "登录成功!",不正确则输出 "用户名或密码错误!"。 希望这个简单的 JSP 基本语法登录程序能够帮助到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小江||小廖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值