JavaWeb

Tomcat

概述

特殊的Servlet容器,开启服务后可通过访问本地ip获取文档;WebApps目录下为网站下的资源,可通过域名后加"/"定位;每个资源为一个网站页面,包括一个index.html或者index.jsp代码的主页,和一个WEB-INF目录储存相关依赖包,多种类以及配置文件;

Http请求流程

分析一个http://localhost:8080/docs/api 请求。

第一步:连接器监听的端口是8080。由于请求的端口和监听的端口一致,连接器接受了该请求。

第二步:因为引擎的默认虚拟主机是 localhost,并且虚拟主机的目录是webapps。所以请求找到了 tomcat/webapps 目录。

第三步:解析的 docs 是 web 程序的应用名,也就是 context(Application Context:只是url后缀而已)。

第四步:解析的 api 是具体的业务逻辑地址。此时需要从 docs/WEB-INF/web.xml 中找映射关系,最后调用具体的函数。


Maven

约定大于配置,抽象设计理念,符合直觉且合理,减少团队内耗;

安装

maven.apache.org

镜像

阿里云Maven中央仓库 为 阿里云云效 提供的公共代理仓库,帮助研发人员提高研发生产效率,使用阿里云Maven中央仓库作为下载源,速度更快更稳定。

Maven 配置
打开 Maven 的配置文件(windows机器一般在maven安装目录的conf/settings.xml),在标签中添加 mirror 子节点:

<mirror>
    <id>aliyunmaven</id>
    <mirrorOf>*</mirrorOf>
    <name>阿里云公共仓库</name>
    <url>https://maven.aliyun.com/repository/public</url>
</mirror>

环境变量配置

变量名MAVEN_HOME,值为安装地址
变量名M2_HOME,值为安装地址下bin目录

本地仓库配置

conf下的settings.xml

<localRepository>E:\Maven\apache-maven-3.8.4\repository</localRepository>


新建Maven项目

GAV : GroupId, AtifactsId,Version,在POM.XML文件里说明项目信息;

Maven仓库,用来导入dependencies到pom(项目对象模型)


Servlet

Sun公司的第一代动态Web开发接口,实现了Servlet接口即为Servlet应用;在Web开发时往往以一个空白project为父模块,在其目录下建新的Web模块;之后在父模块POM里会有module目录生成,同时父模块的依赖可以被使用(前提Scope设定)。

请求响应过程

生命周期:init > service > destroy

Servlet容器(Tomcat)接收到客户端请求,解析请求协议,如果servlet程序还没有被加载,就会执行>加载过程<并调用service()方法,否则直接调用service()方法。

其中,>加载过程<为Servlet容器调用init()方法将Servlet类载入内存,并产生Servlet实例。在调用init()方法的时候,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化。该过程只会被执行一次,即在一个应用程序中,每类Servlet程序只能有一个实例。

service()的过程:由Servlet容器解析请求参数并封装成一个ServletRequest和ServletResponse对象。Servlet容器把ServletRequest和ServletResponse作为参数传递给了service()方法,通过执行service()方法,实现响应的逻辑,并通过ServletResponse对象返回内容到客户端。

最后,调用destroy()。

首次访问Servlet

最终成果
在这里插入图片描述

Web.XML的配置

因为浏览器连接服务器,此配置实质就是在配置服务器的映射代码;

<?xml version="1.0" encoding="UTF-8"?>
<!-- 从Tomcat的web.xml中复制过来的版本配置,否则版本WebApps过低-->
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                      https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0"
         metadata-complete="true">

    <request-character-encoding>
        UTF-8
    </request-character-encoding>
	<!-- 设置了firstServlet下为FirstServlet类(必须继承HttpServlet)-->
    <servlet>
        <servlet-name>firstServlet</servlet-name>
        <servlet-class>FirstServlet</servlet-class>

    </servlet>
    <!-- 设置映射,/testing保证了url下此文档为名为firstServlet的servlet -->
    <servlet-mapping>
        <servlet-name>firstServlet</servlet-name>
        <url-pattern>/testing</url-pattern>
    </servlet-mapping>


</web-app>

servelet类,动态请求渲染页面

//注意依赖为Jakarta,instead of javax.servelet
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

public class FirstServlet extends HttpServlet {
//注意方法为public,否则405
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setCharacterEncoding("utf-8");//防止乱码
        {
            resp.setContentType("text/html");
            PrintWriter out = resp.getWriter();//获取输出流
            out.println("<html>");
            out.println("<head>");
            out.println("<title>TEST!!!</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Everything's worth of it!凸(艹皿艹 )</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }

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

Mapping

web.xml下的servlet-mapping标签下的url-parttern,可以加通配符,但是优先级低于固有路径

ServletContext

Servlet容器的上下文环境,参考进程上下文环境,其内一个个线程即类似一个个的Servlet服务类,可共享参数(.setAttribute(string:K,object:V)),传递配置文件(.getSourceAsInputStream(相对路径)),转发服务(.dispatcher("/new_url",context.forward()))等等;

下载实现

public class FileDownload extends HttpServlet
{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String path = "C:\\Users\\lenovo\\Desktop\\2.jpg";
		//resp.setHeader("refresh","5");每五秒刷新后台
        //设置响应头,响应下载格式并提供文件名
        resp.setHeader("Content-Disposition","attachment;filename=" + path.substring(path.lastIndexOf("\\")));

        File file = new File(path);
        byte[] buffer = new byte[1024]; //in和out流间的缓冲字节数组

        FileInputStream in = new FileInputStream(file);//从文件读取的流

        int length = 0;//记录读入长度

        ServletOutputStream out = resp.getOutputStream();//向浏览器输出的流

        while ((length = in.read(buffer)) > 0) //从输入流read进buffer,由于进程异步性,不能一次读取完毕,设置length表示读取长度

        {
            out.write(buffer,0,length);//从buffer读取字节写出到输出流
        }

    }
}

转发和重定向

目的是在不同servlet间流转,形成不同服务间的切换;

重定向:sendRedirect(绝对url或者/相对url);迭代式
转发:getDispcher(绝对url或者/相对url).forward(req,resp); 递归式

Cookie

  • 通过req获取;resp.addCookie(“key”,“value”);
  • 存在maxAge过期时间,以设定0maxAge函数使用户能够主动消除客户端cookie;
  • 以本地浏览器为主体,保存在本地浏览器缓存中,不以客户端的关闭访问为结束;

Session

  • 在web.xml中可配置session过期时间,或是在session对象的MaxInactiveTime中,一个是分钟一个是秒;
  • 以服务端(web服务器)为主体,浏览器关闭访问session就结束了;
  • 以JsessionID为cookie的基础,通常这个cookie设为-1MaxAge,即为即时会话;

JSP

  • 本质就是Servlet,在Tomcat容器加载请求时,work目录下的index.java存有jsp的相应Servlet程序,就是吧jsp里的各种标签代码加载成Servlet样式再执行这个Servlet向网站交互,提供渲染;可以和html互动,但本质还是转换成out.write写出html标签格式,以及伴随的java代码。

一些标签

  • <%-- annotation --%>在前端不展示, <% java programming code %>service方法内部加载;
  • <%! global variables %>在jsp类内部加载, <%= recall methods or variables %>
  • <%@ include file="…/header.jsp"%>,<jsp:include page = “…/header.jsp”>;二者区别就是前者把header.jsp的代码加进来,后者只是引入jsp文件;
  • 展示error页面,第一种方法可在web-xml里配置标签,里面有code和location等属性可配置;第二种方法可以在jsp命令标签添加<%@ page error-page = “…/error.jsp”%>;
  • <jsp:param name = “xx” value = “xx”></jsp:param>参数参数,<jsp:forward page="/xxx.jsp"></jsp:forward>转发标签,内部可嵌套参数标签
  • Express Language表达式${使用请求对象获取参数};

JSP内置对象作用域

  • Application(ServletContext,随服务器作用域)
  • Session(会话,随浏览器作用域)
  • Request(请求作用域)
  • PageContext(当前页作用域),可forward()转发,可setScope设置提升作用域;
  • 上四个内置对象都可setAttribute和findAttribute进行参数存取,只是作用域(生命周期)不一样;

JSTL(JAVA STANDARD TAG LIBRARY)

  • 核心标签(core)导入前缀:<%@taglib prefix=“c” uri=http://java.sun.com/jsp/jstl/core %>

EG:

 <c:forEach var="var" items="${value}">
    <c:out value="${var}"> This is from test 1</c:out>
</c:forEach>

其中el表达式代表引用变量,适用参数为引用变量的时候;


MVC

  • MVC指MVC模式的某种框架,它强制性地使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。最典型的MVC就是JSP + servlet + javabean的模式。

Filter过滤器

  • 在服务器与请求的资源间的Servlet类,实现了Servlet包下的Filter接口,存在init,doFilter和destroy三个约束方法分别在服务器加载时初始化,请求资源时执行Filter逻辑以及关闭服务器时销毁;
  • 注意doFilter中的chain参数,在过滤逻辑代码结束时需调用chain.doFilter(req,resp),以在多个过滤器间传递参数,形成多层过滤;
  • 最后不要忘了在web.xml配置filter和filter-mapping,一般url-pattern设置为xxx/*以过滤一个目录资源下的所有请求响应;

登录拦截

  • Filter
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		//强转至http的请求响应对象
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
		//若是没有验证成功就想直接访问主页,重定向至登录页面
        if(req.getSession().getAttribute("id") == null) {
            resp.sendRedirect("/index.jsp");
            System.out.println("filtered");
        }

        filterChain.doFilter(servletRequest,servletResponse);
    }
  • Servlet验证类
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username;
		//传回的用户名不为空的情况下判断是否为“administrator”
        if(req.getParameter("username") != null) {
            username = req.getParameter("username");
            System.out.println(username);
            if(username.equals("administrator"))
            {   //是的话定向至主页并且对session进行绑定id,进而方便过滤直接访问情况
                req.getSession().setAttribute("id",req.getSession().getId());
                resp.sendRedirect("/home.jsp");
            }
            else
                resp.sendRedirect("/error.jsp");
        }
        else
            resp.sendRedirect("/error.jsp");
    }
  • 登录页面的action注意是web.xml里配置的mapping-url,不能写jsp或者Servlet类;

Listener监听器

  • 大量接口描述监听内容,对象等等,例如SessionListener,统计会话数量,得到当前访问人数。
  • 在we.xml中只需配置一个listener-calsses即可被动生效。

项目整合

架构设计

  • View层:多个JSP展示与用户的交互,提供接收数据的容器;
  • Service层:多个业务逻辑Servlet桥接数据与持久化层;
  • Model层:Dao数据持久化,提供与数据库的交互,CRUD等等;
  • 总体来说就是前端的多个JSP静态资源以及JS组成了少部分逻辑编写,例如判断新旧密码是否相等;其次在Servlet包下的多个Servlet逐一实现了系统的逻辑功能,通过调用Service层的业务类中二次调用Dao层持久化功能函数,实现对数据库的CRUD,达到诸如登录验证,密码修改,订单查询等功能。

登录验证

  • 由前端返回的登录请求携带的用户名和密码,调用Service.login(用户名,密码)二次调用Dao实现类中的getUser通过封装的工具类Connector.query查询有无该用户并返回结果集或null,之后在Dao层建立返回的User实体类交给Service层后判断密码是否正确,最后返回该用户,并在Servlet层添加该用户至Session后重定向至主页,否则设置登录失败参数转发回登录页面;
  • 需要注意的是各层返回值为空的问题,需要频繁地非空验证;

退出

  • 移除Session中的user信息,并且重定向至登录页面;
  • 需要注意的是权限验证问题,通过Filter验证Session中有无当下User参数来判断是否有人想通过返回指定url访问功能页,如果有的话设定请登录参数,转发回到登录页面;

密码修改

  • 底层执行Dao实现类调用的Connector.update执行修改sql,成功后返回true,在Servlet层移除session并携密码已修改参数转发至登录页面,失败则刷新当前页面,提示修改失败;
  • Servlet复用,通过前端隐藏域的参数提交在统一Servlet中进行分支判断走不同的功能方法;
  • 新旧密码验证通过修改密码jsp引入的js代码实现,其中旧密码验证用失焦判断Ajax方法执行异步请求与数据库交互,通过对旧密码的各种判断put进map里不同参数后以JSON形式响应返回,最后在前端以不同CSS样式实时提醒用户旧密码是否正确等;

用户查询

  • 点击用户查询时,不同于之前配置webxml后走Servlet提交表单再返回结果,该点击的请求额外夹带了method为query的参数使页面加载时直接显示结果;
  • 动态SQL,根据页面是否填写参数对SQL进行append多个where条件进而返回不同的结果集;

文件上传

  • 为保证服务器安全(外界访问),上传的文件应该保存在Web-Inf下(外界不可通过url访问),一般通过file对象的mkdir方法在此建立两个目录,uploadedFiles和temp,用来储存文件和临时文件(会被清理的文件)
  • 前端html须加上"multi-part/form-data判断",同时后端接收时也需要判断有无此字段
  • 必须使用post请求,因为get限制大小,此外文件也需要可以限制大小或者后缀
  • 需要ServletFileUpload类,而它又需要DiskFileItemFactory对象最为构造参数(工厂代理)
  • 利用ServletFileUpload对象的parseRequest方法解析请求,返回表单对象list,遍历并判断是否为携带文件的提交对象
  • 通过输入流进缓存数组,输出流到目标目录,上传的指定位置

邮件发送

  • 利用多线程跑诸如邮件等访问控制服务器的业务,在前端直接写回结果,即可满足“三秒网站”准则
  • POP3协议 = 用户离线服务器缓存接受后在登录是时候转发
  • SMTP协议 = 利用TCP在多种邮箱服务器间转发
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DefinedBySaint

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

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

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

打赏作者

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

抵扣说明:

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

余额充值