一、JSP:Java Server Page是一种运行在服务器端的Java页面

 1、使用能够JSP实现输出:

  1-1:JSP对象输出显示

   out.prin(); 向页面输出显示

   out.println(); 向页面输出显示,在末尾加个空格

   ★换行只能是<br/>

  1-2:JSP注释

   HTML注释:<!-- HTML注释 -->,显示在源代码

   JSP注释:<%-- JSP注释 --%>,隐藏在源代码

   JSP脚本注释:<% //JSP单行注释 %>、<% /**JSP多行注释*/ %>,隐藏在源代码

  1-3:转义字符

   \" \":引号引起来

  1-4:JSP中声明和使用变量:<%String 变量名="内容";>

  1-5:用变量实现页面输入:<%=变量名 %>

  1-6:使用<%@page %>导包

  1-7:<%%>:局部变量

     <%!%>:全局变量

  1-8:Web程序常见的错误

   1>404错误——找不到访问的页面或资源

    A:运行时,URL输入有误

    B:将页面放在WEB-INF下

    C:外部启动Tomcat,未部署项目

   2>500错误——JSP页面代码有误

   3>页面无法显示:未启动Tomcat

 2、内置对象:JSP已经准备好的,可以直接使用的对象

  2-1:请求对象:request(客户端发送请求)

  2-2:输出对象:out

  2-3:响应对象:response(服务器接受请求——200状态码)

  2-4:应用程序对象:application

  2-5:会话对象:session

  2-6:页面上下文对象:pageContext

  2-7:页面对象:page

  2-8:配置对象:config

  2-9:异常对象:exception

 3、request对象常用方法

  3-1:String getParameter(String name):根据表单组件名称获取提交数据

  3-2:String[] getParameterValues(String name):获取表单组件对应多个值时的请求数据

  3-3:void setCharacterEncoding(String charset):指定每个请求的编码

  3-4:RequestDispatcher getRequestDispatcher(String path):返回一个RequestDispatcher对象,该对象的forward()方法用于转发请求

 4、页面间的数据传递

  4-1:使用属性存取数据

   1>setAttribute():在请求中保存属性

    public void setAttribute(String name,Object o);

   2>getAttribute():在请求中获取属性

    public Object getAttribute(String name);

  ★在读取属性中保存的数据时,必须将数据转换成其最初的类型:String mess=(String)request.getAttribute("mess");

   在使用属性值的时候要做非空判断,否则会出现空指针异常

  4-2:转发与重定向

   1>转发:是服务器行为——RequestDispatcher对象、forward()方法(1个请求,返回200状态码,失败时返回页面)

    语法:A:request.getRequestDispatcher("url").forward(request,response);

       B、<jsp:forward page="url" />

   2>重定向:是客户端行为——将用户请求重新定位到一个新的URL(2个请求,第一个返回302状态码,第二个返回200状态码,成功时转到另一个页面)

    语法:response.sendRedirect("url");

 5、Session会话对象:数据保存在服务器

  5-1:Session保存和读取数据的方法

   使用Session保存数据:session.setAttribute(String key,Object value)

   从Session中读取数据:(Object)session.getAttribute(String key);

  5-2:Session对象常用方法(单用户)

   getId():获取sessionId

   invalidate():设置session对象失效

   setMaxInactiveInterval(int interval(单位:秒)):设置session的有效期

   removeAttribute(String key):移除session中的属性

  5-3:Session的有效期

   在Tomcat服务器的web.xml文件中<web-app>和</web-app>之间添加:

      <session-config><session-timeout>分钟</session-timeout></session-config>

 6、Cookie:以文件方法保存数据的,保存在客户端 

  6-1:Cookie的应用(在JSP中使用Cookie)

   1>创建Cookie对象

    Cookie cookieName=new Cookie(String key,Object value);

   2>写入Cookie

    response.addCookie(cookieName);

   3>读取Cookie

    Cookie[] cookies=request.getCookies();

  6-2:Cookie常用方法

   setValue(String value):创建Cookie后,为Cookie进行赋值

   getName():获取Cookie的名称

   getValue():获取Cookie的值

   getMaxAge():获取Cookie的有效期,以秒为单位

   setMaxAge(int expiry):设置Cookie的有效期,以秒为单位

 6、application:实现统计页面的访问次数(多用户共享)

   setAttribute(String key,Object value):以key-value的形式保存对象值

   getAttribute(String key):通过key获取对象值

 7、request、session、application三个对象对比

  相同点:都可以存储属性

  不同点:request中存储的数据仅在一个请求中可用

      session中存储的数据在一个会话的有效期内可用

      application中存储的数据在整个Web项目中可用

二、JDBC和JavaBean操作数据库

 1、JDBC是一中Java数据库连接技术,能实现Java程序对各种数据库的访问。

 2、JDBC访问数据库的五步骤:

  2-1:加载驱动(找到jar包→com.msyql.jdbc→Drivere.class)

    Class.forName("JDBC驱动类的名称");

   ★mysql:com.mysql.jdbc.Driver

    oracle:oracle.jdbc.driver.OracleDriver

  2-2:使用DriverManager类获取数据库的连接

    Connection connection=DriverManager.getConnection(数据库URL,数据用户名,密码);

   ★mysql 的URL:jdbc:mysql://localhost:3306/数据库名

    oracle的URL:jdbc:oracle:thin@localhost:1521:数据库名

  2-3:获取Statement对象,执行sql语句

   1>定义sql语句:String sql = "select * from 表名";

   2>先创建Statement接口:Statement st = connection.createStatement();

   3>获取结果对象:ResultSet rs = st.executeQuery(sql);

  2-4:处理结果

   while (rs.next()){ }

  2-5:释放资源

    rs.close();
    st.close();
    connection.close();

 3、设置配置文件

  3-1:创建database.properties文件

  3-2:构建数据库访问的工具类,来读取配置文件

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

//读取配置文件的工具类-单例模式
public class ConfigManager {
	// 读取配置properties.load(inputStream)
	private static ConfigManager configManager;
	private static Properties properties;

	// 在构造工具类时,进行配置文件的读取
	private ConfigManager() {
		String configFile = "database.properties";
		properties = new Properties();
		InputStream is = ConfigManager.class.getClassLoader()
				.getResourceAsStream(configFile);
		try {
			// 读取配置文件
			properties.load(is);
			is.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// 通过单例模式设置实例化的个数
	public static ConfigManager getInstance() {
		if (configManager == null) {
			configManager = new ConfigManager();
		}
		return configManager;
	}

	// 通过key获取对应的value
	public String getString(String key) {
		return properties.getProperty(key);
	}
}

 4、Statement与PreparedStatement区别

  4-1:Statement由方法createStatement()创建,该对象用于发送简单的sql语句


   sql语句用“?”作为数据占位符、使用setXxx()方法设置数据

 5、连接池与数据源

  5-1:连接池、连接、数据源的关系

   1>连接池:里面放着连接对象,并管理连接对象的(连接对象是保持与数据库连接的)

   2>数据源DataSource:用来获取连接对象,连接数据库(直接从数据源中获取连接)

   3>如何获取DataSource:由Tomcat容器创建,在程序里使用JNDI来获取

   4>通过数据源创建的连接对象被统一的放入到连接池中进行管理

  5-2:在Toacat中配置数据源步骤:

   1>Tomcat中加入数据库驱动文件

   2>配置Tomcat的conf/context.xml

<span >	</span><Resource name="jdbc/news" 
              auth="Container"  type="javax.sql.DataSource"  maxActive="100" 
              maxIdle="30" maxWait="10000" username="root"  password="" 
              driverClassName="com.mysql.jdbc.Driver" 
              url="jdbc:mysql://localhost:3306/news"/>

    ★name:数据源名称,通常采取 jdbc/数据库名

     auth:连接池的归属权

     type:类型

     maxActive:并发连接的最大活动数。 0:无限制

     maxIdle:连接池中空闲的连接的个数

     maxWait:等待连接的最大连接的时间 -1:无限等待下去

     username、password:数据库用户名、密码

     driverClassName:驱动程序名称

     url:访问数据库路径

   3>使用JNDI获取连接对象

     A、 初始化上下文
      Context ctx = new InitialContext();
     B、获取与逻辑名相关联的数据源对象
      DataSource ds = (DataSource) ctx.lookup("java:comp/env/数据源名称");
      connection = ds.getConnection();

   4>调用数据源得到连接

     需要实例化获取数据源方法所在类,然后调用获取数据源的方法就可以得到一个Connection对象

 6、JavaBean:是一个java类。封装数据、业务逻辑

   DAO层:对数据进行增删改查操作,访问数据接口

   util层:读取配置文件的工具类

   service层:业务层,负责业务逻辑,对dao的方法进行封装调用,主要负责和业务逻辑相关的操作

 7、JSP标签

  7-1:JSP动作标签

   1><jsp:useBean>:在JSP中创建一个JavaBean的实例,并指定它的名称和作用范围,可发挥Java组件重用的优势

     语法:<jsp:useBean id="name" class="package.class" scope="scope">

       id:JavaBean的引用名

       class:JavaBean类的完整限定名

       scope:JavaBean的作用范围,默认page

  7-2:JSP页面包含:把指定文件插入正在生成的页面

   1>动态包含:先执行页面代码,再将页面包含,即将一个页面的运行结果包含到另一个页面上

     语法:<jsp:include page="相对URL地址" />

   2>静态包含:先将页面包含,再执行页面代码,即将一个页面的代码复制到另一个页面上(适用于公共的CSS、JS代码)

     语法:<%@include file="url" %>

  7-3:JSP页面跳转

   <jsp:forward page="URL" />

三、第三方控件与分页查询

 1、第三方控件:commons-fileupload(Java的)

  1-1:FileItem接口的常用方法

   1>getFieldName():返回表单字段的name属性值

   2>isFormField():判断FileItem封装的数据是属于普通表单还是文件表单 true:普通表单 false:文件表单

   3>getName():返回上传文件字段中的文件名

   4>write(File file):将FileItem对象中的内容保存到指定文件中

   5>getString(String encoding):按照指定编码格式将内容转换成字符串返回

  1-2:FileItemFactory接口与DiskFileItemFactory类

   1>FileItemFactory是一个接口,是用于构建FileItem实例的工厂

   2>DiskFileItemFactory类是FileItemFactory接口的实现类,在使用中,可以构造一个FileItemFactory接口类型的实例:

      FileItemFactory factory=new DiskFileItemFactory();

  1-3:ServleFileUpload类:用于处理文件上传的核心类,

   1>作用:以List形式返回每一个被封装成FileItem类型的表单元素集合

   2>构造语法:public ServleFileUpload(FileItemFactory fileitemfactory)

   3>常用方法

    A、isMultpartContent(HttpServleRequest request):静态方法,用于判断请求数据中的内容是否是multipart/form-data类型

    B、parseRequest(HttpServleRequest request):将请求数据中的每一个字段,单独封装成FileItem对象,并以集合方法返回

 2、使用commons-fileupload组件实现图片上传步骤

  2-1:获取组件

   commons-fileupload-1.2.2.jar、commons-io-2.4.jar

  2-2:修改页面

   1>修改表单:method="post" enctype="multipart/form-data"

   2>设置上传文件的标签:<input type="file" name="picPath" value="" />

  2-3:在JSP中实现文件上传

   1>判断表单提交内容形式

    boolean isMultiPart = ServletFileUpload.isMultipartContent(request);

    if (isMultiPart){ 处理文件上传}

   2>创建文件谁能够穿所有的API实例

创建FileItemFactory实例:FileItemFactory factory = new DiskFileItemFactory();

创建文件上传的核心类ServletFileUpload:ServletFileUpload upload = new ServletFileUpload(factory);

   3>解析request请求

    List<FileItem> items = upload.parseRequest(request);

   4>循环遍历集合中的数据

//获取迭代器 
	Iterator<FileItem> iters = items.iterator();
	while (iters.hasNext()) {
		FileItem item = iters.next();
		//判断fileItem是文本域还是文件域
		if (item.isFormField()) {//若是普通的文本表单控件
			//获取文本域name的值
			String fieldName = item.getFieldName();
			if (fieldName.equals("categoryId")) {
				news.setCategoryId(Integer.parseInt(item.getString()));
			} else if (fieldName.equals("title")) {
				news.setTitle(item.getString("utf-8")); //获取文本域value的值
			}。。。。。。
		} else {//若是文件表单控件
			//上传文件名称(全路径)
			String fileName = item.getName();
			//userId+系统时间+随机数.doc
			if (fileName != null && !fileName.equals("")) {
				File fullFile = new File(fileName);
				//把文件上传到指定的目录下
				File saveFile = new File(uploadPath,fullFile.getName());
				//上传操作
				item.write(saveFile);
				news.setPicPath(fullFile.getName());
			}
		}	
	}

 3、CKEditor:网页中实现所见所得的编辑器(JS的)

  3-1:使用步骤

   1>下载CKEditor

   2>解压到项目到WebRoot中

   3>在页面中加入CKEditor:<script src="<%=request.getContextPath() %>/ckeditor/ckeditor.js" ></script>

   4>修改页面的<textarea>的属性:  添加"class=ckeditor"

   5>使用→提交

 4、分页查询

  4-1:分页后台实现

   1>确定显示数据总数量:

     sql语句:select count(*) as count from 表名; 

     通过JDBC进行SQL语句执行:Object[] params = {};

                   ResultSet rs = this.executeSQL(sql, params);

     获取总记录数:int count = rs.getInt("count");

   2>计算显示页数

package com.util;

public class PageSupport {

	//总页数
	private int totalPageCount = 1;
	
	//总记录数
	private int totalCount = 0;
	
	//当前页面
	private int currentPageNo = 1;
	
	//页面容量(每页显示多少条)
	private int pageSize = 0 ;

	public int getTotalPageCount() {
		return totalPageCount;
	}

	public void setTotalPageCount(int totalPageCount) {
		this.totalPageCount = totalPageCount;
	}

	public int getTotalCount() {
		return totalCount;
	}

	public void setTotalCount(int totalCount) {
		if(totalCount > 0){
			this.totalCount = totalCount;
			//设置总页数
			this.setTotalPageCountByRs();
		}
	}

	public int getCurrentPageNo() {
		return currentPageNo;
	}

	public void setCurrentPageNo(int currentPageNo) {
		if(currentPageNo > 0){
			this.currentPageNo = currentPageNo;
		}
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		if(pageSize > 0 ){
			this.pageSize = pageSize;
		}
	}

	//设置总页数
	public void setTotalPageCountByRs(){
		if(this.totalCount % this.pageSize == 0){
			this.totalPageCount = this.totalCount / this.pageSize;
		}else if(this.totalCount % this.pageSize > 0){
			this.totalPageCount = this.totalCount / this.pageSize + 1;
		}else{
			this.totalPageCount = 0;
		}
	}
}

   3>分页查询SQL语句   

     select * from 表名 order by createDate desc limit 起始位置,下标以0开始,页面容量;

   ★总页数=总记录数 / 每页显示记录数

    总页数=总记录数 / 每页显示记录数+1

    起始记录数:(当前页码-1)× 每页显示的记录数+1;

    结束记录数:当前页码 × 每页显示的记录数

   4-2:JSP中实现分页 

   1>确定当前页

//页面容量
	int pageSize=2;
	
	//当前页面
	String pageIndex=request.getParameter("pageIndex");
	int currentPageNo = 1;;
	if(pageIndex == null){
		currentPageNo =1;
	}else{
		try{
			currentPageNo = Integer.parseInt(pageIndex);
		}catch(NumberFormatException e){
			response.sendRedirect("error.jsp");
		}
	}
	
	//总记录数
	int totalCount=newsService.getNewsCount();
	
	//总页数
	PageSupport pageSupport = new PageSupport();
	pageSupport.setPageSize(pageSize);
	pageSupport.setCurrentPageNo(currentPageNo);
	pageSupport.setTotalCount(totalCount);
	int totalPageCount =pageSupport.getTotalPageCount();

   2>页面分页设置

<%-- 
	<%if(currentPageNo > 1){ %>
		<a href="newsDetailList.jsp?pageIndex=1">首页</a>
		<a href="newsDetailList.jsp?pageIndex=<%=currentPageNo-1%>">上一页</a>
	<%}if(currentPageNo < totalPageCount) {%>
		<a href="newsDetailList.jsp?pageIndex=<%=currentPageNo+1%>">下一页</a>
		<a href="newsDetailList.jsp?pageIndex=<%=totalPageCount %>">尾页</a>  
	<%} %>
	--%>
	<%if(currentPageNo > 1){ %>
		<a href="javaScript:page_nav(document.forms[0],1)">首页</a>
		<a href="javaScript:page_nav(document.forms[0],<%=currentPageNo-1%>)">上一页</a>
	<%}if(currentPageNo < totalPageCount) {%>
		<a href="javaScript:page_nav(document.forms[0],<%=currentPageNo+1%>)">下一页</a>
		<a href="javaScript:page_nav(document.forms[0],<%=totalPageCount %>)">尾页</a>  
	<%} %>



   3>首页和尾页异常处理

//首尾页的异常控制
	if(currentPageNo <1){
		currentPageNo = 1;
	}
	if(currentPageNo > totalPageCount){
		currentPageNo = totalPageCount;
	}



四、EL和JSTL

 1、EL语法

  1-1:EL表达式:${EL表达式 }

  1-2:EL操作符

   1>操作符“.”:获取对象的属性

   2>操作符“[]”:获取对象的属性、获取集合中的对象

  ★使用EL表达式之前,要先把变量放在作用域中

  1-3:运算符(和java类似)

   empty:用于检测变量名是否为空,是否等于null

  1-4:EL功能

   1>获取JavaBean对象的属性

   2>获取数组、List、Map类型对象的元素

   3>使用运算符进行数据处理

   4>屏蔽一些常见的异常

   5>自动实现类型转换

  1-5:EL访问作用域

   1>pageScope:页面作用域→获取页面范围内的属性值

   2>requestScope:请求作用域→获取请求范围内的属性值

   3>sessionScope:会话作用域→获取会话范围内的属性值

   4>applicationScope:应用程序作用域→获取应用程序范围内的属性值

 2、JSTL:JSP标准标签库、实现JSP页面中的逻辑控制

  2-1:JSTL使用步骤

   1>添加jar包(jstl.jar和standard.jar)

   2>在JSP页面添加指令:<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

  2-2:输出标签:用来显示数据

   1><c:out>

    语法:<c:out value="输出显示的表达式" default="默认输出显示的值" escapeXml="是否对输出的内容进行转义" />

   2><c:set>

    设置变量的语法:<c:set value="变量的值" var="变量的名称" scope="变量存在的作用范围">

    设置对象属性的语法:<c:set value="变量的值" target="对象的名称" property="对象的属性名称" />

   3><c:remove>

    语法:<c:remove var="变量的名称" scope="变量存在的作用域范围" />

  2-3:迭代标签<c:forEach>:可替换for循环语句

   语法:<c:foreach var="集合中元素的名称" items="集合对象" varStatus="当前循环的状态信息">

  2-3:条件标签<c:if/>:可替代if语句

   语法:<c:if test="判断的条件" var="判断的结果" scope="判断结果存放的作用域">

  2-4:超链接标签<c:url/>

   语法:<c:url value="url">

  2-5:超链接的参数标签<c:param>

   语法:<c:param name="参数名称" value="参数的值">

  2-6:导入标签<c:import/>

   语法:<c:import url="URL">

  2-7:格式化日期标签<fmt:formatDate/>

   语法:<fmt:formatDate value="时间对象" pattern="显示格式"/>

五、Servlet、过滤器、监听器

 1、Servlet:接受请求,调用JavaBean去处理请求

  1-1:Servlet API:

   1>Servlet接口:Java Servlet的基础接口,定义了Servlet必须实现的方法

   2>GenericServlet类:继承自Servlet接口,属于通用的,不依赖于协议的Servlet

   3>HttpServlet类:继承自GenericServlet类,是在其基础上扩展了HTTP协议的Servlet

   4>HttpServletRequest接口:继承自ServletRequest接口,用于获取请求数据的读取

   5>HttpServletResponse接口:继承自ServletResponse接口,用于返回响应数据

  1-2:创建Servlet

   1>实现Servlet接口

   2>继承GenericServlet类

   3>继承HttpServlet类

  1-3:Servlet中主要方法

   1>init():Servlet的初始化方法,仅仅会执行一次

   2>service():处理请求和生产响应

   3>destroy():在服务器停止并且程序中的Servlet对象不再使用的时候调用,只执行一次

   4>ServletRequest:封装客户的请求信息,作用相当于JSP内置对象request

   5>ServletResponse:创建响应信息,将处理结果返回给客户端,作用相当于JSP内置对象response

   6>ServletConfig:包含了servlet的初始化参数信息

  1-4:Servlet生命周期

   1>加载和实例化:创建Servlet的实例

   2>初始化:调用init()方法

   3>处理请求:调用servlet()方法

   4>销毁:调用destroy()方法

  1-5:Servlet的部署:修改web.xml

<servlet>
  	<servlet-name>servlet</servlet-name>  类名
  	<servlet-class>cn.web.servlet.Servlet</servlet-class>  包名+类名
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>servlet</servlet-name>  类名
  	<url-pattern>/servlet</url-pattern>  <span style="font-family: Arial, Helvetica, sans-serif;">URL路径</span>
  </servlet-mapping>


 2、过滤器(Filter):接口

  2-1:过滤器的生命周期

   1>实例化

   2>初始化:调用init()方法

   3>执行过滤:调用doFilter()方法

   4>销毁:调用destory()方法

  2-2:使用过滤器的步骤

   1>创建实现Filter接口的类

   2>在doFilter()中编写实现过滤的方法

   3>调用下一个过滤器或者web资源

   4>在web.xml文件中配置过滤器

<filter>
  	<filter-name>过滤器名</filter-name>
  	<filter-class>过滤器的完全限定名</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>过滤器名</filter-name>
  	<url-pattern>过滤器映射的web资源</url-pattern>
  </filter-mapping>

  2-3:应用场景

   1>对请求和响应进行统一处理

   2>对请求进行日志记录和审核

   3>对数据进行屏蔽和替换(上传代码时去掉空格,压缩代码)

   4>对数据进行加密和解密(认证)

六、监听器:web.xml配置(<listener><listener-class>监听器所属类的完全限定名</listener-class> </listener>)

 1、HttpSessionBindingListener监听(一对一)

  1-1:创建用户类实现HttpSessionBindingListener接口

  1-2:在valueBound()方法、valueUnbound()方法实现用户统计数量

  1-3:在web.xml中进行监听配置    

 2、HttpSessionListener监听(设置一次就可以监听所有的session)

  方法:1>sessionCreated(HttpSessionEvent event)

     2>sessionDestroyed(HttpSessionEvent event)

        执行session.invalidate()方法、session会话超时

  在web.xml配置监听器

 3、ServletContextListener监听:启动服务时获取数据源(所有用户公用一个对象《application》)

  contextInitialized、contextDestroyed

 ★ServletContextListener:在Servlet上下文对象初始化或者销毁时得到通知

  ServletContextAttributeListener:在Servlet上下文中的属性列表发生变化时得到通知

  HttpSessionListener:在Session创建后或者失效前得到通知

  HttpSessionActivationListener:实现该接口的对象,如果绑定到Session中,当Session被钝化或者激活时,Servlet容器将通知该对象

  在web.xml配置监听器