JAVAEE基础知识

发布时间 2023-08-19 20:49:17作者: 小曾Study平台

JAVAEE基础知识

2018年3月,开源组织Eclipse基金会宣布,JavaEE(Enterprise Edition)被更名为JakartaEE,也就是9版本后改名Jakarta EE,也就是JakartaEE9。

Java EE(Java Platform,Enterprise Edition)是sun公司(2009年4月20日甲骨文将其收购)推出的企业级应用程序版本。这个版本以前称为 J2EE。能够帮助我们开发和部署可移植、健壮、可伸缩且安全的服务器端 Java应用程序。Java EE 是在 Java SE 的基础上构建的,它提供Web 服务、组件模型、管理和通信 API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web 3.0应用程序。

Java,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台的总称。用Java实现的HotJava浏览器(支持Java applet)显示了Java的魅力:跨平台、动态的Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览器均支持Java applet。

1、IDEA下载与破解

1、本破解教程除了适用于IDEA,同样适用于JetBrains全家桶,比如PyCharm、DataGrip、Goland、WebStorm等等
本次工具支持2021.3以后版本( 2021.3.1,2021.3.2,2021.3.3,2022.1,2022.1.1,2022.1.2,2022.1.3,2022.1.4,2022.2,2023.1)的IDEA使用.
2、首先下载IDEA相关版本
https://www.jetbrains.com/idea/
3、下载激活脚本
下载地址:https://wwu.lanzoub.com/i2Mls0ha05le
脚本文件夹介绍:
- cripts: 这里存放了激活用到的脚本(windows、mac、linux都有)
- vmoptions:IDEA关联的配置文件
4、 运行激活脚本(如果之前已经激活过,建议先执行卸载脚本,再执行安装脚本)
打开下载文件中的scripts文件,我们可以看到如下几个文件脚本
Windows系统: 双击运行 install-current-user.vbs 脚本,为当前用户安装破解补丁。install-all-users.vbs为所有系统用户安装,不过不太推荐
Mac、Linux系统: 执行install.sh 脚本(Mac 注意给整个文件夹777权限)与之对应的uninstall xxx脚本就是卸载补丁的脚本。
5、双击执行 install-xxx 补丁,我们会看到如下的弹窗,意思是:补丁运行可能需要几秒钟,点击确定,然后等待Done的提示框就可以。
6、输入激活码
【激活码】XIZQAN09CR-eyJsaWNlbnNlSWQiOiJYSVpRQU4wOUNSIiwibGljZW5zZWVOYW1lIjoia2lkZHkgaW5zZWFtcyIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiIiLCJjaGVja0NvbmN1cnJlbnRVc2UiOmZhbHNlLCJwcm9kdWN0cyI6W3siY29kZSI6IlBEQiIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFNJIiwiZmFsbGJhY2tEYXRlIjoiMjAyNS0wOC0wMSIsInBhaWRVcFRvIjoiMjAyNS0wOC0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUEMiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBDV01QIiwiZmFsbGJhY2tEYXRlIjoiMjAyNS0wOC0wMSIsInBhaWRVcFRvIjoiMjAyNS0wOC0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUkIiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBQUyIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiSUkiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQR08iLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBTVyIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6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
【注意】其他软件激活码访问:https://www.955code.com/8857.html。
7、之后就看到成功激活到2088年了!部分版本显示2025年,就是永久激活了!太在乎这个时间的。
【注意】同样适用于其他JetBrains产品,比如PyCharm、DataGrip、Goland、WebStorm等等。
如果您是旧版本IDEA(2021.2.2及其之前版本),请参考:https://www.955code.com/2906.html

output

output (1)

  • idea常用快捷键

image-20230815210230229

2、HTTP协议基础知识

1、B/S架构:Brower--->server,浏览器发送http请求到服务器,服务器获得数据经过逻辑处理后,响应给浏览器。这种架构只需要修改服务器的代码,就可以完成软件的更新。
C/S架构:client---->server,客户端发送数据给服务器,这种架构需要重新安装更新后的软件,维护代码非常不便。
2、HTTP协议是超文本请求和响应传输协议。
3、简单快速:客户向服务器请求服务时
4、HTTP协议特点:
一、支持客户/服务器模块
二、简单快速:只需传送请求方法和路径。请求方式常有的有get和post,由于HTTP协议简单,因而通信速度很快。
三、灵活:HTTP允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。
四、无连接:每次连接只处理一个连接。服务器处理完客户的请求,并收到客户的应答后,断开连接,这种方式可以节省传输时间。HTTP1.1支持可持续连接。
五、无状态:HTTP协议是无状态协议。无状态是指对于事务处理没有记忆能力,缺少状态意味着后续处理需要先前信息,则它必须重传,这样导致传输的数据量增大。
5、浏览器发送到服务器是属于请求协议,服务器发送到浏览器是属于响应协议。
  • 浏览器请求地址书写格式分析图:

image-20230815211333928

  • HTTP之URL
HTTP是一个基于请求和响应模式的、应用层的协议,常基于TCP的连接方式,绝大多数web开发都是构建在HTTP之上的web应用。
HTTP协议包括:请求行、请求头、请求体(get请求方式没有请求体)、响应行、响应头、响应体(html代码标签/json字符串)
基本格式:
post请求方式:http://IP(主机名/域名):端口/访问的资源路径
get请求方式:http://IP(主机名/域名):端口/访问的资源路径?key=value&key=value&……
  • HTTP状态码分类:

image-20230816101044686

  • 常见请求头参数

image-20230816102348651

  • 常见响应头参数

image-20230816102532971

3、TOMCAT服务器

一、Tomcat基本介绍

1、Tomcat服务器实际上是一个用JAVA编写的软件,它提供一个容器,用于运行web项目,可以实现多个客服端通过网络传输请求访问web项目,实现数据的共享,一个容器可以运行多个项目。
2、硬件服务器实际上是一台电脑,里面一般安装linux系统,可以在服务器上部署软件服务器和web软件,实现客户端通过网络访问远程服务器实现数据共享。
3、Tomcat目录分析:
bin:有开启和停止tomcat的指令文件。
lib:tomcat运行依赖的jar包(jsp.jar,servlet-api.jar等)。
conf:存放tomcat配置文件,其中server.xml可以修改端口号,修改默认加载项目。
log:存放日志的文件夹,可以看日志信息去查bug,相当于javase开发的控制台输出信息。
webapps:存放运行web项目的文件夹。
temps:临时文件存放文件夹。
[注意]:如果在DOS命令窗口启动输出信息出现乱码问题,要修改conf文件夹中的logging.properties文件编码格式,默认是UTF-8,应该改为GBK。

二、Idea配置Tomcat

  • 下载Tomcat
1、由于tomcat是用java开发的,所以下载tomcat时要注意jdk版本与tomcat版本配套问题。
2、使用tomcat前,要在window环境配置中,在系统环境path配置好JAVA_HOME环境。
3、在官网下载:http://www.tomcat.apache.org/。下载后解压缩包,并把bin目录配置到系统环境的path中。
  • Tomcat与JDK版本兼容图

image-20230816112547893

  • 配置tomcat

image-20230816113338213

image-20230816113423314

image-20230816113444517

4、Servlet基础

Servlet是运行在服务器上的应用,tomcat容器三大组件(servlet、filter、listener)之一,通过servlet可以实现页面的请求访问。

一、IDEA搭建web项目

常用的两种方式:
1、在普通java项目中,添加web框架支持。
2、创建javaee,maven项目,导入相关依赖。
  • 普通java项目添加web框架支持

image-20230816135752236

img

img

  • maven工程构建JAVAEE项目

image-20230816135950340

二、搭建servlet的三种方式

  1. 继承HttpServlet类。
public class Servlet_Demo1 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("service 方法!");
    }
}

2.继承GenericServlet类。

public class Servlet_Demo1 extends GenericServlet {

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        
    }
}

3.实现Servlet接口

public class Servlet_Demo1 implements Servlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

三、Servlet设置跳转页面的两种方式

  • 传统方式(servlet3.0以前)
在web.xml文件配置servlet编辑器
   <servlet>
        <servlet-name>servlet1</servlet-name>  <!--自定义servlet名字-->
       <!--绑定servlet全类名-->
        <servlet-class>com.zwf.servletDemo.Servlet_Demo1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet1</servlet-name>
        <!--设置servlet请求跳转路径-->
        <url-pattern>/index</url-pattern>
    </servlet-mapping>
  • 注解方式
//注解设置跳转路径 name:自定义名  value:跳转路径
@WebServlet(name = "servletDemo",value = "/s1")
public class Servlet_Demo1 implements Servlet {
}

四、servlet运行机制

1、浏览器访问响应http页面请求,然后首先执行servlet中的service()方法,然后判断是get还是post请求,然后相应调用doGet()或者doPost()方法。
2、如果你直接重写service()方法,它直接先执行service(ServletRequest req,ServletResponse resp)方法,你可以直接在service()中编写逻辑代码,或者不编写service()方法,直接编写doGet()或者doPost()方法,servlet会根据请求方式不同跳转到相应方法。

5、servlet生命周期

浏览器访问servlet请求路径,servlet会先调用构造器,然后调用初始化函数init(),接着调用service()方法期间封装了HttpServletRequest和HttpServletResponse对象,最后关闭tomcat容器,servlet调用destory()销毁servlet对象。
[注意]只有service()方法可以被调用多次,其他方法只会加载调用一次。

6、HttpServletRequest对象

HttpServletRequest是http请求对象,可以获取请求头中相关信息,它的父类是servletRequest,并且是父类唯一的子接口,目的是长远考虑,如果出现新的协议可以直接继承父接口进行编写。
常用方法有:
getRequestURL():获取项目全路径
getRequestURI():获取项目页面路径 /项目名路径/子路径
getQueryString():获取参数的完整格式 key=value&key=value
getMethod():获取请求方式(get post delete put等请求)
getContextpath():获取项目根路径  /项目名
getProtocol():获取HTTP版本
getParamter(String name); 根据name属性值  获取value。
getParamterValues(String name); 根据name属性值  获取所有value。
  • 测试代码
 //获取项目全路径(http://服务器:端口号/项目名路径/子路径)
        StringBuffer URL = req.getRequestURL();
        System.out.println("项目全路径:"+URL);
        //获取资源目录路径(/项目名/子路径)
        String uri = req.getRequestURI();
        System.out.println("资源路径"+uri);
        //获取请求方式
        String method = req.getMethod();
        System.out.println("请求方式:"+method);
        //获取项目路径资源路径(webapp站点路径  /项目名)
        String path = req.getContextPath();
        System.out.println("项目资源路径:"+path);
        //获取请求参数(username=zs&pwd=123)
        String queryString = req.getQueryString();
        System.out.println("请求的参数:"+queryString);
        //获取HTTP版本号 HTTP1.1
        String proto = req.getProtocol();
        System.out.println("超文本传输协议的版本号:"+proto);
        System.out.println("**************************************");
        //根据name值获取value值
        String username = req.getParameter("username");
        System.out.println(username);
        //根据name值获取所有的value值  一般用于获取多选框的value值 返回一个数组类型
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println(Arrays.toString(hobbies));
  • request解决乱码问题
原因:前端表单传来的中文要以UTF-8编码方式通过TCP协议socket方式转为字节数组,传送到servlet时还是UTF-8,但是使用requestParamter(String name);默认是把UTF-8编码转换成ISO-8859-1字符编码,而此编码不支持中文,就出现乱码。
解决方案:使用 String value=new String(request.getParamter().getBytes("ISO-8859-1"),"UTF-8")(新版本tomcat处理乱码问题无效,tomcat8.0以下版本);但是这种方式如果对于多个参数传递,就需要每个参数都要定义,非常繁琐。所以我们就出现了一个新方法。
request.setCharacterEncoding("UTF-8");但是这个方法实际上只对post请求方式解决中文乱码问题有效,我们只需要更换tomcat版本在8.0及其以上就解决了get和post乱码问题。
  • 测试代码
//以下方式对新版本tomcat处理中文乱码问题无效 tomcat8.0以上
  String username = new String(req.getParameter("username").getBytes("ISO-8859-1"), "UTF-8");
//解决中文乱码问题  tomcat8.0以上  get post请求全部解决  低版本只解决了post乱码问题
req.setCharacterEncoding("UTF-8");
  • 请求转发
1、请求转发是浏览器向服务器发送一次请求,服务器内部处理处理数据,地址栏不会变,可设置和在不同页面获取request域中的值,不同页面之间可以共享数据。
2、常用方式:
request.setAttribute(String name,Object obj);
request.getAttribute(String name);
request.getRequestDispathcher(String path).forward(request,response);
  • 测试代码
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String[] hobbies = req.getParameterValues("hobby");
        req.setAttribute("username",username);
        req.getRequestDispatcher("infor.jsp").forward(req,resp);

7、ServletResponse对象

  • response解决乱码问题
原因:idea默认是UTF-8字符编码,文本网络传输时转化为字节数组,字节数组默认编码格式是ISO-8859-1,要通过response.setCharacterEncoding("UTF-8")把字节数组字符编码转为UTF-8,然后再加响应头response.setContentType("text/pain;charset=UTF-8"),让浏览器以UTF-8字符编码显示文本,如果是字符流可以不设置response.setCharacterEncoding("UTF-8")。
  • 测试代码
 resp.setCharacterEncoding("UTF-8");
//GBK UTF-8支持中文  iso-8859-1不支持中文格式 三种不同方式的请求头编写方式
resp.setHeader("Content-Type","text/pain;charset=utf-8");
 resp.setContentType("text/pain;charset=utf-8");
resp.addHeader("Content-Type","text/pain;charset=utf-8");
  • 重定向
客户端向浏览器发送多次请求,多次请求的request不同,导致request域不能存放数据,也就是“服务器指导,客户端操作”,不同页面之间不能共享数据。
常用方法:response.sendRedirect(String path);
  • 测试代码
req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String[] hobbies = req.getParameterValues("hobby");
        req.setAttribute("username",username);
        req.setAttribute("hobby",hobbies);
        resp.sendRedirect("infor.jsp");
  • 请求转发和重定向的区别
1、请求转发是处理同一个请求,重定向是处理不同的请求。
2、请求转发地址栏不会改变,重定向会改变跳转地址。
3、请求转发可以通过request域携带参数,重定向不能携带参数。
4、请求转发服务器内部处理,效率高,重定向能跳转到服务器内外部。
5、请求转发表单可以重复提交,重定向表单不能重复提交。
6、请求转发不支持绝对路径,重定向支持绝对路径(推荐绝对路径)。
  • 关于请求转发和重定向路径问题
1、请求转发是在服务器根目录下(/项目名/)去找文件,所以设置相对路径应该是getRequestRedirect("/资源路径"),如果是跳转到jsp文件,设置相对路径应该是getRequestDispatcher("/*.jsp")或者getRequestDispatcher("*.jsp");不能使用绝对路径。
2、重定向是在服务器根目录中(http:127.0.0.1:8080/)去找文件,所以设置相对路径应该设置为response.sendRedirect("/项目名/资源路径");设置绝对路径应该是response.sendRedirect("http:127.0.0.1:8080/项目名/资源路径");
3、web项目文件夹下的页面文件,重定向和请求转发都可以访问,而WEB-INF文件夹下的页面文件,只能通过请求转发访问。
5、通过el表达式中的${pageContext.request.contextpath}获取项目根相对路径。

8、Cookie对象

1、cookies是服务器创建给客户端保存的数据对象,可以让客户端下次访问服务端的时候直接用cookie匹配服务端的session进行查找,cookie保存的数据以键值对存在,Cookie不适合大量数据的存储(每个Cookie存储的数据不超过4KB)。
2、特点:
一、cookie只能保存在各自浏览器中,不能跨浏览器。
二、cookie只能保存很小的数,不超过4kb。
三、浏览器保存cookie数量有限,一般有选择性的存储。
四、cookie默认是保存在浏览器内存中,要设置保存时间(单位是秒)才能持久化保存。
五、cookie原则上是不支持保存中文,如果要保存中文的需要进行编码,获取中文时需要解码。
六、同名cookie的值会被覆盖。
  • 测试代码
        //创建cookie
        Cookie cookie=new Cookie("username","zs");
        //响应给客户端
        resp.addCookie(cookie);
         //设置保存时间1分钟 默认不持久化保存,只保存在浏览器内存中
          cookie.setAge(60);
       //获取浏览器的cookie值 只会获取所有的cookie值
        Cookie[] cookies = req.getCookies();
        //处理中文字符 不处理中文字符编码问题 会报服务器错误
  Cookie cookies=new Cookie( URLEncoder.encode("姓名"),URLEncoder.encode("小曾"))
        for (Cookie c:cookies){
            System.out.println(c.getName()+"------------>"+c.getValue());
            //获取中文字符
            URLDecode.decode(c.getName());
        }
    //可以设置访问cookie的网页路径  / 表示此服务器所有的项目都可以获取cookie值 还可以指定具体获取cookie的请求。
    cookie.setPath("/");  

image-20230817142633465

9、HttpSession对象

1、session是服务器创建保存的,服务器创建一次session生成sessionId,服务器把sessionId响应到浏览器中以JSEEIONID保存在服务器中,下次请求的时候,浏览器以JSESSION去匹配服务器的sessionId值获取session存储的数据。
2、如果关闭浏览器,再次打开浏览器请求时,前一次的cookie对象被销毁,请求中没有JSEEEIONID,服务器会重新创建sessionId响应新的JSESSIONID保存在浏览器中。
3、如果关闭服务器,在没有钝化的情况下session立即销毁或者执行invidate()销毁session,重新打开服务器会创建新的session,浏览器重新访问又会生成新的cookie。
4、session对象默认销毁时间是30分钟,如果你不进行操作,到了销毁时间就会销毁session对象,如果操作了就会重新计时。
5、session域可以存放数据在用户多次请求中进行数据共享,可以在同一种浏览器发送请求实现数据共享,重定向也可以实现数据共享。
  • 测试代码
        //设置字符编码
        req.setCharacterEncoding("UTF-8");
        HttpSession session = req.getSession(); 
        //设置
        session.setAttribute("name","session对象");
        String id = session.getId();
        System.out.println("sessionId="+id);
        //设置过期时间  单位是秒
        session.setMaxInactiveInterval(30);
        //获取最大过期时间  默认是30*60s
        int max = session.getMaxInactiveInterval();
        System.out.println("最大过期时间:"+max+"s");
        //判断sessionId是否是新的
        boolean aNew = session.isNew();
        System.out.println(aNew?"sessionId是新的":"sessionId是旧的");
        //对session进行立即销毁
        session.invalidate();
        //请求转发到相应路径
        req.getRequestDispatcher("/session/get").forward(req,resp);
  • 在web.xml文件中配置过期时间
 <!--基本单位是分钟 这里设置为60分钟-->
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>

10、ServletContext对象

1、ServletContext域是servlet对象中范围最大的域,可以实现同一个web容器数据共享,每一个web服务器只能创建一个ServletContext对象,也可以跨浏览器进行数据共享,重定向也可以实现数据共享。
2、获取ServletContext对象的四种方式:
ServletContext context = req.getSession().getServletContext();
ServletContext context1 = req.getServletContext();(常用)
ServletContext context2 = super.getServletConfig().getServletContext();
ServletContext context3 = super.getServletContext();
  • 设置服务器容器初始化数据(web.xml)
<!--服务器启动后会加载这个数据,可以用来加载springIOC容器-->
    <context-param>
        <param-name>name</param-name>
        <param-value>张珊</param-value>
    </context-param>
  • 测试代码
       //获取项目真实路径          //D:\bigCode\JavaEEStudy\out\artifacts\Servlet_Demo2_war_exploded\
        String realPath = context.getRealPath("/");
        System.out.println(realPath);
        //获取服务器加载时的初始化对象
        String name = context.getInitParameter("name");
        System.out.println(name);
        //在application域中存放数据
        context.setAttribute("age",18);
        //获取服务器信息 Apache Tomcat/9.0.60
        String info = context.getServerInfo();
        System.out.println(info);
        resp.sendRedirect("/test/session/get");

11、文件的上传和下载

在上网的时候我们常常遇到文件上传的情况,例如上传头像、上传资料等;当然除了上传,遇见下载的情况也很多,接下来看看我们 servlet 中怎么实现文件的上传和下载。

一、文件上传

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
    <form action="upload" method="post" enctype="multipart/form-data">
    文件名:<input type="text" name="fileName" placeholder="请输入上传的文件名">
   <label for="upload">文件上传:
       <input type="file" name="uploadFile" id="upload"/><br>
   </label>
    <input type="submit" value="上传文件">
    </form>
</body>
</html>

  • Servlet后端代码
 req.setCharacterEncoding("UTF-8");
        String fileName = req.getParameter("fileName");
        System.out.println("获取表单文件名:"+fileName);
        //获取文件表单名对象
        Part part=req.getPart("uploadFile");
        //获取上传文件名
        String FileName = part.getSubmittedFileName();
        //获取项目真实路径
        String path=req.getServletContext().getRealPath("/upload/");
        System.out.println(path);
        //写入项目路径中
        part.write(path+FileName);

二、文件下载

  • 方式一
html超链接请求,对于不识别文件会自动下载,对于识别文件的会直接打开,所以可以设置为<a href="下载路径" download="1.jpeg">下载文件</a>
download属性有的浏览器不识别,谷歌浏览器识别,download可以设置为下载文件重命名。
  • 前端代码(前提是要把存放文件的download文件夹加载到服务器中)

image-20230817210537643

<body>
<%--由于浏览器识别文本和图片 不会下载  浏览器不识别压缩文件 会自动下载
   想要让文本文件和图片文件进行下载  要加上download属性还可设置重命名
--%>
<a href="/download/hello2023.txt" download="new.txt">下载文本文件</a>
<a href="/download/test2023.rar" >下载压缩文件</a>
<a href="/download/冰墩墩2023.png" download>下载图片文件</a>
</body>
  • 方式二
1. 需要通过 response.setContentType 方法设置 Content-type 头字段的值, 为浏览器无法使用某种方式或激活某个程序来处理的 MIME 类型,例 如 "application/octet-stream" 或 "application/x-msdownload" 等。(设置这个以后,浏览器才会不识别文件而进行下载,否则就会直接识别文件,如文本、图片等)
2. 需要通过 response.setHeader 方法设置 Content-Disposition 头的值 为 "attachment;filename=文件名"   (设置这个以后,浏览器才会出现下载框并有下载文件名字)
3. 读取下载文件,调用 response.getOutputStream 方法向客户端写入附件内容。
  • 前端代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>下载文件</title>
</head>
<body>
   <form action="download1">
       请输入要下载文件的文件名:
       <input type="text" name="fileName" placeholder="请输入要下载的文件名"/><br>
       <input type="submit" value="下载"/>
   </form>
</body>
</html>

  • servlet后端
package com.msb.servletDemo;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author Mr Zeng
 * @version 1.0
 * @date 2023-08-17 21:13
 */
@WebServlet("/download1")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        //获取文件名
        String name = req.getParameter("fileName");
        //获取文件真实路径
        String parentPath = req.getServletContext().getRealPath("/download/");
        File file = new File(parentPath+name);
        //判断文件是否存在
        if(file.exists()){
            //设置请求头
          resp.setContentType("application/x-msdownload");
          resp.setHeader("Content-Disposition","attachment;filename="+name);
          //获取设置响应的输出流
            ServletOutputStream stream = resp.getOutputStream();
            //获取输入流
            FileInputStream inputStream=new FileInputStream(file);
            byte[] bytes=new byte[1024];
            int len=0;
            while ((len=(inputStream.read(bytes)))!=-1){

                stream.write(bytes,0,len);
                 stream.flush();  //刷新
            }

            inputStream.close();
            stream.close();

        }else {
            resp.getWriter().println("下载的文件不存在!!!");
        }

    }
}

12、过滤器

1、Filter 即为过滤器,用于在 Servlet 之外对 Request 或者 Response 进行修改。它主要用于对用户请求进行预处理,也可以对 HttpServletResponse 进行后处理。
2、应用:处理用户权限分配、乱码问题。
3、过滤器的创建过程:
一、编写类实现Filter接口,重新抽象方法doFilter()。
二、为实现类添加@WebFilter([过滤路径]),让过滤器生效。
三、编写servlet类。
  • 单个过滤器的工作原理。
1、启动服务器后初始化过滤器,然后执行doFilter(),每访问一次请求,就执行一次doFilter(),在doFilter()方法中进行拦截前和放行后的操作,关闭服务器就销毁过滤器。

image-20230818092507491

  • 多个过滤器的工作原理
1、若是一个过滤器链:先配置先执行(请求时的执行顺序);响应时: 以相反的顺序执行。
2、通俗点讲就是开启服务器后,先配置的过滤器先初始化,然后后配置的后初始化,然后发起一次请求,先配置的过滤器执行doFilter(),后配置的过滤器接着执行doFilter(),然后放行后,先执行后配置的过滤器放行后操作,然后再执行先配置得到过滤器的放行后操作,最后关闭服务器先销毁先配置的过滤器,后销毁后配置的过滤器。

image-20230818092827807

  • 为所有请求设置UTF-8字符编码案例代码
package com.zwf.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author Mr Zeng
 * @version 1.0
 * @date 2023-08-18 8:59
 */
@WebFilter("/*")  //设置拦截/session/*
public class ServletFilterEncode implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("A过滤器初始化过滤器……");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //进行编码处理
        servletRequest.setCharacterEncoding("UTF-8");
        servletResponse.setCharacterEncoding("UTF-8");
        servletResponse.setContentType("text/pain;charset=utf-8");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("A过滤器放行后处理……");
    }

    @Override
    public void destroy() {
        System.out.println("A过滤器过滤器销毁……");
    }
}

13、监听器

1、监听器实际上是监听Servlet三大域对象(request、session、servletContext)的创建、销毁、动态运行,在创建、销毁、动态运行期间执行一定业务操作设置的对象。
2、应用:在session监听器中监听在线人数等。
3、使用方式
一、创建实现类实现三大域对象监听器接口。
二、重写接口中的抽象方法。
三、使用@WebListener注解激活监听器。
  • 三大域八大监听接口

image-20230818095530241

  • 测试session监听器
1、关闭服务器session销毁,请求一次会话,创建session会话。session钝化需要下超时前设置,超时了session序列化文件就会删除,如果没有超时,钝化了,下次请求可以加载序列化文件在内存中(活化)。
2、同一种浏览器只有一个session,session对象在同一种浏览器中共享数据,除非删除浏览器中cookie才会创建新的session。
  • 创建session钝化和活化的环境
1、配置context.xml文件
<!--
   directory:设置序列化文件存放路径
   maxIdleSwap: 设置多久后钝化  单位s  这里设置的1s后钝化
   -1表示立即钝化
   saveOnRestart=true 表示重启后保存序列化文件
-->
<Context>
<Manager className="org.apache.catalina.session.PersistentManager"  maxIdleSwap="1" >
    <Store className="org.apache.catalina.session.FileStore" directory="D:\Tomcat\tomcat9\conf\session"/>
</Manager>
</Context>
2、对象实现序列化接口,并实现session钝化监听器接口。
3、对象存进session中。
4、在没有配置session钝化设置文件时,正常关闭服务器session会进行钝化操作,序列化文件放在tomcat的${TomcatPath}\work\Catalina\localhost\上下文路径名\目录下。(IDEA无法完成此操作,只有把IDEA中out文件夹的项目放在tomcat的webapps目下,DOS窗口启动服务器进行访问。)在未到超时情况下,启动服务器,session会自动进行活化。
5、正常关闭后session序列化后文件
  • 测试代码
//前提要是实现序列化接口
public class suser implements Serializable, HttpSessionActivationListener {
    private int sno;
    private String sname;
    private int age;
    private String address;

    public suser() {
    }

    public suser(int sno, String sname, int age, String address) {
        this.sno = sno;
        this.sname = sname;
        this.age = age;
        this.address = address;
    }

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        System.out.println(se.getSession().getId()+"session对象钝化了!!!!");
    }

    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        System.out.println(se.getSession().getId()+"session对象活化了!!!!");
    }

}

         //对象存进session域中

        HttpSession session = req.getSession();
        suser suser = new suser(120104,"张三",25,"北京");
        session.setAttribute("suser",suser);

  • 编写在线人数案例
@WebListener
public class sessionListenerDemo implements HttpSessionListener {
    private int onlineNumber=0;
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        //因为多个session可以访问在线人数 所以要存储在application域中
        ServletContext context = se.getSession().getServletContext();
          onlineNumber++;
          context.setAttribute("countNumber",onlineNumber);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext context = se.getSession().getServletContext();
        onlineNumber--;
        context.setAttribute("countNumber",onlineNumber);
    }

}

14、JSP技术

JSP(全称Java Server Pages)是由Sun Microsystems公司主导创建的一种动态网页技术标准。JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成HTML、XML或其他格式文档的Web网页,然后返回给请求者。JSP技术以Java语言作为脚本语言,为用户的HTTP请求提供服务,并能与服务器上的其它Java程序共同处理复杂的业务需求。
JSP将Java代码和特定变动内容嵌入到静态的页面中,实现以静态页面为模板,动态生成其中的部分内容。JSP引入了被称为“JSP动作”的XML标签,用来调用内建功能。另外,可以创建JSP标签库,然后像使用标准HTML或XML标签一样使用它们。标签库能增强功能和服务器性能,而且不受跨平台问题的限制。JSP文件在运行时会被其编译器转换成更原始的Servlet代码。JSP编译器可以把JSP文件编译成用Java代码写的Servlet,然后再由Java编译器来编译成能快速执行的二进制机器码,也可以直接编译成二进制码。
其实 Jsp 本质就是一个 Servlet,当我们第一次访问Jsp的时候,Jsp引擎都会将这个Jsp翻译成一个Servlet进行执行代码。
  • JSP注释
1、显性注释:可以在前端页面上展示的注释。
<!---->
2、隐性注释:不能在前端页面上展示的注释。
jsp注释:<%----%>
java注释://  /**/

一、Scriptlet脚本小程序

      <%! /*定义全局变量*/%>  //在servlet中执行定义变量
      //直接输出,相当于out.print();
      <%="你好"%> //在servlet中执行out.print();
      <%/*编写java代码  定义局部变量*/%>  //在servlet中执行
  • 静态引入和动态引入
静态引入是多个文件最终会在一个servlet中执行,重复的页面会被覆盖,效率高,代码耦合度也高。
动态引入是各个页面单独执行,互相调用,重复页面不会被覆盖,每个页面生成各自的字节码文件,效率低,代码耦合度低。
  • 测试代码
<%--静态引入 page1.jsp已经定义了局部变量a --%>
<%@include  file="page1.jsp"%>
<%
//    int a=20;  //无法定义局部变量
  %>
<%@include  file="page2.jsp"%>

<%--动态引入  双标签内如果没有参数 不能有空格--%>
<%
    String str="admin";
%>
<%--name属性不能使用scriptLet表达式 而value可以使用--%>
<jsp:include page="page1.jsp"></jsp:include>
<jsp:include page="page2.jsp">
    <jsp:param name="username" value="<%=str%>"/>
</jsp:include>
<%--page2页面中可以在scriptLet标签内用java代码获取属性值--%>
<%
     String username=request.getParamter("username");
%>

二、jsp四大域对象

pageContext:页面中的数据共享,页面跳转数据失效。
request:服务端请求的数据共享(请求转发),客户端请求数据共享失效。  
session:客服端和服务端都可以实现数据共享。
ServletContext:整个项目jsp页面数据共享。
jsp标签实现请求转发:<jsp:forward page="page1.jsp"></jsp:forward>
  • 代码测试
   pageContext.setAttribute("username","小曾");
    request.setAttribute("req","小赵");
    session.setAttribute("ses","小王");
    application.setAttribute("app","小李");

   <%--获取pageContext中的对象--%>
   ${username}
<%--服务器跳转--%>
<jsp:forward page="page4.jsp"></jsp:forward>
 
//page4页面如下:
<%--可以获取session和重定向request转发的数据
        username是pageContext域中的数据 跳转页面无法获取
     --%>
   ${username}
     <%--获取request请求的数据--%>
   ${req}
<%--获取session数据--%>
   ${ses}
  <%--获取application域数据--%>
   ${app}

三、jsp九大内置对象(可以直接使用,不用实例化)

image-20230819095206944

  • 注意:如果要使用exception内置对象,必须把页面设置为错误页面 isErrPage=truem,其他内置对象直接使用
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="error.jsp" pageEncoding="UTF-8" isErrPage=true%>   
<%
        //使用内置对象 exception打印异常信息
        String message = exception.getMessage();
        out.print("错误信息是:"+message);
    %>
  • jsp页面头部声明属性
常用属性:contextType:浏览器请求头文件声明浏览器展示的文本类型和字符编码
        language:声明此页面用java语言编写
        errorPage:声明如果页面执行出现异常,跳转到的页面。
        pageEncodeing:声明页面字符编码
        isErrPage:声明页面是异常跳转页面,也是使用exception内置对象必须声明的属性。
        import:导入java类。
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="error.jsp" pageEncoding="UTF-8" import="java.util.List"%>

四、EL表达式

1、EL表达式主要是用于简化输出展示值的java代码,直接在里面编码name属性就可以获取四大域对象存储的值。
2、表达式:${expression}
3、使用EL表达式获取域数据的时候,如果没有指明作用域,那会按照作用域由小到大的顺序去找,直到找到为止:pageContext ---> request ---> session ---> application
4、当域对象全找完了还未找到则返回空字符串""。
  • EL对域对象中的值直接操作
<%  
pageContext.setAttribute("username","小曾");
    request.setAttribute("req","小赵");
    session.setAttribute("ses","小王");
    application.setAttribute("app","小李");
%>
<%--可以获取session和重定向request转发的数据
        username是pageContext域中的数据 跳转页面无法获取
     --%>
   ${username}
     <%--获取request请求的数据--%>
   ${req}
<%--获取session数据--%>
   ${ses}
  <%--获取application域数据--%>
   ${app}
//EL表达式取对象值
<%
        List<String> list=new ArrayList<>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        request.setAttribute("list",list);
     
        Map<String,Object> map=new HashMap<>();
          map.put("sno",1002);
          map.put("age",18);
          map.put("address","北京");
          request.setAttribute("maps",map);

     //        如果实体类中的属性是私有化  必须加上get方法  否则取不出值
        User user=new User("1001","张三",18,"北京");
        request.setAttribute("user",user);

    %>

     <%--EL表达式进行取值--%>
      ${list[0]},
      ${list[1]},
      ${list[2]},

      ${maps.name}<br>
      ${maps["age"]}

      ${user}<br>
      ${user.name}
  • 运算符使用
可以直接在${}进行运算。
+-*/运算,但是需要注意的一点是使用+号只是单纯的用于数值计算,不能用于字符串拼接,如果是数值字符型会自动转为数值进行运算。
比较运算符: ==  equ 
不为空:${empty 变量}返回布尔型  如果变量是一个空字符串或者null返回true  如果是一个集合,只要没有添加值就返回true。 如果是自定义对象,只要是null返回true。
逻辑运算符:! || && >= = <=   between and

五、JSTL标签

前提需要导入jstl-api.jar和standard.jar两个包。
JSTL标签是对EL表达式的补充,进一步简化<%%>里的java代码,大致可以分为三大类:条件动作标签、格式化动作标签、迭代动作标签。
条件动作标签:<c:if test="${}"> <c:/if>  
<c:choose>
<c:when test=""> 
<c:/when>
<c:otherwise>
<c:/otherwise>
<c:/choose>
迭代动作标签:
<c:foreache item="" var="" begin="" end="" step=""  >
<c:foreache>
格式化动作标签:
<fmt:formatNumber>
<fmt:formatDate>
<fmt:parseNumber>
<fmt:parseDate>
  • 条件动作标签测试代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导入jstl标签核心标签库和动作标签库--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>测试jstl标签</title>
</head>
<body>
        <%
            request.setAttribute("score",78);

        %>
<%--  scope表示jsp四大域,var表示接收变量--%>
     <c:if test="${score<60}">
         成绩不及格!
     </c:if>
        <c:if test="${score>=60&&score<70}" >
            成绩及格!
        </c:if>
        <c:if test="${score>=70&&score<80}" >
            成绩良好!
        </c:if>
        <c:if test="${score>=80&&score<=100}">
            成绩优秀!
        </c:if>
       <c:choose>
         <c:when test="${score<80}">
             成绩在80分以内!
         </c:when>
       <c:when test="${score>80}">
            成绩超过80分!
       </c:when>
       <c:otherwise>
           没有成绩数据!
       </c:otherwise>
   </c:choose>

</body>
</html>
  • 迭代动作标签测试代码
<%@ page import="java.util.List" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Map" %><%--
  User: Mr Zeng
  Date: 2023/8/19
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>测试迭代动作标签</title>
</head>
<body>
    <%
        List list=new ArrayList();
        list.add(121);
        list.add(1123);
        list.add(1546);
        list.add(12562);
        list.add(1213);
        list.add(12135445);
        pageContext.setAttribute("list",list);
        pageContext.setAttribute("str","abcd#efgh#ijlm");
        Map map=new HashMap();
        map.put("name","小曾");
        map.put("age",23);
        map.put("job","程序员");
        pageContext.setAttribute("map",map);
    %>
<%--items表示获取迭代的key  var表示接收的变量  varStatus表示变量数据类型--%>
     <c:forEach items="${list}" var="i" varStatus="int">
               ${i},
     </c:forEach>
    <br>
     <%--直接迭代输出数值--%>
     <c:forEach begin="1" end="10" var="i" step="2">
         ${i}
     </c:forEach>
      <br>
<%--如果迭代字符串用,分割  则会自动分割--%>
    <c:forEach items="${str}" var="s">
        ${s}
    </c:forEach>
<%--如果其他符号分割需要指定分割的符号--%>
   <c:forTokens items="${str}" delims="#" var="s">
       ${s}
   </c:forTokens>
    <hr>
<%--迭代输出map集合--%>
   <c:forEach items="${map}" var="m">
       ${m.key}--------->${m.value}
   </c:forEach>
</body>
</html>

  • 测试格式化动作标签
<%
    Date date = new Date();
    request.setAttribute("date",date);
%>
<%--设置时区是美元--%>
<fmt:setLocale value="en_US" scope="page"/>
<%--数值转型 默认转为人民币数值¥--%>
<fmt:formatNumber type="currency" value="120121012"/><br>
<%--字符串1231转成数值型 用于转表单存储的数据 表单输入的数据是字符串类型--%>
<fmt:formatNumber type="number" value="1231"/>
<%--日期按照相应格式转字符串 pattern表示字符格式--%>
<fmt:formatDate value="${date}" pattern="yyyy-MM-dd HH:mm:ss"/><br>
<%--字符串2000-01-16会自动转日期--%>
<fmt:parseDate value="2000/01/16" type="date" pattern="yyyy/MM/dd"/>
<fmt:parseDate value="2000-01-16" type="date" pattern="yyyy-MM-dd"/>
<%--货币或数字转字符串 type:表示传入的值所属类型 number数值型 percent百分数 currency货币--%>
<fmt:parseNumber type="number" value="12121"/>
<fmt:parseNumber type="percent" value="100%"/>
<fmt:parseNumber type="currency" value="$120151"/>

六、MVC三层架构

MVC三层架是model、view、controller,view视图层采用jsp技术,model层采用jdbc技术,controller层采用servlet技术。
业务设置:用户进行登录操作,如果登录失败跳转到登录页并提示信息,登录成功跳转到首页,如果直接进入首页进行拦截并重定向到登录页,如果直接发起登录请求也拦截并跳转到错误页。
image-20230819155737657
  • 模拟登录跳转代码
  1. Servlet请求代码
package com.zwf.controller;

import com.zwf.service.LoginService;
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 javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author Mr Zeng
 * @version 1.0
 * @date 2023-08-19 16:13
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {

   private final LoginService SERVICE=new LoginService();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String pwd=req.getParameter("password");
        boolean login = SERVICE.Login(username, pwd);
        String path = req.getContextPath();
        HttpSession session = req.getSession();
        String username1 =(String)session.getAttribute("username");
        if(login){
            req.setAttribute("username",username);
            session.setAttribute("username",username);
            req.getRequestDispatcher("/index.jsp").forward(req,resp);
          }else {
            System.out.println(username);
            System.out.println(pwd);
            System.out.println(username1);
            if(username!=null||pwd!=null){
                if(!"".equals(username)||!"".equals(pwd)){
                    req.setAttribute("info","用户名或密码错误,请核对密码再进行登录!");
                    req.getRequestDispatcher("/login.jsp").forward(req,resp);
                }
            }else{
                if(username1==null||"".equals(username1)){
                    resp.sendRedirect(path+"/error.jsp");
                }else {
                    resp.sendRedirect(path+"/index.jsp");
                }

            }

        }

    }
}
  1. Service层代码
package com.zwf.service;

import com.zwf.dao.DataDao;
import com.zwf.pojo.LoginUser;

/**
 * @author Mr Zeng
 * @version 1.0
 * @date 2023-08-19 16:13
 */
public class LoginService {

    private  final DataDao DAO=new DataDao();
    public boolean Login(String username,String password) {
        boolean flag = false;
        LoginUser loginUser = DAO.queryFind(username, password);
        if (loginUser != null) {
            flag = true;
        }
        return flag;
    }
}
  1. dao层代码
package com.zwf.dao;

import com.zwf.pojo.LoginUser;
import com.zwf.utils.SqlUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * @author Mr Zeng
 * @version 1.0
 * @date 2023-08-19 16:12
 */
public class DataDao {
    private  Connection conn=null;
    private PreparedStatement statement=null;
    private ResultSet rs=null;
    public LoginUser queryFind(String username,String password){
        LoginUser us=null;
        conn = SqlUtils.getConnection();
        String sql="select * from login_user where username=? and password=?";
        try {
          statement=conn.prepareStatement(sql);
          statement.setString(1,username);
          statement.setString(2,password);
            rs = statement.executeQuery();
            while (rs.next()){
                us =new LoginUser();
                us.setUid(rs.getInt(1));
                us.setPassword(rs.getString(3));
                us.setUsername(rs.getString(2));
            }
            return us;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            SqlUtils.conClose(conn,statement,rs);
        }
    }
    
}
  1. 工具类
package com.zwf.utils;

import java.sql.*;

/**
 * @author Mr Zeng
 * @version 1.0
 * @date 2023-08-19 16:14
 */
public class SqlUtils {
    private static Connection connection = null;
    private static final String URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
    private static final String USER = "SCOTT";
    private static final String PASSWORD = "tiger";

    static {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

    }

    public static Connection getConnection() {
        try {
            return connection = DriverManager.getConnection(URL, USER, PASSWORD);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public static void conClose(Connection con, Statement state, ResultSet rs) {
        if (con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (state != null) {
            try {
                state.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }

        }
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void conClose(Connection con, Statement state) {
        conClose(con, state, null);
    }
}

  1. 过滤器
package com.zwf.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Mr Zeng
 * @version 1.0
 * @date 2023-08-19 17:55
 */
public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request=(HttpServletRequest)servletRequest;
        HttpServletResponse response=(HttpServletResponse)servletResponse;
        String username = (String) request.getSession().getAttribute("username");
        System.out.println(username);
        String path = request.getContextPath();
        if(username==null||"".equals(username)){
              response.sendRedirect(path+"/error.jsp");
              return;
          }

        filterChain.doFilter(servletRequest,servletResponse);
    }
}
  1. web.xml文件注册过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <filter>
        <filter-name>encode</filter-name>
        <filter-class>com.zwf.filter.EncodeFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>encode</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>login</filter-name>
        <filter-class>com.zwf.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>login</filter-name>
        <url-pattern>/index.jsp</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
</web-app>