【javaWeb项目】基于网页形式,通过浏览器访问的java应用程序,就称为javaweb程序

JavaWeb前端

第一章

1、javaWeb是什么

	//基于网页形式,通过浏览器访问的java应用程序,就称为javaweb程序

2、web程序的分类

	//1、静态web程序
			特点:网页上的内容是固定不变的,不能动态加载,例如web前端
	//2、动态web程序
			特点:1、页上的内容可以根据请求的不同,动态加载数据,例如javaweb程序
				 2、动态web程序可以与用户动态交互
				 3、企业开发涉及到的应用程序主要是动态web程序

3、不同点

	1、静态web无法与用户动态加载数据,动态web程序则可以与用户交互,根据请求加载不同数据
	2、静态web程序用浏览器打开页面即可直接运行,web动态程序必须在一个特定的环境中才能运行,环境称为web容器(web服务器)

4、web服务器

web服务器用于给web程序提供一个运行环境,只要将web程序(静态或动态都可以)放入到web服务器中,就能通过网络进行访问

常用服务器:
1、tomcat/*应用最多*/
2、jboss
3、weblogic
......

Tomcat的特点:
	1、tomcat免费
	2、不需要解压缩,配置简单
	3、小巧灵活
tomacat版本
	tomacat版本需要与jdk版本对应,jdk是1.8,推荐8.5的版本

5、开发工具

idea的版本以年份为版本:
	个人推荐2018.2

6、idea使用

1、psvm----生成主函数main
2、sout----输出语句
3、alt+insert------生成get,set,tostring
	//右键 grnreate
4、选中报错位置,然后alt-----处理异常


在这里插入图片描述

get set tostring

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

推荐插件: rainbow(彩虹)

​ 作用:如果代码有很多括号,每一对括号的颜色不同

7、idea的相关设置

1、局部设置--只对当前空间有效,切换项目需要重新配置
2、全局配置---配置一次,对所有项目都有效(推荐)

8、tomcat服务器配置文件

要将项目部署到tomcat中,只需要把项目拷贝到tomcat/webapps目录下即可
在这里插入图片描述

9、启动tomcat服务器

	1、单独启动tomcat,不借助idea
	
	//找到tomcat的文件位置 进入bin 启动startup.bat  停止shutdown.bat
	注意:如果启动了tomcat就不能再次启动,否则会报错
	如果tomcat无法启动,原因是没有配置Java_HOME变量
	2、在idea中启动服务器
	
	Web项目的目录结构:
        src:存放java原文件

        web:
            存放html,jsp,css,img,js
            WEB-INF
                web.xml-------------核心配置文件
                lib-----------------放依赖,也就是jar

第二章

主要内容:jsp的基本应用 servlet的使用

1、HTML页面与jsp页面有什么区别
主要区别:
	1、HTML是静态页面,无法动态加载数据,不能与用户交互
	2、jsp的动态页面,可以加载数据,能交互
	
jsp的本质:
	jsp:Java server page
	它是由运行服务器端的java程序动态生成的页面

	jsp本质上是一个java类,只不过它是以页面的形式呈现数据
		
2、简易登录案例

如果要在jsp页面编写java代码,只需要在页面写下标记

<%
	java脚本
%>
java脚本的作用,用于在jsp页面中嵌入java代码  

重要方法

1、设置编码格式

默认情况下,表单提交数据会采用latin文编,格式为iso-8859-1,这种不支持中文

解决方案:在取值之前,设置请求(request)的编码格式

		request.setCharacterEncoding("utf-8");//在取值之前设置
		string name=request.getParameter("user");

2、获取表单数据

获取表单提交的数据
	string val=request.getParameter("表单中控件的name的名称")
				//request:请求
				//Parameter:参数

	示例:string name=request.getParameter("user");//获取表单中的用户名

		 System.out.println("姓名"+name);//输出到控制台

		 out.println("姓名"+name+"<br>");//输出到页面
				//br:换行显示

3、跳转页面

	跳转页面的方法(固定写法)
	request.getRequestDispatcher("/xxx.jsp").forward(request,response)

4、存储

存值
	将数据存储在request中,跳转页面中可以取到存储的数据
	request.setAttribte("消息的key",);
		//键:必须是字符串类型
		//值:可以为任意类型(string 对象 集合)
	
	示例:request.setAttribte("err","用户或密码错误");
	
取值
	在jsp页面中,获得存储request中的消息
	要获得存储在request中的数据,显示在页面,我们需要使用"EL表达式"
	格式:${消息的key}
	
	示例:${err}

5、使用request没有提示,是因为没有导包
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3、jsp模型I

如果jsp页面即作为视图组件与用户交互,又作为控制器组件处理程序流程,这样的架构称为jsp模型

jsp模型缺点:
	视图显示与流程控制的代码都是在jsp页面中完成,随着功能的增加,可读性变差

搞错了,数据库被遗忘了,等我看完数据库再回来看

2023.4.14 学完数据库归来

开发中提供一种:“单一性原则”,一个组件只做一件事

为了解决该问题,jsp提供了另一种模型:“jsp模型2
4、jsp模型II

在jsp模型II中,jsp只作为视图组件呈现界面与用户交互,它不在作为控制器,控制程序流程

程序中的控制器组件由一个java类:servlet类

servlet作为控制器类,用于控制程序

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5、servlet

什么是servlet?

servlet是一个运行在服务端的java组件,它一般作为控制器,用于接受用户的请求,对请求做出响应

响应:根据请求处理的不同结果,呈现不同的页面给客户端
6、servlet配置方式

方式1:采用注释

@webServlet("/login")

方式2:隐射的方式

    <servlet>
        <!--3、匹配别名-->
        <servlet-name>abc</servlet-name>
        <!--4、找到对应的servlet进行处理-->
        <servlet-class>com.arjunna.web.loginServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <!--2、生成别名-->
        <servlet-name>abc</servlet-name>
        <!--1、配置映射,指定如何匹配请求-->
        <url-pattern>/first</url-pattern>
    </servlet-mapping>

在这里插入图片描述

第三章 servlet

1、一个类要成为servlet必须满足下列条件

1、servlet必须是HttpServlet的子类

2、必须重写父类的doGet或doPost方法,运行重写两个,最少一个
	如果请求方式是get会进入doget
	如果请求方式是post会进入doPost
	
3、方法必须接受两个参数
	HttpServletRequest	-------请求对象
		通过它可以获得与本次请求相关的所有信息
	HttpServletResponse	-------响应对象
		通过它可以执行与响应相关的操作
		
4、方法必须要抛出两种异常
	ServletException
	IoException

普通类成为servlet处理请求的要求:

在这里插入图片描述

2、配置servlet

I、在web.xml中配置
    <servlet>
        <!--3、匹配别名-->
<servlet-name>abc</servlet-name> 第三步
        <!--4、找到对应的servlet进行处理-->第四步
        <servlet-class>com.arjunna.web.loginServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <!--2、生成别名-->
        <servlet-name>abc</servlet-name>  第二步
        <!--1、配置映射,指定如何匹配请求--> 第一步
        <url-pattern>/first</url-pattern>
    </servlet-mapping>
II、采用注解配置
@webServlet("/login")
public class loginServlet extends HttpServlet {
}

3、servlet将数据输出显示在控制台

 request.setCharacterEncoding("UTF-8");--只能处理表单提交数据的乱码

//        设置响应的编码格式,防止输出流产生中文乱码
        response.setContentType("text/html;charset=utf-8");
        //产生输入流,用于将数据显示在客户端浏览器上
        PrintWriter out =response.getWriter();
        //输出内容到客户端浏览器
        out.write("<h1>你好,世界</h1>");
        //刷新流,保证所有内容都可以被输出
        out.flush();
        //关闭流
        out.close();

4、解决中文乱码

如果表单提交的数据有中文,会产生乱码
     request.setCharacterEncoding("UTF-8");
     String xx=request.getParameter("xx");
     
     
如果用流输入的内容有中文
	 response.setContentType("text/html;charset=utf-8");
 	 PrintWriter out =response.getWriter();

5、有哪些方式进入servlet

只要表单可以发送post请求

I、表单提交可以进入servlet
默认get方式,但这种不安全,所有信息会显示在地址栏中

建议采用method="post"

表单提交时既可以发送get请求,也可以发送post请求
II、超链接可以进入servlet
超链接只能发送get请求,只能进入doGet方法
<a href="second">超链接</a>
III、直接在浏览器地址中输入请求名
这种只能发送get请求
IIII、通过jsp:forward标签跳转
<jsp:forward page="first">

在jsp页面中,只要遇到此标记,系统就会自动发出请求进行跳转
    
这种方式只能发送get请求

6、向servlet传递参数的方式

I、表单提交传递参数
<form action="login" method="post">
	姓名:<input type="text" name="user"><br>
	密码:<input type="password" name="pwd"><br>
	<input type="submit" value="提交">
</from>
II、超链接传递参数
1、超链接传递一个参数
	
		<a href="请求名称?参数名=值">超链接</a>
		<a href="second?id=1">
		
		在servlet中取参数的写法是
			String val=request.getParameter("参数名");
			String id=request.getParameter("id");
		
		注意:?只能用一次
		
		
2、超链接传递多个参数
		要求:第一个参数用?连接,后面的所有参数都要&连接
		
		<a href="请求名称?参数名1=值&参数名2=值">超链接</a>
		<a href="second?id=12&name=jack">
		
		在servlet中取参数的写法是
			String val=request.getParameter("参数名");
			String id=request.getParameter("id");
			String name=request.getParameter("name");

7、处理增删改查

I、针对每一个操作编写一个servlet进行处理
		<a href="add">增加<a>
		<a href="del">删除<a>
		<a href="update">修改<a>
		<a href="sel">查询<a>
	
这种写法会导致产生大量冗余代码
不会使用的
II、将增删改查写在同一个servlet类中
一般servlet中仅包含doGet与doPost方法,如果要包含其他方法,其他方法的格式要满足下列条件:


	protected void 方法名(HttpServletRequest request, 					HttpServletResponse response) throws ServletException, 		    IOException {
	
	
	}
	只有方法名可以自己写
解决方案:
		所有请求先进入doGet方法或doPost方法,用户要调用哪一个方法,就把该方法名称,作为参数传递进来,取到该参数然后手动调用自定义方法
		<a href="op?method=add">增加<a>
		<a href="op?method=del">删除<a>
		<a href="op?method=update">修改<a>
		<a href="op?method=sel">查询<a>
package com.arjunna.web;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/op")
public class opServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //调用doPost方法
        doPost(request,response);
    }


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置编码格式
        request.setCharacterEncoding("UTF-8");

        //接受参数的值
        String op=request.getParameter("method");

        //判断
        switch (op){
            case "add":
                add(request,response);
                break;
            case "del":
                del(request,response);
                break;
            case "update":
                update(request,response);
                break;
            case "sel":
                sel(request,response);
                break;
        }
    }


    protected void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("添加");

    }
    protected void del(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("删除");
    }
    protected void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("修改");
    }
    protected void sel(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("查询");
    }

}

在这里插入图片描述

8、java中的反射机制

我们希望servlet类中的每一个方法,可以自动调用,不再手动判断,手动调用
答:要实现这个效果,我们可以通过java中的反射机制来实现
I、反射的使用
作用:JAVA反射机制是在运行状态中
		对于任意一个类,都能够知道这个类的所有属性和方法;
		对于任意一个对象,都能够调用它的任意一个方法和属性;
II、什么是反射
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
III、要执行反射的前提条件
要对一个对象进行反射操作,前提条件是要获得当前类字节码文件所应的对象Class
IIII、获得class的三种方式
    //方式1:直接获取
    public void one(){
        Class clazz= userInfo.class;
        System.out.println(clazz);
    }


    //方式2:通过类的实例获得class对象
    public void two(){
        userInfo user=new userInfo();
        Class clazz= user.getClass();
        System.out.println(clazz);
    }


    //方式3:通过类的全路径获取class
    public void three() throws ClassNotFoundException {
        Class clazz= Class.forName("com.arjunna.enty.userInfo");
        System.out.println(clazz);
    }
IIIII、通过class对象,获得类中的属性
  
//区分修饰符
public void one(){
        //获得class对象
        Class clazz= userInfo.class;

        //通过class获得当前类中的属性(字段:field)

        //此方法只能获得类中public修饰的属性
        Field[] arrs=clazz.getFields();
        for(Field f:arrs){
            System.out.println(f.getName());
        }
    }

-----------------------------------------------
//不区分修饰符
    public void two(){
        //获得class对象
        Class clazz= userInfo.class;

        //通过class获得当前类中的属性(字段:field)

        //此方法获得所有声明的属性(不区分修饰符)
        Field[] arrs=clazz.getDeclaredFields();
        for(Field f:arrs){
            System.out.println(f.getName());
        }
    }
IIIIII、通过class获得类中的方法
    //获取当前类以及上一级类中的所有方法(不区分修饰符)
    public void one(){

        //获得class对象
        Class clazz= userInfo.class;
        //获得类中的方法
        Method[] methods=clazz.getMethods();

        for (Method method:methods){
            System.out.println(method.getName());
        }
    }


-----------------------------------------------
    //获得当前类的所有方法(不区分修饰符)
    public void two(){

        //获得class对象
        Class clazz= userInfo.class;
        //获得类中的方法
        Method[] methods=clazz.getDeclaredMethods();

        for (Method method:methods){
            System.out.println(method.getName());
        }
    }

-----------------------------------------------
    //根据方法名,获得类中的指定方法(不带参数)
    public void there() throws NoSuchMethodException {

        //获得class对象
        Class clazz= userInfo.class;
        //获得类中的方法
        Method methods=clazz.getDeclaredMethod("getPwd");

        System.out.println(methods.getName());
    }

-----------------------------------------------
    //根据方法名,获得类中的指定方法(带参数)
    public void four() throws NoSuchMethodException {

        //获得class对象
        Class clazz= userInfo.class;
        //获得类中的方法
        Method methods=clazz.getDeclaredMethod("test", int.class, String.class);

        System.out.println(methods.getName());
    }
IIIIIII、通过class对象执行类中的指定方法
    //执行类中的public方法
    public void one() throws Exception {

        //获得class对象
        Class clazz= userInfo.class;

        //获得要执行的public的方法
        Method method=clazz.getDeclaredMethod("add");

        //通过class获得当前类的实例
        Object obj=clazz.newInstance();

        //在对象上执行特定的方法
        method.invoke(obj);
    }

-----------------------------------------------
    //默认情况下,只能访问public方法,如果要访问其他修饰符,需要进行暴力反射
    public void two() throws Exception {

        //获得class对象
        Class clazz= userInfo.class;

        //获得要执行的public的方法
        Method method=clazz.getDeclaredMethod("del");

        //通过class获得当前类的实例
        Object obj=clazz.newInstance();

        //配置暴力反射(忽略访问修饰符,强制调用方法)
        method.setAccessible(true);

        //在对象上执行特定的方法
        method.invoke(obj);
    }

-----------------------------------------------(重点关注)
    //执行类中的带参方法
    public void there() throws Exception {

        //获得class对象
        Class clazz= userInfo.class;

        //获得要执行的public的方法
        Method method=clazz.getDeclaredMethod("test", int.class, String.class);

        //通过class获得当前类的实例
        Object obj=clazz.newInstance();

        //配置暴力反射(忽略访问修饰符,强制调用方法)
        method.setAccessible(true);


        //在对象上执行特定的方法
        //(对象实例,参数1,参数2)
        method.invoke(obj,1,"李白");
    }

-----------------------------------------------(重点关注)
    //执行带返回值的方法
    public void four() throws Exception {

        //获得class对象
        Class clazz= userInfo.class;

        //获得要执行的public的方法
        Method method=clazz.getDeclaredMethod("test2", int.class, int.class);

        //通过class获得当前类的实例
        Object obj=clazz.newInstance();

        //配置暴力反射(忽略访问修饰符,强制调用方法)
        method.setAccessible(true);

        //在对象上执行特定的方法
        //接受返回的参数
        Object val = method.invoke(obj,2,3);
        System.out.println("返回值是:"+val);
    }

9、使用反射简化servlet操作

I、编写BaseServlet
要求:BaseServlet需要继承HttpServlet


package com.arjunna.web;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


/*
* 反射的应用
* */
public class BaseServlet extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {

            //获得当前类的class对象
            Class clazz=this.getClass();

            //获得客户端请求的方法
            String methodName=req.getParameter("method");

            //通过class对象,获得当前类中指定名称的方法
            Method method=clazz.getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);

            //配置暴力反射(忽略访问修饰符,强制调用方法)
            method.setAccessible(true);

            //通过反射执行指定的方法
            method.invoke(this,req,resp);


        }catch (Exception e){
            e.printStackTrace();
        }

        }
    }


II、让子类继承于BaseServlet类
@WebServlet("/op")
public class opServlet extends BaseServlet {


	protected void add(HttpServletRequest request, 					HttpServletResponse response) throws ServletException, 		IOException {
        System.out.println("添加");
    }
    protected void del(HttpServletRequest request, 					HttpServletResponse response) throws ServletException, 		IOException {
        System.out.println("删除");
    }
    protected void update(HttpServletRequest request, 				HttpServletResponse response) throws ServletException, 		IOException {
        System.out.println("修改");
    }
    protected void sel(HttpServletRequest request, 					HttpServletResponse response) throws ServletException, 		IOException {
        System.out.println("查询");
    }
    /*         如果子类继承父类,子类就自动拥有父类的方法         */
}

在这里插入图片描述

第四章

项目步骤

1、创建项目
2、导入相关依赖(jar)
3、导入配置文件
	conf--->druid.properties
4、创建包结构
	util
	dao
	enty
	web
5、导入公共类
	1、JDBCUtil类
	2、BaseServlet类
6、编写实体类,与数据表的结构对应
7、编写infoDao类
8、编写InfoServlet类
9、编写jsp页面
10、导入jsp标签库的依赖  简化jsp的编码
	jstl.jar
	standard.jar
11、在jsp页面中引入
<%@ taglib prefix="c"  uri="http://java.sun.com/jstl/core_rt" %>
12、使用c:forEach遍历数据即可

1、简单的前后端交互

在java代码中,向request中存储数据
	request.setAttribute("键",值);-----必须是string类型
		值-----可以是任何类型(objcet)
	request.setAttribute("list",list)
		
在java代码中,从request中取数据
	数据类型  变量名 = (数据类型) request.getAttribute("键");
	List<userInfo> list =(List<userInfo>) request.getAttribute("list");
	//要强制转换

在jsp页面中,对request中存储的List的集合遍历,显示成表格

方式1:在jsp页面中,采用java脚本的方式遍历
方式1:在jsp页面中,采用java脚本的方式遍历

    <table border="1" style="margin:0 auto;width: 60%;text-align: center">
        <tr>
            <th>编号</th>
            <th>姓名</th>
            <th>密码</th>
            <th>余额</th>
        </tr>
        <%
            //接受交互层传递的request
            List<userInfo> list= (List<userInfo>) request.getAttribute("list");

            //遍历打印在页面上
            for (userInfo u:list) {
                out.write("<tr>");
                out.write("<td>"+u.getId()+"</td>");
                out.write("<td>"+u.getName()+"</td>");
                out.write("<td>"+u.getPwd()+"</td>");
                out.write("<td>"+u.getBalance()+"</td>");
                out.write("</tr>");

            }

        %>
    </table>

缺点:当代码稍微复杂一点,代码的可读性会变的非常差


方式2:使用JSTL标签库

jstl:jsp标准标签库

javaweb中,把jsp页面经常会使用的一些功能,封装成了标签,通过标签可以简化jsp页面的编码,避免在jsp页面中编写java脚本,简化页面编码

<c:forEach items="${存储的集合的名称}" var="从集合中取到的每一个对象">

<c:forEach>

使用便签库遍历数据

    <table border="1" style="margin:0 auto;width: 60%;text-align: center">
        <tr>
            <th>编号</th>
            <th>姓名</th>
            <th>密码</th>
            <th>余额</th>
        </tr>
        <c:forEach items="${list}" var="u" varStatus="st">
            <tr>
                <td>${u.id}</td>
                <td>${u.name}</td>
                <td>${u.pwd}</td>
                <td>${u.balance}</td>
            </tr>
        </c:forEach>
    </table>
    
    
    
    items-----它用于指定要遍历的集合名称
    var-------它用于指定变量,保存从集合遍历出来的每一个对象
    varStatus------它用于指定变量,只在当前对象在集合中的状态信息
    	
    	${st.index}-------得到当前对象在集合中的下标(从0开始)
      	${st.count}-------得到当前对象在集合中的第几个对象(从1开始计数)
      	${st.first}-------判断当前是否是集合的第一对象
      	${st.last}-------判断当前是否是集合的最后一对象

在这里插入图片描述

修改数据的思路:

1、点击连接,将要修改的id传回到后台
2、在后台代码中,根据id查询出一条数据,封装成对象,存储在request中
3、跳转到修改页面,将要修改的旧数据显示在控件,供用户查询
	-----数据回显
4、点击页面修改,将要修改的新数据提交到数据库

2、转发与重定向

I、javaweb程序跳转的方式有两种
方式1: 转发 foreard
		        						request.getRequestDispatcher("show.jsp").forward(request,response);
	   特点:1、转发时是在服务器端完成的跳转,地址栏不会改变,依然是之前的请求地址,如果刷新页面请求就会重复执行
	   		2、转发时,request会作为参数向下传递参数,所以,存储在request中的数据,在下一个页面中是可以把request中的数据取出来
	   		3、转发时只能跳转到当前项目中的地址
		
		
		
方式2: 重定向 redirect

response.sendRedirect("show.jsp");

		特点:1、重定向,它是通过修改客户端浏览器地址栏的地址实现跳转,地址栏的信息会改变成跳转后的地址,之前的请求已经结束,此时再刷新页面,请求也不会执行
			 2、重定向时,没有将请求继续向下继续传递,所以存在request中的数据,下一个页面取不到值
			 3、重定向时,可以跳转到任意的URL地址
II、面试题:forward(转发)与redirect(重定向)的区别
1、forward它是在服务器端完成的跳转,地址栏不会变,依然是之前的请求地址
   重定向它是客户端地址栏中实现的跳转,地址栏会改变,之前的请求会结束

2、转发时request会作为参数向下传递,所有存储在request中的数据再下一个页面可以取到,重定向时,没有将request作为参数向下传递,所以存储在request中的数据在下一个页面中取不到值

3、转发时,只能在项目内跳转;重定向时,可以跳转到任意地址

4、转发由request产生;重定向是由response产生



@@一般在加载数据时用转发,增、删、改以后用重定向
III、重定向的两种写法
方式1:重定向到页面
	response.sendRedirect("show.jsp");
		
		
方式2:重定向到serVlet中的某一个方法中
	response.sendRedirect("xxx?method=xxx")

第五章

—servlet的三种作用域

—jstl标签库的使用

—过滤器

1、servlet的三种作用域

**作用域:**作用域就是存储数据的有效范围

I、request:请求作用域
之前存储的数据时,采用如下形式
	request.setAttribute("键","值");
	
	
	
request:它是一个请求对象,可以执行与请求相关的操作
		 同时,它也是一个存储作用域,它存储的数据在一个请求(request)中有效,如果产生了新的请求,则之前存放在request(请求)中的数据会全部丢失

下列三种情况,会产生新的请求:

1、表单提交一次

2、页面跳转一次

3、页面刷新一次

问题:怎么确保即使产生新的请求,数据也不会丢失?

	 那么就需要更大的存储范围

II、HttpSession:会话作用域
HttpSession:会话(比请求作用域大)
			它是一个存储作用域,存放在会话作用域中的数据与请求无关,不论产生多少个请求,都不会影响到存放在会话作用域中的数据
			
问题1:什么时候产生?
	 当客户端与服务器端建立连接时,会话就会自动产生,会话作用域产生后就可以向该作用域存储数据,只要这个会话不中断,存储的数据将一直有效
	 
问题2:客户端与服务器端建立连接?
	值客户端用浏览器访问这个web应用程序,我们就称为:与服务器建立了连接
	
问题3:会话中断
	指关闭正在访问web程序的浏览器,我们就称为:”会话中断“
	只要客服端与服务器端建立连接,就会自动产生会话“HttpSession“(如打电话)
	

第一步:在serlvet中获得会话

	HttpSession session=request.getSession();

第二步:向会话作用域中存储数据

	session.setAttribute("消息的key",“数据”);
						键:必须是字符串类型
						值;可以为任意字符
						注释:与request的使用一模一样

第三步:从会话中取数据(在java中取值)

	类型 val =(类型) session.getAttribute("消息的key");

第三步:从会话中取数据(在jsp页面中取值)

	${消息的key}
会话(session)作用域的特点
	1、存放在session作用域中的数据与请求无关,不论产生多少个新的请求,都不会影响到存储在会话中的数据
	
	2、数据如果存储在session中,不论是转发还是重定向都可以取到值(与跳转方式无关)
	3、当session中断时,存放在session中的数据会全部丢失
			下列三种情况session会中断:
				1、关闭浏览器
				
				2、默认情况下,如果三十分钟内没有操作,session会因为闲置超时过期
				idle 闲置 expire 失效
				session.setMaxInactiveInterval();
					设置session过期时间
					
				3、调用session.invalidate();
					此方法调用后,session会马上失效
	4、当客户端与服务器端建立连接时,服务器端会为每一个客户端分配一个session,用于存储当前客户端的数据,每一个客户端的session,只有当前客服端自己才能访问
			只要打开一个新的浏览器访问web程序,系统就会认为是一个新的客户端,就会分配一				个session给当前用户存储数据(一个浏览器就是一个新客户端)
	

在这里插入图片描述

session只能查看当前用户自己访问web程序的次数

但是如果想要查看这个web程序启动以来,有多少个用户访问过,就需要更大的存储空间

III、 servletContext 全局上下文(全局作用域)
servletContext

​			它是最大的存储作用域

​			在web程序启动时(tomcat)全局上下文就开始了,知道服务器停止,全局上下文才会结束,只要服务器在运行,存放在全局上下文中的数据将一直有效
全局上下文的特点
	1、只要服务器在运行,存放在全局上下文的数据将一直有效,可以随时存,随时取

	2、全局上下文不区分用户,存放在全局上下文中的数据是全局共享(任何用户都可以取到)

获得全局上下文
servletContext cxt=this.getServletContext();
在servlet中,向全局上下文存数据
cxt.setAttribute("消息的key",值)
在servlet中,从全局上下文取数据
类型 val=(类型) cxt.getAttribute("消息的key");
在jsp页面中,从全局上下文取数据
${消息的key}

IIII、三种作用域总结
三种作用域:

​				request--------------------------------------请求作用域

​				session--------------------------------------会话作用域

​				servlet----------------------------------------全局上下文

**存数据的方式:**

​				作用域.setAttribute(“key”,值);

**取数据的方式**

​				类型 val = (类型)  作用域.getAttribute(“key”);

**jsp页面取值**

​				${}

**以上三种存储作用域的范围从小到大排序依次是:**

​				request   <    session	<	servletContext(几乎不用)

**问题:我们在编写代码时,应该使用哪一种存储作用域存数据**

​			原则:优先考虑范围较小的作用域,如果较小的范围解决不了问题,才会考虑大范围

2、jstl标签库

I、什么是jstl?
jstl:称为JSTL标准标签库,把一些jsp页面的常见功能封装成标签,通过标签可以简化jsp的页面,避免出现java小脚本

II、分类
前提条件:要使用jstl的标签,首先要导入两个依赖
		 1standard.jar
		 2、jstl.jar
1、核心标签库

要使用核心标签库,需要在jsp页面中引入核心标签库的指令

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

EL表达式的取值原理:

<c:set var="msg" value="hello" scope="page"/>
<c:set var="msg" value="hello" scope="request"/>
<c:set var="msg" value="hello" scope="session"/>
<c:set var="msg" value="hello" scope="application"/>

方式1:${msg}
	 这种方式,没有指定作用域的范围,系统会默认从最小的作用域开始取,如果小的范围中能找到,就不会再查找大范围,如果没有找到,就会依次从大范围中查找
	 
方式2:${作用域范围.msg}
	这种方式取值,只会查找特定的存储范围,如果没有找到,也不会再查找其他范围
	${pageScore.msg}------page范围
	${requestScore.msg}------request范围
	${sessionScore.msg}------session范围
	${applicationScore.msg}-----application范围

注意:在使用el表达式的时候,指定范围,性能会更好

核心标签库的分类


1、通用标签
		<c:set>
			作用:在jsp页面中设置一个变量,存储在作用域中
			使用:<c:set var="msg" value="hello" scope="作用域的名称"/>
				 var="msg"-----------设置了一个变量名叫msg
				 value="hello"-------它的值是hello
				 scope=""------------设置该变量的存储范围(默认是page作用域)
				 作用域有四种:
				 	1、page--------它存储的数据仅在当前页面有效,离开当前页就取不到
				 	2、request-----它存储的数据在request中有效
				 	3、session-----它存储的数据在session中有效
				 	4、application--它存储的数据在整个应用程序中有效(servletContext)
				 	
		<c:redirect>
			作用:在页面进行重定向
			使用:<c:redirect url="show.jsp">
					url="show.jsp"---重定向到页面
					url="op?method=init"-----重定向到某个方法上
			
2、逻辑标签:用于在页面中进行逻辑判断
		<c:if>
			作用:用于进行条件判断,如果条件成立,就执行if块的代码
			使用:<c:if test="${条件判断}">
				 	代码
				 <c:if>
			案例:
				分数:${requestScore.score}
				考核结果:<c:if test="${requestScore.score>=60}">
							<b style="color:green">合格</b>
						</c:if>
						<c:if test="${requestScore.score<60}">
							<b style="color:red">不合格</b>
						</c:if>
						
		<c:choose> <c:when> <c:otherwise>
			作用:这三个标签组合在一起,类似java中的多重if
			使用:<c:choose>
					<c:when test="${表达式1}">代码1<c:/when>
					<c:when test="${表达式2}">代码2<c:/when>
					<c:when test="${表达式3}">代码3<c:/when>
					<c:otherwise>代码4<c:/otherwise>
				 </c:choose>
			案例:
				分数:${requestScore.score}
				考核结果:<c:choose>
                           <c:when test="${requestScore.score>=90}">优秀<c:/when>
                           <c:when test="${requestScore.score>=80}">良好<c:/when>
                           <c:when test="${requestScore.score>=60}">合格<c:/when>
                           <c:otherwise>
                           		不合格
                           <c:/otherwise>
						 </c:choose>	

3、迭代标签:也称为循环标签
		<c:forEach>
			作用:用于对集合循环遍历
			使用1:<c:forEach items="${list}" var="u" varStatus="st">
                    <tr>
                        <td>${u.id}</td>
                        <td>${u.name}</td>
                        <td>${u.pwd}</td>
                        <td>${u.balance}</td>
                    </tr>
       	 		  </c:forEach>
				     items-----它用于指定要遍历的集合名称
    				 var-------它用于指定变量,保存从集合遍历出来的每一个对象
    				 varStatus------它用于指定变量,只在当前对象在集合中的状态信息
           
       		使用2:<select>
            		<option value="-1" >请选择年龄</option>
            		<c:forEach var="k" begin="1" end="120">								<option value="${k}">${k}岁</option>
            		</c:forEach>
            	 </select>>
            	在页面中生成循环结构
            		bengin:表示从几开始
            		end:到几结束
            		val:保存循环产生的每一个值
2、格式化标签库

作用:用于转换数据格式

前提条件:

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

转换日期类型的数据

//在请求中存值
request.setAttribute("bir",new Date());   
   
//格式化日期
   <fmt:formatDate value="${requestScope.bir}" pattern="yyyy-MM-dd HH:mm:ss E">
    </fmt:formatDate>

转换货币格式的数据

//在请求中存值
request.setAttribute("salary",123456.7895);  

//格式化金额
<fmt:formatNumber value="${requestScope.salary}"  type="currency"/>

3、sql标签库(已废弃)

III、标签的示例:

示例1:要求某一个页面只有登录用户才能查看,未登录的用户不允许查询页面(一般用户登录成功后,我们会将用户信息存放在session中,只有session不中断,就可以一直记录当前用户的状态信息)

**1、盗链:**越过登录直接访问网页地址

在这里插入图片描述

解决方法:

	显示页面
	<%--//判断用户是否登录,如果没有登录就直接跳转到登录页面--%>
	<c:if test="${sessionScope.user==null}">
    	<c:redirect url="login.jsp"/>
	</c:if>
	
	<h1>${sessionScope.user}</span>,欢迎您! </h1>
	
	
但此方法也有问题,一旦页面多了就得每个页面都写一个,过于麻烦
2、回显数据,转换日期格式
<input type="Date" value="<fmt:formatDate value="${requestScope.bir}" pattern="yyyy-MM-dd">">

日期标签里面嵌套格式化日期标签
3、单选按钮的数据回显
<input type="radio" name="gender" value="男" 							<c:iftest="${user.gender=='男'}">checked</c:if>>男

<input type="radio" name="gender" value="女"
       		<c:if test="${user.gender=='男'}">checked</c:if>>女

将查询到的用户性别做逻辑判断,匹配的加上checked属性
4、下拉选项数据回显
<select name="gender">
    <option value="-1" 
    	<c:if test="${gender=='-1'}">selected</c:if>>全部学生		</option>
    <option value="男" 
         <c:if test="${gender=='男'}">selected</c:if>>男生			</option>
    <option value="女" 
         <c:if test="${gender=='女'}">selected</c:if>>女生			</option>
</select>

查询条件相等的加上selected属性
5、在idea中编写代码中如果出现黄色的波浪线,是因为系统检测到重复代码

1、只要编写一句不一样就OK

2、file>Inspections>Duplicated code取消√即可

3、数据的分页使用

-- 设涉及到分页的sql语句

-- 分页查询的语句:
	select * from info limit 开始下标,几条数据;

-- 每页显示3条
	select * from info limit 0,3-----第1页
	select * from info limit 3,3-----第2页
	select * from info limit 6,3-----第3页
	select * from info limit,3-----第N页
	
-- 开始下标=(当前页-1)* 每页条数
-- 开始下标-(N-1)* 3

要分页显示数据必须要知道的四个值

1、当前页 page

2、每页显示的条数	rows

3、一共有几条数据	count

4、一共可以显示多少页  maxPage
总页数公式 = 总条数 % 每页条数 == 0 ?总条数/每页条数:总条数/每页条数 +1
int maxPage = count % rows == 0 ? count/rows : count/rows+1

分页流程

阶段1:显示全部数据
阶段2:只显示前3条数据
阶段3:实现分页
阶段4:优化分页

第六章

完善第五章的内容(新内容分页)

第七章

1、分页的优化

        <tr>
            <td colspan="6">
                <c:if test="${page==1}">
                    <span>首页</span>
                    <span>上一页</span>
                 </c:if>
                <c:if test="${page!=1}">
                    <a href="op?method=init&page=1">首页</a>
                    <a href="op?method=init&page=${page-1}">上一页</a>
                </c:if>
                <c:if test="${page==maxPage}">
                    <span>尾页</span>
                    <span>下一页</span>
                </c:if>
                <c:if test="${page!=maxPage}">
                    <a href="op?method=init&page=${page+1}">下一页</a>
                    <a href="op?method=init&page=${maxPage}">尾页</a>
                </c:if>
                &nbsp;
                <span>当前第<select οnchange="location.href='op?method=init&page='+this.value">
                    <c:forEach  var="k" begin="1" end="${maxPage}">
                        <option value="${k}" <c:if test="${k==page}">selected</c:if>>
                            ${k}
                        </option>
                    </c:forEach>
                </select>页</span>
                <span>共<b>${requestScope.maxPage}</b>页</span>
                <span>每页<b>${requestScope.rows}</b>条</span>
                <span>共<b>${requestScope.count}</b>条</span>

            </td>
        </tr>
多条件搜索后的分页
1、当点击搜索时,进入servlet中的search方法
	在该方法中获得所有查询条件,将查询条件存放在session

2、然后从search方法中重定向带init方法,根据条件分页


2、过滤器 Filter

定义:过滤器,它是一个运行在服务器端的java组件,主要用于拦截用户请求,给请求附加功能

在系统中配置了过滤器之后,客户端发出的请求在访问服务器的目标自愿(jsp,servlet)之前,会先进入过滤器,过滤器执行的代码完成之后,才会访问请求的目标资源

在这里插入图片描述

I、配置过滤器
过滤器属于工作类,一般放在util类

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

II、使用过滤器的场景
过滤器主要用于进行功能扩展
例如:拦截用户请求,判断用户是否登录,如果没有登录,自动转向登录界面

使用过滤器进行权限判断,用户不登录可以看到页面,但如果要操作页面上的功能,就必须要登录。如果未登录,会自动转向登录界面

个人认为这个过滤器很简单,很实用

3、支付宝沙箱

它是支付宝用于开发中的一种环境,它的用法与真实环境的用法一样

区别:
	1、它是用于开发环境中,主要用于测试环境支付功能,并不能真的付款,它使用的是测试数据
	2、它使用网关是开发环境的网关
	
如果要转换成正式环境,只需要向支付宝提交营业执照,更换网关地址即可

项目开发中会涉及三种环境:
	1、开发环境:这个环境主要用于编写代码
	2、测试环境:开发结束后,用于测试代码的环境
	3、生产环境:项目开发全部结束,并且测试通过,项目要上线投入生产使用
沙箱账号

商家信息
商户账号hsgxuj3492@sandbox.com
登录密码
商户PID2088721012026616
账户余额1000100.00


买家信息
买家账号yruahu7657@sandbox.com
登录密码
支付密码
用户UID2088722012026626
用户名称yruahu7657
证件类型IDENTITY_CARD
证件账号216297196408127438
账户余额1000000.00 


商家秘钥:


支付宝公钥:

网关地址:https://openapi.alipaydev.com/gateway.do
    
    
    
    
trade_no:2023042122001426620502312463---支付宝交易号
out_trade_no:202342117383328---商品交易号
total_amount:100.00---交易金额

第八章

1、支付宝的应用

app_id = "";

merchant_private_key = "";

alipay_public_key = "";


return_url = "http://localhost:8080/alipay/return_url.jsp";


gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

要调用支付宝接口进行支付,必须提供四个参数

tradeNo---------订单编号
tradePrice------订单金额
tradeName-------订单名称
tradeMsg--*-----交易详情

编写一个servlet类,用于处理付款成功的回调,这样才能获得支付宝的交易号,才能执行退款操作


2、购物车的综合练习

流程
1、数据表分析

2、加载全部商品

3、判断用户是否登录

4、用户的注册、登录

5、添加商品到购物车中

6、修改商品信息(增、删、改、查)

7、分页显示商品

8、支付
1、数据表的分析
1、商品表
		goods表
			goods_id 商品编号
			goods_name 商品名称
			goods_price 商品单价
			goods_prc 商品的图片
			
2、用户表
		user表
			user_id 用户编号
			user_name 用户名称
			user_pwd 用户密码
			
3、购物信息表
		cart表
			cart_id 购物编号
			user_id 用户编号---标识是哪一个用户的购物信息(外键,关联到用户表)
			goods_id 商品编号---标识购买的是哪一件商品(外键,关联到商品表)
			amout   购买数量
			

重定向传值

//传值
 response.sendRedirect("init.jsp?flag=ok");
 
 //取值
 ${param.flag}

弹框


alert() 是单线程消息框,再没有点击之前,其他数据无法加载
        <c:if test="${param.flag=='ok'}">
                <script>
                    new swal({
                        title: '已加入购物车!',
                        color: 'rgb(44, 153, 238)',
                        text: '2秒后自动关闭。',
                        timer: 2000
                    }).then(
                        function () { },

                        function (dismiss) {
                            if (dismiss === 'timer') {
                                console.log('小趴菜')
                            }
                        }
                    )
                </script>
        </c:if>

第九章

1、完善购物车案例

2、cookie的使用

3、文件上传下载

4、oos的使用

1、完善购物车

分页显示
1、当前页 page

2、每页显示的条数	rows

3、一共有几条数据	count

4、一共可以显示多少页  maxPage
总页数公式 = 总条数 % 每页条数 == 0 ?总条数/每页条数:总条数/每页条数 +1
int maxPage = count % rows == 0 ? count/rows : count/rows+1
付款
1、支付宝的四个值

2、导入依赖以及配置类

3、编写页面
	1、订单编号
	2、订单名称
	3、订单金额
	4、订单详情

2、cookie

I、什么是cookie
cookie是由服务器端产生的一个文本,产生好以后,服务器将会把cookie发送到客户端保存

cookie:它用于将用户信息保存在客户端
HttpSession:它用于将用户信息保存在服务器端

cookie的作用:用于在客户端保存用户信息
II、cookie的工作原理
1、当客户端与服务器端建立连接时,服务器将会产生一个cookie,cookie可以记录一些用户信息,然后服务器会将cookie发送到客户端保存

2、以后每一次客户端与服务器建立连接,保存在客户端的cookie将会自动跟随请求一起发送到服务器

III、cookie的保存位置
不同的浏览器,保存的cookie的位置不一样

C:\Users\86159\AppData\Local\Google\Chrome\User Data\Default\Network
IIII、cookie的特点
cookie是在客户端以文本的方式保存用户信息,安全性不高,所以不能存储敏感信息,芽一班用于存储用户身份(userID、username)

它主要在客户端记录当前用户的身份信息;
例如:用户几天之内不用登录,系统会自动登录
IIIII、cookie的基本使用

创建cookie

在服务器端创建cookie

        //创建cookie
        Cookie ck=new Cookie("d118_cookie","这是一个新的cookie");
        //设置cookie的存活时间-秒
        ck.setMaxAge(120);
        //将cookie保存到客户端
        response.addCookie(ck);
        System.out.println("cookie发送成功!");

获得cookie

获得指定的cookie
      
      //获取请求携带的cookie----它只能获得当前程序发送到客户端保存的cookie
        Cookie[] cks=request.getCookies();
        if (cks!=null){
            for (Cookie ck:cks) {
                if (ck.getName().equals("d118_cookie")){
                    System.out.println("cookie的名字:"+ck.getName());
                    System.out.println("cookie的值:"+ck.getValue());
                }
            }
        }

3、自动登录案例–cookie

获得复选框的值

 <input type="chekbox" value="ok" >


//获得一组复选框选中的值
 String[] vals = request.getParameterValues("复选框的name'");

//获取一个复选框的值
String str = request.getParameter("复选框的name");
*选中有值
*没有选中是null
package web;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/user")
public class cookieServlet extends BaseServlet {

    protected void init(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //读取cookie
        //获取请求携带的cookie----它只能获得当前程序发送到客户端保存的cookie
        Cookie[] cks=request.getCookies();
        //指定的cookie
        Cookie userCookie=null;
        //对所有的cookie遍历
        if (cks!=null){
            for (Cookie ck:cks) {
                if (ck.getName().equals("username")){
                    //找到了指定的cookie
                    userCookie=ck;
                    break;
                }

            }
        }
        if (userCookie!=null){
            //得到cookie的用户信息
            String user  = userCookie.getName();
            //将用户信息存到seesion中
            request.getSession().setAttribute("user",user);
            //重定向到显示页面
            response.sendRedirect("success.jsp");
        }else {
            //cookie已失效

            //没有找到指定cookie
            response.sendRedirect("login.jsp");
        }

    }

    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //获取用户名
        String username = request.getParameter("user");

        if (username.equals("")){
            request.setAttribute("msg","用户名或密码错误");
            request.getRequestDispatcher("login.jsp").forward(request,response);
        }else{

            //将用户信息存放到session中
            request.getSession().setAttribute("username",username);

            //判断用户是否勾选记住登录
            String remember = request.getParameter("remember");

            if (remember!=null){
                //创建cookie
                Cookie ck=new Cookie("username",username);
                //设置cookie的存活时间-秒
                ck.setMaxAge(20);
                //将cookie保存到客户端
                response.addCookie(ck);
                System.out.println("cookie发送成功!");
            }
            response.sendRedirect("success.jsp");
        }
    }

}

4、文件上传

指客户端的文件上传到服务器

1、编写工程

2、导入依赖
    common-fileupload.jar
    common-io.jar

3、编写页面

4、编写servlet处理请求


1、编写上传页面的要求
1、表单提交方式必须post请求

2、必须指定表单enctype="multipart/form-data"-----允许表单携带附件

3、使用文件域选择文件
	<input type="file" name="file">
	
	
	
    <form action="" method="post" enctype="multipart/form-data">
      文件:<input type="file" name="file">
      <input type="submit" value="提交">
    </form>
2、上传案例
package com.web;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

@WebServlet("/file")
public class fileServlet extends BaseServlet {


    SimpleDateFormat sfdate=new SimpleDateFormat("yyyy-MM-dd");

    Map<String,String> map=new HashMap<>();

    protected void up(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        try {
            //获得文件对象的工厂类,用于获得表单提交的所有数据(表单中提交的的数据,系统都会当成一个文件进行处理)
            FileItemFactory factory =new DiskFileItemFactory();

            //获得处理器
            ServletFileUpload sf=new ServletFileUpload(factory);

            //通过处理器,将表单请求中提交的每一条数据转换成文件对象FileItem放入list集合中
            List<FileItem> list=sf.parseRequest(request);

            //判断哪些是真正的文件,哪些是表单的普通数据
            //如果是真的文件,需要在服务器端生成物理文件,如果是普通数据直接使用
            for (FileItem item:list) {

                if (item.isFormField()){//如果返回true,就表示当前是表单的普通数据,如果false,则是文件
                    //普通数据

                    //获取当前普通数据的字段名称
                    String key=item.getFieldName();
                    //获得普通数据的值
                    String value=item.getString("utf-8");

                    //把数据存放到map中
                    map.put(key,value);

                }else {
                    //文件
                    //获取时间,防止重名
                    Date date=new Date();

                    //获得上传的文件名
                    String fileName = "a_"+sfdate.format(date)+"_"+UUID.randomUUID().toString()+"_"+item.getName();

                    //在服务器指定路径下,生成新文件
                    File file=new File("E:/upload",fileName);

                    //判断文件目录是否存在
                    if (!file.getParentFile().exists()){
                        file.getParentFile().mkdirs();
                    }

                    //将上传文件的数据写入新文件中
                    item.write(file);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

//        从map中取值
            String user=map.get("user");
            String pwd=map.get("pwd");
            request.getSession().setAttribute("user",user);
            request.getSession().setAttribute("pwd",pwd);
            //重定向
            response.sendRedirect("ok.jsp");
    }


}

第十章

基于javaweb上传下载

oos对象存储服务

jxl

1、上传与下载

模拟向数据库添加文件

SimpleDateFormat sfdate=new SimpleDateFormat("yyyy-MM-dd");

Date date=new Date();

String fileName = "a_"+sfdate.format(date)
+"_"+UUID.randomUUID().toString()
+"_"+item.getName();

//解决文件重名

上传

//上传
    protected void up(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        try {
            //获得文件对象的工厂类,用于获得表单提交的所有数据(表单中提交的的数据,系统都会当成一个文件进行处理)
            FileItemFactory factory =new DiskFileItemFactory();

            //获得处理器
            ServletFileUpload sf=new ServletFileUpload(factory);

            //通过处理器,将表单请求中提交的每一条数据转换成文件对象FileItem放入list集合中
            List<FileItem> list=sf.parseRequest(request);

            //判断哪些是真正的文件,哪些是表单的普通数据
            //如果是真的文件,需要在服务器端生成物理文件,如果是普通数据直接使用
            for (FileItem item:list) {

                if (item.isFormField()){//如果返回true,就表示当前是表单的普通数据,如果false,则是文件
                    //普通数据

                    //获取当前普通数据的字段名称
                    String key=item.getFieldName();
                    //获得普通数据的值
                    String value=item.getString("utf-8");

                    //把数据存放到map中
                    map.put(key,value);

                }else {
                    //文件
                    //获取时间,防止重名
                    Date date=new Date();

                    //获得上传的文件名
                    String fileName = "a_"+sfdate.format(date)+"_"+item.getName();

                    //在服务器指定路径下,生成新文件
                    File file=new File("E:/upload",fileName);

                    //判断文件目录是否存在
                    if (!file.getParentFile().exists()){
                        file.getParentFile().mkdirs();
                    }

                    //将上传文件的数据写入新文件中
                    item.write(file);


                    //获得文件类型
                    String type=fileName.substring(fileName.lastIndexOf(".")+1);
                    map.put("type",type);//存放到map中

                    //获得文件保存路径
                    map.put("path",file.getAbsolutePath());

                    //获得文件大小
                    long num=file.length();//1024byte=1kb  1024kb=1mb
                    //判断是以什么结尾
                    String size="";
                    if (num/1024/1024>=1){
                        size=num/1024.0/1024+"Mb";
                    }else{
                        size=num/1024.0+"kb";
                    }
                    map.put("size",size);


                    /******************上传成功后存到数据库********************/

                    fdao.add(map.get("user"),map.get("pwd"),map.get("type"),map.get("path"),map.get("size"));

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

//        从map中取值
            String user=map.get("user");
            String pwd=map.get("pwd");
            String type=map.get("type");
            String path=map.get("path");
            String size=map.get("size");
            request.getSession().setAttribute("user",user);
            request.getSession().setAttribute("pwd",pwd);
            request.getSession().setAttribute("type",type);
            request.getSession().setAttribute("path",path);
            request.getSession().setAttribute("size",size);
            //重定向
            response.sendRedirect("ok.jsp");



    }

下载

//下载
    protected void download(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获得下载的文件编号
        Integer id=Integer.parseInt(req.getParameter("id"));

        //到数据库查找该id的文件信息
        fileInfo f=fdao.findByid(id);

        /*******************下面是下载的代码******************************************/
        //获得文件名,将文件名转换utf-8
        String fname= URLEncoder.encode(f.getFileName(),"utf-8");//只需要转换文件名

       //显示下载界面
        resp.setContentType("application/x-msdownload");
        //设置下载面板上显示的内容
        resp.setHeader("Content-disposition","attachment;fileName="+fname);

        //创建输入流,用于读取要下载的文件
        InputStream in=new FileInputStream(f.getFilePath());

        //通过响应产生输出流
        ServletOutputStream out=resp.getOutputStream();

        //创建字节数组,充当数据缓冲区
        byte[] b=new byte[8192];

        //定义变量保存写入到数据缓冲区的数据长度
        int len=0;
        //一边读一边写
        while ((len=in.read(b))!=-1){
            out.write(b,0,len);
        }
        out.close();
        in.close();
    }

2、在web程序中图片显示的问题

在web程序中,要显示图片,图片的路径只支持两种路径

1、相对路径
	img/1.jpg
2、网络路径
	http://xxxx.xx.xx/xx.jpg

绝对路径无法显示

解决图片上传的显示问题

解决方案1:使用分布式文件系统FastDFS

FastDFS需要在linux系统中配置

在这里插入图片描述

解决方案2:使用对象oss服务

阿里云对象存储 OSSObject Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,提供最高可达 99.995 % 的服务可用性。多种存储类型供选择,全面优化存储成本。

3、oss服务配置及使用

阿里云账号
登录名:
账号ID:
手机号:



1、服务器位置:oss-cn-beijing.aliyuncs.com

2、AccessKey ID:
   AccessKey Secret:
   
3、空间名称:

4、上传文件名:6.jpg

5、完整路径:e:/upload/6.jpg
package com.demo;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;

import java.io.FileInputStream;
import java.io.InputStream;

public class fileUpload {

    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "oss-cn-.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "";
        String accessKeySecret = "";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "bg.jpg";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
        String filePath= "E:\\upload\\bg.jpg";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream inputStream = new FileInputStream(filePath);
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 设置该属性可以返回response。如果不设置,则返回的response为空。
            putObjectRequest.setProcess("true");
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            // 如果上传成功,则返回200。
            System.out.println(result.getResponse().getStatusCode());
        } catch (Exception oe) {
            oe.printStackTrace();
        }
    }
}

第十一章

jxl解析电子表格文档

servlet的生命周期

jsp的内置对象

1、jxl解析电子表格文档

I、什么是jxl
jxl:它是操作电子表格文档excel的一种技术,通过它可以读取excel文件的数据,也可以将数据写入到excel文件
II、使用jxl解析excel文件
把excel中的数据读取到程序中

电子表格文件的后缀名:*.xls、*.xlsx
jxl解析主要支持*.xls
poi可以解析*.xlsx

一般在显示数据表格时,或者是批量导入数据时,导入到数据里

使用步骤

1、导入依赖jar  jxl.jar

2、编写如下代码


/*解析单个工作表*/
package com.sc.demo;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import java.io.FileInputStream;
import java.io.InputStream;

public class demo {
    public static void main(String[] args) throws Exception {

        //创建输入流,用于读取要解析的文件
        InputStream in=new FileInputStream("e:/date/test.xls");

        //根据输入流的信息,产生工作簿
        Workbook wk=Workbook.getWorkbook(in);

        //获得工作簿中所有的表单
        Sheet[] sheets=wk.getSheets();

        //分别获得表单的名称
//        for (Sheet sheet:sheets) {
//            System.out.println(sheet.getName());
//        }

        //获得第一个表单的数据
        Sheet st=sheets[1];

        //获得表单的总行数
        int rows = st.getRows();

        //获得表单的总列数
        int cols=st.getColumns();

        //读取每一行、每一列的值
        for (int i=0;i<rows;i++){//遍历所有行
            for (int j=0;j<cols;j++){//遍历所有的列
                //根据列下标,行下标获得表单中指定的单元格
                Cell cell=st.getCell(j,i);//(列下标,行下标);
                //获得当前单元格中的内容
                String msg=cell.getContents();
                System.out.print(msg+"\t");
            }
           System.out.println();
        }
    }
}


/*解析所有工作表的方法*/
package com.sc.demo;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import java.io.FileInputStream;
import java.io.InputStream;

public class demo {
    public static void main(String[] args) throws Exception {

        //创建输入流,用于读取要解析的文件
        InputStream in=new FileInputStream("e:/date/test.xls");

        //根据输入流的信息,产生工作簿
        Workbook wk=Workbook.getWorkbook(in);

        //获得工作簿中所有的表单
        Sheet[] sheets=wk.getSheets();

//        获得所有的表单信息
        for (Sheet st:sheets) {
            System.out.println("----------------------------------------");
            //获得表单的总行数
            int rows = st.getRows();

            //获得表单的总列数
            int cols=st.getColumns();

            //读取每一行、每一列的值
            for (int i=0;i<rows;i++){//遍历所有行
                for (int j=0;j<cols;j++){//遍历所有的列

                    //根据列下标,行下标获得表单中指定的单元格
                    Cell cell=st.getCell(j,i);//(列下标,行下标);

                    //获得当前单元格中的内容
                    String msg=cell.getContents();

                    System.out.print(msg+"\t");
                }
                System.out.println();

            }
        }
    }
}

III、将数据写入到xls文件中

只写入一个单元格的案例

package com.sc.demo;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class demo2 {
    /*
    * 写数据到excel
    * */
    public static void main(String[] args) throws Exception {

        //创建输出流
        OutputStream out= new FileOutputStream("e:Date/out.xls");

        //创建一个可以写入数据的工作簿
        WritableWorkbook wk= Workbook.createWorkbook(out);

        //在工作簿中创建表单,并设置表单名称
        WritableSheet st = wk.createSheet("d118", 0);//参数1:表单名称,参数2:表单的下标

        //创建一个标签Label-----它就是每一个单元格要显示的内容
        Label labelid=new Label(0,0,"编号");//(列下标,行下标,标签显示的名称)

        //将标签放到表单中
        st.addCell(labelid);

        //将工作簿的数据写入到文件中
        wk.write();

        //关闭工作簿
        wk.close();
        out.close();
        System.out.println("数据已写入");
    }
}

将数据库的数据写入到excel表格中

package com.sc.demo;

import com.sc.dao.stuDao;
import com.sc.enty.stuInfo;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;

public class demo2 {
    /*
    * 写数据到excel
    * */


    public static void main(String[] args) throws Exception {


        //创建输出流
        OutputStream out= new FileOutputStream("e:Date/out.xls");

        //创建一个可以写入数据的工作簿
        WritableWorkbook wk= Workbook.createWorkbook(out);

        //在工作簿中创建表单,并设置表单名称
        WritableSheet st = wk.createSheet("d118", 0);//参数1:表单名称,参数2:表单的下标

        //创建一个标签Label-----它就是每一个单元格要显示的内容
        Label labid=new Label(0,0,"编号");//(列下标,行下标,标签显示的名称)
        Label labname=new Label(1,0,"姓名");
        Label labage=new Label(2,0,"年龄");
        Label labgender=new Label(3,0,"性别");
        Label labclazz=new Label(4,0,"班级");
        Label labtel=new Label(5,0,"电话");
        Label labtime=new Label(6,0,"注册日期");
        Label labres=new Label(7,0,"备注");
        //将标签放到表单中
        st.addCell(labid);
        st.addCell(labname);
        st.addCell(labage);
        st.addCell(labgender);
        st.addCell(labclazz);
        st.addCell(labtel);
        st.addCell(labtime);
        st.addCell(labres);


        stuDao sdao=new stuDao();
        //获得要写入的数据
        List<stuInfo> list=sdao.init();

        for (int i=0;i<list.size();i++){
            //蝴蝶每一个对象
            stuInfo stu=list.get(i);
            Label id=new Label(0,i+1,stu.getSid().toString());
            Label name=new Label(1,i+1,stu.getSname());
            Label age=new Label(2,i+1,stu.getSage().toString());
            Label gender=new Label(3,i+1,stu.getSgender());
            Label sclass=new Label(4,i+1,stu.getSclass());
            Label tel=new Label(5,i+1,stu.getStel());
            Label time=new Label(6,i+1,stu.getSregtime());
            Label res=new Label(7,i+1,stu.getRes());

            //将标签添加到表单中
            st.addCell(id);
            st.addCell(name);
            st.addCell(age);
            st.addCell(gender);
            st.addCell(sclass);
            st.addCell(tel);
            st.addCell(time);
            st.addCell(res);
        }

        //将工作簿的数据写入到文件中
        wk.write();

        //关闭工作簿
        wk.close();
        out.close();
        System.out.println("数据已写入");
    }
}

设置写入到exce中的样式

package com.sc.demo;

import com.sc.dao.stuDao;
import com.sc.enty.stuInfo;
import jxl.Workbook;
import jxl.write.*;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;

public class demo2 {
    /*
    * 写数据到excel
    * */


    public static void main(String[] args) throws Exception {


        //创建输出流
        OutputStream out= new FileOutputStream("e:Date/out.xls");

        //创建一个可以写入数据的工作簿
        WritableWorkbook wk= Workbook.createWorkbook(out);

        //在工作簿中创建表单,并设置表单名称
        WritableSheet st = wk.createSheet("d118", 0);//参数1:表单名称,参数2:表单的下标

        /*****************************在写入数据前,设置表格的数据样式************************************/
//
//           设置表格每一列宽度或高度
            st.getSettings().setDefaultColumnWidth(25);//列宽
//            st.getSettings().setDefaultRowHeight(15);//行高
//        指定一种可以用流写入文件的字体(字体类型,字体大小,字体是否加粗)
            //大标题的样式
            WritableFont ft=new WritableFont(WritableFont.ARIAL,20,WritableFont.BOLD);
//            指定一种单元格的格式(参数:字体)
            WritableCellFormat wcf=new WritableCellFormat(ft);
            wcf.setAlignment(Alignment.CENTRE);//内容居中对齐
            wcf.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )
            wcf.setWrap(true);//数据自动换行

        //普通标题的样式
            WritableFont f1=new WritableFont(WritableFont.ARIAL,18,WritableFont.BOLD);
//          指定一种单元格的格式(参数:字体)
            WritableCellFormat wcf1=new WritableCellFormat(f1);
            wcf1.setAlignment(Alignment.CENTRE);//内容居中对齐
            wcf1.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )
            wcf1.setWrap(true);//数据自动换行

        //内容的样式
            WritableFont f2=new WritableFont(WritableFont.ARIAL,18);
    //          指定一种单元格的格式(参数:字体)
            WritableCellFormat wcf2=new WritableCellFormat(f2);
            wcf2.setAlignment(Alignment.CENTRE);//内容居中对齐
            wcf2.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )
            wcf2.setWrap(true);//数据自动换行
        /************************************指定样式结束**********************************************/

        //添加大标题
        Label th=new Label(0,0,"学员信息",wcf);
        st.addCell(th);
        //合并单元格(开始列下标,开始行下标,结束列下标,结束行下标);
        st.mergeCells(0,0,7,0);


        //创建一个标签Label-----它就是每一个单元格要显示的内容
        Label labid=new Label(0,1,"编号",wcf1);//(列下标,行下标,标签显示的名称,表格的样式)
        Label labname=new Label(1,1,"姓名",wcf1);
        Label labage=new Label(2,1,"年龄",wcf1);
        Label labgender=new Label(3,1,"性别",wcf1);
        Label labclazz=new Label(4,1,"班级",wcf1);
        Label labtel=new Label(5,1,"电话",wcf1);
        Label labtime=new Label(6,1,"注册日期",wcf1);
        Label labres=new Label(7,1,"备注",wcf1);
        //将标签放到表单中
        st.addCell(labid);
        st.addCell(labname);
        st.addCell(labage);
        st.addCell(labgender);
        st.addCell(labclazz);
        st.addCell(labtel);
        st.addCell(labtime);
        st.addCell(labres);


        stuDao sdao=new stuDao();
        //获得要写入的数据
        List<stuInfo> list=sdao.init();

        for (int i=0;i<list.size();i++){
            //蝴蝶每一个对象
            stuInfo stu=list.get(i);
            Label id=new Label(0,i+2,stu.getSid().toString(),wcf2);
            Label name=new Label(1,i+2,stu.getSname(),wcf2);
            Label age=new Label(2,i+2,stu.getSage().toString(),wcf2);
            Label gender=new Label(3,i+2,stu.getSgender(),wcf2);
            Label sclass=new Label(4,i+2,stu.getSclass(),wcf2);
            Label tel=new Label(5,i+2,stu.getStel(),wcf2);
            Label time=new Label(6,i+2,stu.getSregtime(),wcf2);
            Label res=new Label(7,i+2,stu.getRes(),wcf2);

            //将标签添加到表单中
            st.addCell(id);
            st.addCell(name);
            st.addCell(age);
            st.addCell(gender);
            st.addCell(sclass);
            st.addCell(tel);
            st.addCell(time);
            st.addCell(res);
        }

        //将工作簿的数据写入到文件中
        wk.write();

        //关闭工作簿
        wk.close();
        out.close();
        System.out.println("数据已写入");
    }
}

2、点击下载生成excel表格保存到本地

package com.sc.web;

import com.sc.dao.stuDao;
import com.sc.enty.stuInfo;
import jxl.Workbook;
import jxl.write.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;


@WebServlet("/jxl")
public class jxlServlet extends BaseServlet {

        stuDao sdao=new stuDao();

    protected void init(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {


        //加载数据
        List<stuInfo> list=sdao.init();

        //存到seesion中
        request.getSession().setAttribute("list",list);

        //跳转到显示页面
        response.sendRedirect("init.jsp");

    }

    //导出数据
    protected void export(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

            //取出session中的数据
            List<stuInfo> list= (List<stuInfo>) request.getSession().getAttribute("list");

            //文件名
            String fname="d118学生信息.xls";

            //转换文件编码格式
            String name= URLEncoder.encode(fname,"utf-8");

            //设置响应格式(响应格式是一个电子表格文件)
            response.setContentType("application/vnd.ms excel");

            //设置下载面板上显示的内容
            response.setHeader("Content-disposition","attachment;fileName="+name);

            //通过响应产生一个输出流,用于将excel文件输出到客户端
           ServletOutputStream out=response.getOutputStream();



           /********************************以下代码直接赋值导出表格的代码*********************************/

        try {

            //创建一个可以写入数据的工作簿
            WritableWorkbook wk= Workbook.createWorkbook(out);

            //在工作簿中创建表单,并设置表单名称
            WritableSheet st = wk.createSheet("d118", 0);//参数1:表单名称,参数2:表单的下标

            /*****************在写入数据前,设置表格的数据样式************************/
//
//           设置表格每一列宽度或高度
            st.getSettings().setDefaultColumnWidth(25);//列宽
//            st.getSettings().setDefaultRowHeight(15);//行高
//        指定一种可以用流写入文件的字体(字体类型,字体大小,字体是否加粗)
            //大标题的样式
            WritableFont ft=new WritableFont(WritableFont.ARIAL,20,WritableFont.BOLD);
//            指定一种单元格的格式(参数:字体)
            WritableCellFormat wcf=new WritableCellFormat(ft);
            wcf.setAlignment(Alignment.CENTRE);//内容居中对齐
            wcf.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )
            wcf.setWrap(true);//数据自动换行

            //普通标题的样式
            WritableFont f1=new WritableFont(WritableFont.ARIAL,18,WritableFont.BOLD);
//          指定一种单元格的格式(参数:字体)
            WritableCellFormat wcf1=new WritableCellFormat(f1);
            wcf1.setAlignment(Alignment.CENTRE);//内容居中对齐
            wcf1.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )
            wcf1.setWrap(true);//数据自动换行

            //内容的样式
            WritableFont f2=new WritableFont(WritableFont.ARIAL,18);
            //          指定一种单元格的格式(参数:字体)
            WritableCellFormat wcf2=new WritableCellFormat(f2);
            wcf2.setAlignment(Alignment.CENTRE);//内容居中对齐
            wcf2.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )
            wcf2.setWrap(true);//数据自动换行
            /******************指定样式结束************************/

            //添加大标题
            Label th=new Label(0,0,"学员信息",wcf);
            st.addCell(th);
            //合并单元格(开始列下标,开始行下标,结束列下标,结束行下标);
            st.mergeCells(0,0,7,0);


            //创建一个标签Label-----它就是每一个单元格要显示的内容
            Label labid=new Label(0,1,"编号",wcf1);//(列下标,行下标,标签显示的名称,表格的样式)
            Label labname=new Label(1,1,"姓名",wcf1);
            Label labage=new Label(2,1,"年龄",wcf1);
            Label labgender=new Label(3,1,"性别",wcf1);
            Label labclazz=new Label(4,1,"班级",wcf1);
            Label labtel=new Label(5,1,"电话",wcf1);
            Label labtime=new Label(6,1,"注册日期",wcf1);
            Label labres=new Label(7,1,"备注",wcf1);
            //将标签放到表单中
            st.addCell(labid);
            st.addCell(labname);
            st.addCell(labage);
            st.addCell(labgender);
            st.addCell(labclazz);
            st.addCell(labtel);
            st.addCell(labtime);
            st.addCell(labres);

            for (int i=0;i<list.size();i++){
                //获得每一个对象
                stuInfo stu=list.get(i);
                Label id=new Label(0,i+2,stu.getSid().toString(),wcf2);
                Label stuname=new Label(1,i+2,stu.getSname(),wcf2);
                Label age=new Label(2,i+2,stu.getSage().toString(),wcf2);
                Label gender=new Label(3,i+2,stu.getSgender(),wcf2);
                Label sclass=new Label(4,i+2,stu.getSclass(),wcf2);
                Label tel=new Label(5,i+2,stu.getStel(),wcf2);
                Label time=new Label(6,i+2,stu.getSregtime(),wcf2);
                Label res=new Label(7,i+2,stu.getRes(),wcf2);
                //将标签添加到表单中
                st.addCell(id);
                st.addCell(stuname);
                st.addCell(age);
                st.addCell(gender);
                st.addCell(sclass);
                st.addCell(tel);
                st.addCell(time);
                st.addCell(res);
            }

            //将工作簿的数据写入到文件中
            wk.write();

            //关闭工作簿
            wk.close();
            out.close();
            System.out.println("数据已写入");




        } catch (Exception e) {
            e.printStackTrace();
        }
        /*******************************************赋值结束*********************************************/

    }
}

3、servlet的生命周期(理解)

servlet的生命周期分为下列几个阶段:

1、实例化阶段--------只执行1次

​ 调用的构造方法

2、实例初始化阶段--------只执行1次

​ init()

3、服务阶段--------多次执行

​ service()

4、销毁阶段--------只执行1次

​ destroy()

servlet生命周期的四个阶段,其中实例化、初始化、销毁只会执行一次,服务阶段会多次将执行

实例:

package com.sc.web;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/demo")
public class demoServlet extends HttpServlet {

    public demoServlet(){
        System.out.println("1、调用了构造方法实例化servlet..");
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

        System.out.println("3、service方法进行服务处理..");
        super.service(req, res);
    }

    @Override
    public void destroy() {
        System.out.println("4、销毁servlet");
        super.destroy();
    }

    @Override
    public void init(ServletConfig config) throws ServletException {

        System.out.println("2、调用init方法进行初始化..");
        super.init(config);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

servlet的执行过程
1、当请求到达服务器,web容器(tomcat)会调用servlet的构造方法创建一个servlet实例

2、servlet创建好以后,web容器会马上调用当前servlet的init方法进行初始化

3、初始化完成后,web容器会调用当前servlet父类(HttpServlet)类中的service方法进行处理,在该方法中系统会判断请求的请求方式,是post还是get请求,如何根据请求的类型调用servlet类中的doget或者dopost方法进行处理,当请求处理完成以后,当前servlet会驻留在web容器,当下一次请求再一次到达服务器时,web容器就会调用已存在的servlet直接处理,不再创建实例,初始化实例

4、直到web容器停止时,web容器会调用servlet的destroy方法,销毁当前的servlet实例

4、jsp的内置对象

在开发中,如何编写动态网页项目
开发流程:
1、美工会做好静态模型---Demo
			一般demo中只会包含:html,css,js
			
2、程序员需要将美工提供的静态模型修改成动态页面
      Label sclass=new Label(4,i+2,stu.getSclass(),wcf2);
            Label tel=new Label(5,i+2,stu.getStel(),wcf2);
            Label time=new Label(6,i+2,stu.getSregtime(),wcf2);
            Label res=new Label(7,i+2,stu.getRes(),wcf2);
            //将标签添加到表单中
            st.addCell(id);
            st.addCell(stuname);
            st.addCell(age);
            st.addCell(gender);
            st.addCell(sclass);
            st.addCell(tel);
            st.addCell(time);
            st.addCell(res);
        }

        //将工作簿的数据写入到文件中
        wk.write();

        //关闭工作簿
        wk.close();
        out.close();
        System.out.println("数据已写入");




    } catch (Exception e) {
        e.printStackTrace();
    }
    /*******************************************赋值结束*********************************************/

}

}




### 3、servlet的生命周期(理解)

**servlet的生命周期分为下列几个阶段:**

**1、实例化阶段**--------只执行1次

​		 调用的构造方法

**2、实例初始化阶段**--------只执行1次

​		 init()

**3、服务阶段**--------多次执行

​		 service()

**4、销毁阶段**--------只执行1次

​		destroy()

```java
servlet生命周期的四个阶段,其中实例化、初始化、销毁只会执行一次,服务阶段会多次将执行

实例:

package com.sc.web;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/demo")
public class demoServlet extends HttpServlet {

    public demoServlet(){
        System.out.println("1、调用了构造方法实例化servlet..");
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

        System.out.println("3、service方法进行服务处理..");
        super.service(req, res);
    }

    @Override
    public void destroy() {
        System.out.println("4、销毁servlet");
        super.destroy();
    }

    @Override
    public void init(ServletConfig config) throws ServletException {

        System.out.println("2、调用init方法进行初始化..");
        super.init(config);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

servlet的执行过程
1、当请求到达服务器,web容器(tomcat)会调用servlet的构造方法创建一个servlet实例

2、servlet创建好以后,web容器会马上调用当前servlet的init方法进行初始化

3、初始化完成后,web容器会调用当前servlet父类(HttpServlet)类中的service方法进行处理,在该方法中系统会判断请求的请求方式,是post还是get请求,如何根据请求的类型调用servlet类中的doget或者dopost方法进行处理,当请求处理完成以后,当前servlet会驻留在web容器,当下一次请求再一次到达服务器时,web容器就会调用已存在的servlet直接处理,不再创建实例,初始化实例

4、直到web容器停止时,web容器会调用servlet的destroy方法,销毁当前的servlet实例

4、jsp的内置对象

在开发中,如何编写动态网页项目
开发流程:
1、美工会做好静态模型---Demo
			一般demo中只会包含:html,css,js
			
2、程序员需要将美工提供的静态模型修改成动态页面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/585787.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

神经网络基础(Neural net foundations)

Today we’ll be learning about the mathematical foundations of deep learning: Stochastic gradient descent (SGD), and the flexibility of linear functions layered with non-linear activation functions. We’ll be focussing particularly on a popular combination…

基于SSM的文物管理系统(含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的文物管理系统拥有俩种角色 管理员&#xff1a;个人信息管理、用户管理、分类管理、文物信息管理、文物外借管理、文物维修管理、留言板管理等 用户&#xff1a;登录注册、分类…

接口测试 - postman

文章目录 一、接口1.接口的类型2. 接口测试3. 接口测试流程4. 接口测试用例1. 测试用例单接口测试用例-登录案例 二、HTTP协议1. HTTP请求2. HTTP响应 三、postman1. 界面导航说明导入 导出用例集 Get请求和Post请求的区别:2.postman环境变量和全局变量3. postman 请求前置脚本…

【webrtc】MessageHandler 4: 基于线程的消息处理:以Fake 收发包模拟为例

G:\CDN\rtcCli\m98\src\media\base\fake_network_interface.h// Fake NetworkInterface that sends/receives RTP/RTCP packets.虚假的网络接口,用于模拟发送包、接收包单纯仅是处理一个ST_RTP包 消息的id就是ST_RTP 类型,– 然后给到目的地:mediachannel处理: 最后消息消…

如何轻松在D盘新建文件夹?意外丢失的文件夹怎么找回

对于很多刚接触电脑的朋友来说&#xff0c;如何正确地新建文件夹并将其放置在特定盘符&#xff08;如D盘&#xff09;可能是一个不小的挑战。同时&#xff0c;如果新建的文件夹突然消失&#xff0c;而我们又确信自己没有删除它&#xff0c;那么该如何找回呢&#xff1f;本文将为…

想要接触网络安全,应该怎么入门学习?

作为一个网络安全新手&#xff0c;首先你要明确以下几点&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#xff1f;有哪些方向&#xff1f;怎么选&#xff1f;这一行职业前景如何&#xff1f; 其次&#xff0c;如果你现在不清楚学什么的话&…

微信小程序实现九宫格

微信小程序使用样式实现九宫格布局 使用微信小程序实现九宫格样式&#xff0c;可以直接使用样式进行编写&#xff0c;具体图片如下&#xff1a;1、js代码&#xff1a; Page({/*** 页面的初始数据*/data: {current: 4},// 监听activeClick(e) {let index e.currentTarget.dat…

IOT-9608I-L 的GPIO应用

目录 概述 1 GPIO接口介绍 2 板卡上操作IO 2.1 查看IO驱动 2.2 使用ECHO操作IO 2.2.1 端口选择 2.2.2 查看IO 2.2.3 echo操作IO 3 C语言实现一个操作IO的案例 3.1 功能介绍 3.2 代码实现 3.3 详细代码 4 测试 测试视频地址&#xff1a; IOT-9608I-L的一个简单测试&a…

使用Gradio搭建聊天UI实现质谱AI智能问答

一、调用智谱 AI API 1、获取api_key 智谱AI开放平台网址&#xff1a; https://open.bigmodel.cn/overview 2、安装库pip install zhipuai 3、执行一下代码&#xff0c;调用质谱api进行问答 from zhipuai import ZhipuAIclient ZhipuAI(api_key"xxxxx") # 填写…

回溯Backtracking Algorithm

目录 1) 入门例子 2) 全排列-Leetcode 46 3) 全排列II-Leetcode 47 4) 组合-Leetcode 77 5) 组合总和-Leetcode 39 6) 组合总和 II-Leetcode 40 7) 组合总和 III-Leetcode 216 8) N 皇后 Leetcode 51 9) 解数独-Leetcode37 10) 黄金矿工-Leetcode1219 其它题目 1) 入…

汽车热辐射、热传导、热对流模拟加速老化太阳光模拟器系统

汽车整车结构复杂&#xff0c;材料种类繁多&#xff0c;在使用过程中会面临各种严酷气候环境的考验&#xff0c;不可避免会出现零部件材料老化、腐蚀等不良现象&#xff0c;从而影响汽车的外观、功能&#xff0c;甚至产生安全隐患。因此&#xff0c;分析汽车零部件材料老化腐蚀…

【图论】图论基础

图论不同地方讲的不太一样&#xff0c;本文仅限作者的理解 定义 图是一般由点集 V V V 和边集 E E E 组成。 对于 v ∈ V v\in V v∈V&#xff0c;称 v v v 为该图的一个节点。 对于 e ∈ E e\in E e∈E&#xff0c;一般用二元组 ( u , v ) (u,v) (u,v) 表示 e e e&am…

Matlab生成txt文件导入到Vivado仿真

Matlab处理数据并将其写入txt文件 %% Txt Generate pre_RS_datadec2bin(simDataIn,8); %将数据转化为8bit的二进制 fidfopen("F:\FPGA\Xilinx_vivado\project\dvbstestbench\dbvs\matlab\pre_RS_data.txt","wt"); for i1:n*nMessages %数据…

记一次使用Notepad++正则表达式批量替换SQL语句

目录 一、需求二、解决方案三、正则解析 一、需求 存在如下SQL建表脚本&#xff1a; CREATE TABLE "BUSINESS_GOODS" ( "ID" VARCHAR(32) NOT NULL, "GOODS_CODE" VARCHAR(50), "GOODS_NAME" VARCHAR(100), ... NOT CLUSTER PRIMARY…

设计模式第一次测验 | 数据库连接设计(单例模式、抽象工厂模式、工厂模式)

需求如下&#xff1a; 我们需要设计一个工具&#xff0c;它负责创建一个与数据库软件的连接池。 该工具由在容器&#xff08;Tomcat等&#xff09;内运行的应用程序用来连接数据库软件。 在同一个容器中运行的所有应用程序共享同一个连接池对象。 现在我们需要支持以下数据库软…

TCP/IP和HTTP协议

TCP/IP OSI 七层模型在提出时的出发点是基于标准化的考虑&#xff0c;而没有考虑到具体的市场需求&#xff0c;使得该模型结构复杂&#xff0c;部分功能冗余&#xff0c;因而完全实现 OSI 参考模型的系统不多。而 TCP/IP 参考模型直接面向市场需求&#xff0c;实现起来也比较…

arthas如何排除CPU使用率过高问题

1、首先启动arthas java -jar arthas-boot.jar 2、使用thread查看各线程CPU使用率 thread 可以看到CPU使用率最高的有2个线程&#xff0c;以线程ID为19的为例子&#xff1a; 输入thread 19查看线程19的堆栈信息&#xff1a; thread 19 可以看到是(CpuController.java:78行…

「C/C++ 01」类型转换与整型提升

目录 一、类型转换和截断问题 1. 隐式类型转换 2. 强制类型转换 3. 截断问题 二、整型提升 0. 算数表达式的计算过程 1. 整型提升是什么&#xff1f; 2. 为什么要整型提升&#xff1f; 3. 如何进行整型提升 4. 唯一的注意事项 5. 通过在vs中的监视窗口来观察整型提升 6. 整型…

螺旋角和导程、转位后的齿轮有什么关系?

最近和小伙伴聊到了一个问题&#xff1a;斜齿轮螺旋角和导程的关系&#xff0c;主要是在遇到在采用转位设计方式的刀具时&#xff0c;更觉得有点迷惑&#xff0c;今天咱们就聊聊这个事儿。 先来说斜齿轮螺旋角和导程的关系&#xff1a; 斜齿轮是有多个螺旋面组成的&#xff0…

力扣153. 寻找旋转排序数组中的最小值

Problem: 153. 寻找旋转排序数组中的最小值 文章目录 题目描述思路复杂度Code 题目描述 思路 1.初始化左右指针left和right&#xff0c;指向数组的头和尾&#xff1b; 2.开始二分查找&#xff1a; 2.1.定义退出条件&#xff1a;当left right时退出循环&#xff1b; 2.2.当nums…
最新文章