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的标签,首先要导入两个依赖
1、standard.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>
<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服务
阿里云对象存储 OSS(Object 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、程序员需要将美工提供的静态模型修改成动态页面