05【JSP-MVC】

news2024/11/27 7:38:02

文章目录

  • 05【JSP-MVC】
  • 一、JSP简介
    • 1.1 JSP概述
      • 1.1.1 HTML和Servlet的弊端
      • 1.1.1 什么是JSP
    • 1.2 JSP体验:
      • 1.2.2 JSP的执行过程
      • 1.2.2 JSP和Servlet是什么关系?
  • 二、JSP的脚本元素
    • 2.1 JSP中的注释:
    • 2.2 JSP脚本表达式
    • 2.3 JSP代码片段
    • 2.4 JSP声明
    • 2.5 JSP页面的三种脚本小结:
    • 2.6 pageContext域
      • 2.6.1 页面域
      • 2.6.2 页面域测试:
    • 2.7 JSP九大内置对象
      • 2.7.1 Request对象
      • 2.7.2 Response对象
      • 2.7.3 Out对象
      • 2.7.4 Session对象
      • 2.7.5 Application对象
      • 2.7.6 PageContext对象
      • 2.7.7 Config对象
      • 2.7.8 Page
      • 2.7.9 Exception对象
  • 三、EL表达式
    • 3.1 EL表达式的作用
      • 3.1.1 什么是EL
      • 3.1.2 EL表达式的作用:
    • 3.2 获取数据
      • 3.2.1 指定域获取数据
      • 3.2.2 示例:取出不同作用域中的值
      • 3.2.3 小结:从四个作用域中取值
    • 3.3 EL表达式获取不同类型的数据
    • 3.4 练习题:
  • 四、EL中使用表达式
    • 4.1 算术表达式 :
    • 4.2 比较表达式
    • 4.3 逻辑表达式 :
    • 4.4 三元运算:
    • 4.5 判空表达式:
    • 4.6 使用上面所有的运算符
  • 五、核心标签库
    • 5.1 JSTL标签库
      • 5.1.1 JSTL使用步骤
    • 5.2 判断标签\<c:if\>
    • 5.3 多分支标签choose
    • 5.4 遍历标签`<c:forEach>`
      • 5.4.1 参数
      • 5.4.2 varStatus属性:
      • 5.4.3 遍历集合:
      • 5.4.4 遍历数组和Map:
  • 六、三层架构与MVC
    • 6.1 JavaWEB发展史
      • 6.1.1 Model1
      • 6.1.2 Model2 第一代
      • 6.1.2 Model2 第二代
    • 6.2 什么是MVC
      • 6.1.1 JavaWeb对MVC的实现
    • 6.3 三层架构开发模式
    • 6.4 MVC中的三层
  • 七、综合案例:完成用户显示列表案例
    • 7.1 案例需求
    • 7.2 案例效果
    • 7.3 实现步骤
      • 7.3.1 执行SQL语句
      • 7.3.2 导入jar包、配置文件、实体类和工具类
      • 7.3.3 数据源工具类
      • 7.3.4 验证码类
      • 7.3.5 用户登录
        • 7.3.5.1 登录页面
        • 7.3.5.2 LoginServlet:
        • 7.3.5.3 UserService:
        • 7.3.5.4 UserDao
      • 7.3.6 用户列表
        • 7.3.6.1 列表页面
        • 7.3.6.2 ListServlet:
        • 7.3.6.3 UserService:
        • 7.3.6.4 UserDao

05【JSP-MVC】

一、JSP简介

1.1 JSP概述

1.1.1 HTML和Servlet的弊端

我们之前学习过HTML和Servlet,HTML属于静态资源,专门用于布局页面,方便页面美化操作,写JS脚本和CSS代码都比较方便,但是由于HTML是静态资源,不能制作动态的内容。

后来我们学习了Servlet,Servlet属于动态资源,可以编写Java脚本,让网友具备更多的动态交互感;但Servlet的缺点也非常明显,那就是不方便编写HTML/CSS/JS等前端代码;

  • 我们来观察一下Servlet编写的一个布局:
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.io.PrintWriter;
import java.util.Arrays;
import java.util.List;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo01")
public class Demo01Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       
        // 模拟从数据库里面查询
        List<String> mountains_01 = Arrays.asList("庐山", "黄山", "雁荡山");
        List<String> mountains_02 = Arrays.asList("东岳泰山", "西岳华山", "南岳衡山", "北岳恒山", "中岳嵩山");

        response.setContentType("text/html;charset=utf8");
        PrintWriter out = response.getWriter();
        out.println("  <head>\n" +
                "    <title>demo</title>\n" +
                "    <style>\n" +
                "      .s1{\n" +
                "        color:blue;\n" +
                "      }\n" +
                "      .s2{\n" +
                "        color:gold;\n" +
                "      }\n" +
                "    </style>\n" +
                "  </head>");

        out.println("<h2>三山<h2>");
        out.println("<ul class='s1'>");
        for (String mountain : mountains_01) {
            out.println("<li>" + mountain + "</li>");
        }
        out.println("</ul>");
        out.println("<hr>");


        out.println("<h2>五岳<h2>");
        out.println("<ul class='s2'>");
        for (String mountain : mountains_02) {
            out.println("<li>" + mountain + "</li>");
        }
        out.println("</ul>");
    }
}

访问:http://localhost:8080/demo01

在这里插入图片描述

总结:

  • HTML:
    • 优点:方便页面美化操作,写JS脚本和CSS代码都比较方便;
    • 缺点:不能制作动态的内容;
  • Servlet:
    • 优点:可以制作动态内容;
    • 缺点:不方便写CSS和JS代码;

1.1.1 什么是JSP

JSP(全称JavaServer Pages)是由[Sun Microsystems](https://baike.baidu.com/item/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编译器来编译成能快速执行的二进制机器码,也可以直接编译成二进制码。

Tips:JSP本质上就是一个Servlet,属于动态技术;

  • 快速体验JSP:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>测试页面</title>
    <style>
        h1 {
            color: red;
        }
    </style>
</head>
<body>
<h1>我是HTML代码</h1>
<%
    System.out.println("我是Java代码");
%>
</body>
</html>

观察idea控制台的输出语句;

1.2 JSP体验:

JSP既有HTML的优点,方便制作和美化。又可以在页面写Java代码,可以制作动态内容。

  • 快速体验JSP:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>测试页面</title>
    <style>
        h1 {
            color: red;
        }
    </style>
</head>
<body>
<h1>我是HTML代码</h1>
<%
    System.out.println("我是Java代码");
%>
</body>
</html>

1.2.2 JSP的执行过程

JSP首先会将代码翻译成Servlet的Java代码,然后再编译成字节码文件执行。

在这里插入图片描述

  • Servlet生成的位置:

C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Tomcat_8_0_43_06_JSP_EL_JSTL_MVC\work\Catalina\localhost\01_jsp\org\apache\jsp

在这里插入图片描述

1.2.2 JSP和Servlet是什么关系?

查看源码:

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase

public abstract class HttpJspBase extends HttpServlet

在这里插入图片描述

在这里插入图片描述

我们写的JSP在最后都会被翻译成Servlet,也就是说JSP实质上就是一个Servlet

  • 那么JSP什么时候翻译成Servlet?生成多少次?

浏览器第一次访问JSP的时候,由Tomcat将JSP翻译成了Servlet,并且编译成字节码文件,生成1次。

我们的代码运行在_jspService()方法中

  • HTML代码: 通过out通过直接write()输出

  • Java代码:原样放在翻译以后的Servlet中

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/8.0.43
 * Generated at: 2022-05-05 01:09:56 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
        implements org.apache.jasper.runtime.JspSourceDependent,
        org.apache.jasper.runtime.JspSourceImports {

    private static final javax.servlet.jsp.JspFactory _jspxFactory =
            javax.servlet.jsp.JspFactory.getDefaultFactory();

    private static java.util.Map<java.lang.String, java.lang.Long> _jspx_dependants;

    private static final java.util.Set<java.lang.String> _jspx_imports_packages;

    private static final java.util.Set<java.lang.String> _jspx_imports_classes;

    static {
        _jspx_imports_packages = new java.util.HashSet<>();
        _jspx_imports_packages.add("javax.servlet");
        _jspx_imports_packages.add("javax.servlet.http");
        _jspx_imports_packages.add("javax.servlet.jsp");
        _jspx_imports_classes = null;
    }

    private volatile javax.el.ExpressionFactory _el_expressionfactory;
    private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

    public java.util.Map<java.lang.String, java.lang.Long> getDependants() {
        return _jspx_dependants;
    }

    public java.util.Set<java.lang.String> getPackageImports() {
        return _jspx_imports_packages;
    }

    public java.util.Set<java.lang.String> getClassImports() {
        return _jspx_imports_classes;
    }

    public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
        if (_el_expressionfactory == null) {
            synchronized (this) {
                if (_el_expressionfactory == null) {
                    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
                }
            }
        }
        return _el_expressionfactory;
    }

    public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
        if (_jsp_instancemanager == null) {
            synchronized (this) {
                if (_jsp_instancemanager == null) {
                    _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
                }
            }
        }
        return _jsp_instancemanager;
    }

    public void _jspInit() {
    }

    public void _jspDestroy() {
    }

    public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
            throws java.io.IOException, javax.servlet.ServletException {

        final java.lang.String _jspx_method = request.getMethod();
        if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
            response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
            return;
        }

        final javax.servlet.jsp.PageContext pageContext;
        javax.servlet.http.HttpSession session = null;
        final javax.servlet.ServletContext application;
        final javax.servlet.ServletConfig config;
        javax.servlet.jsp.JspWriter out = null;
        final java.lang.Object page = this;
        javax.servlet.jsp.JspWriter _jspx_out = null;
        javax.servlet.jsp.PageContext _jspx_page_context = null;


        try {
            response.setContentType("text/html;charset=UTF-8");
            pageContext = _jspxFactory.getPageContext(this, request, response,
                    null, true, 8192, true);
            _jspx_page_context = pageContext;
            application = pageContext.getServletContext();
            config = pageContext.getServletConfig();
            session = pageContext.getSession();
            out = pageContext.getOut();
            _jspx_out = out;

            out.write("\r\n");
            out.write("<html>\r\n");
            out.write("<head>\r\n");
            out.write("    <title>测试页面</title>\r\n");
            out.write("    <style>\r\n");
            out.write("        h1 {\r\n");
            out.write("            color: red;\r\n");
            out.write("        }\r\n");
            out.write("    </style>\r\n");
            out.write("</head>\r\n");
            out.write("<body>\r\n");
            out.write("<h1>我是HTML代码</h1>\r\n");

            System.out.println("我是Java代码");

            out.write("\r\n");
            out.write("\r\n");
            out.write("</body>\r\n");
            out.write("</html>\r\n");
        } catch (java.lang.Throwable t) {
            if (!(t instanceof javax.servlet.jsp.SkipPageException)) {
                out = _jspx_out;
                if (out != null && out.getBufferSize() != 0)
                    try {
                        if (response.isCommitted()) {
                            out.flush();
                        } else {
                            out.clearBuffer();
                        }
                    } catch (java.io.IOException e) {
                    }
                if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
                else throw new ServletException(t);
            }
        } finally {
            _jspxFactory.releasePageContext(_jspx_page_context);
        }
    }
}

二、JSP的脚本元素

2.1 JSP中的注释:

JSP中的三种注释说明
HTML<!-- 注释 --> 只能注释静态内容,不能注释Java代码。 通过浏览查看源代码可以看到的
Java与以前是一样的,在网页中看不到,但在翻译以后Servlet中有。 // 单行注释 /* 多行注释 */ /** 文档注释 */
JSP<%-- 动态内容 --%> 可以注释JSP上任何元素 网页中没有,在生成的Java源代码中也没有
  • 面试题:如果使用HTML注释JSP脚本元素会怎么样?

如:<!-- <%out.print(3*5);%> -->

在网页上看不到内容,但JSP的脚本还是会正常的执行,查看HTML源代码能看到被注释的内容;

2.2 JSP脚本表达式

JSP脚本表达式说明
语法<%= 变量名或表达式 %> 翻译成Servlet变成out.print()打印输出
作用直接输出变量的值或对表达式进行计算
  • JSP代码演示

JSP表达式:

<%
    String name = "张三";
%>
<%=name%> <br>
<%=3*4%><br>

查看翻译后的代码:

在这里插入图片描述

tips:<%=xxx%>采用的是out的print方法输出;

2.3 JSP代码片段

JSP代码片段说明
语法<% 一行或多行Java代码; %> 例:<% String name=‘abc’ %>
作用在JSP的页面上执行一段Java代码,必须符合Java的语法规则。每行代码以分号结束。
  • 演示:在脚本中创建一个ArrayList,添加四个名字,在ol-li中有序列表输出,使用Java中的for循环输出。

  • 执行效果:

在这里插入图片描述

  • 代码:
<body>
<%
    //将一个数组转成List对象
    List<String> names = Arrays.asList("江西", "陕西", "广西", "山西");
%>
<ol>
    <% //for循环输出
        for (String n : names) {
    %>
    <li>
        <%=n%>
    </li>
    <%}%>
</ol>
</body>
  • 生成的Servlet代码:
// 将一个数组转成List对象
List<String> names = Arrays.asList("江西", "陕西", "广西", "山西");

out.write("\n");
out.write("<ol>\n");
out.write("    ");
// for循环输出
for (String n : names) {

    out.write("\n");
    out.write("    <li>\n");
    out.write("        ");
    out.print(n);
    out.write("\n");
    out.write("    </li>\n");
    out.write("    ");
}

2.4 JSP声明

JSP声明说明
语法<%! 全局变量或方法 %>,例:<%! String name='abc' %>
作用用于在JSP页面上声明全局变量或方法
  • 演示:
  1. 在脚本中创建一个字符串,使用表达式输出

  2. 在声明中也创建一个同名的字符,表达式输出,会不会有问题?

  • 代码:
<body>

<%--定义代码片段,代码生成在service方法中--%>
<% String name="张三";%>

<%--定义声明片段,代码生成在类中方法外(成员变量)--%>
<%! String name="李四";%>

<h1>成员变量: <%=this.name%></h1>
<h1>局部变量: <%=name%></h1>
</body>
  • 生成的Servlet代码
package org.apache.jsp;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
        implements org.apache.jasper.runtime.JspSourceDependent,
        org.apache.jasper.runtime.JspSourceImports {

	//  李四在成员变量中
    String name = "李四";

    .....
    
    public void _jspInit() {
    }

    public void _jspDestroy() {
    }

    public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
            throws java.io.IOException, javax.servlet.ServletException {

            response.setContentType("text/html;charset=UTF-8");
            ....

            // 张三在局部变量中
            String name = "张三";

        	out.print(name);
       		out.print(this.name);
            ....
        } catch (java.lang.Throwable t) {
            
        } finally {
        }
    }
}
  • 结论:声明部分声明变量是在类中的成员变量,全局变量。而在JSP代码片段中声明的变量是局部变量,声明在_jspService()方法中。

2.5 JSP页面的三种脚本小结:

组成部分功能语法
JSP代码片段在JSP中执行Java代码<% Java代码; %> 如:<% String name='abc'; %>
JSP脚本表达式在JSP中输出变量值<%= 变量%> 如:<%=name %>
JSP声明声明成员变量或方法<%! 声明 %> 如:<%! String name='abc' %>
  • 案例:分别输出脚本变量和作用域中变量值
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    int m=5;
    //向使用域中添加一个变量
    request.setAttribute("n", 6);
%>

输出m:
<%=m%><br>

输出作用域中值:
<%=request.getAttribute("n")%><br>

</body>
</html>

结果:

在这里插入图片描述

2.6 pageContext域

page: 只能在当前页面中有效

request: 一次请求

session: 一次会话

context: 整个服务器

2.6.1 页面域

pageContext域是servlet中4个域对象中最后一个了,页面域的大小是4大域对象中最小的,只在当前页面上有效,不同的JSP页面之间不能实现数据的共享(即使是一次请求)。比请求域范围还要小。

  • 页面域对象名:类PageContext,在JSP中对应了一个内置对象名:pageContext

四个与页面域有关的方法:

页面域操作有关的方法说明
void setAttribute(String key, Object value)向页面域中添加键和值
Object getAttribute(String key)从页面域中得到值
void removeAttribute(String key)删除页面域中键值对
Object findAttribute(String key)自动从四个作用域中去查某个键,从小到大的范围来查找,如果找到就停止。如果没有找到,返回null

page域的内容只能作用在当前页面

pageContext<request<session<ServletContext

2.6.2 页面域测试:

  • demo01.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
        // 分别在page域和request域中存入一个值
        pageContext.setAttribute("pageContextMsg","hello page!");
        request.setAttribute("requestMsg","hello request!");
        
        // 转发到demo02.jsp(还是在一次请求中)
        request.getRequestDispatcher("/demo02.jsp").forward(request,response);
%>
</body>
</html>
  • demo02.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<h1>page域: <%=request.getAttribute("pageContextMsg")%></h1>
<h1>request域: <%=request.getAttribute("requestMsg")%></h1>
</body>
</html>

访问结果:

在这里插入图片描述

2.7 JSP九大内置对象

2.7.1 Request对象

Request对象是javax.servlet.http.HttpServletRequest类的实例。代表请求对象,主要用于接受客户端通过HTTP协议连接传输到服务器端的数据。比如表单中的数据、网页地址后带的参数等。

2.7.2 Response对象

Response对象是javax.servlet.http.HttpServletResponse类的实例。代表响应对象,主要用于向客户端发送数据。

2.7.3 Out对象

Out对象是javax.servlet.jsp.JspWriter类的实例。主要用于向客户端浏览器输出数据。

2.7.4 Session对象

Session 对象是javax.servlet.http.HttpSession类的实例。主要用来保持在服务器与一个客户端之间需要保留的数据,比如在会话期间保持用户的登录信息等,会话状态维持是Web应用开发者必须面对的问题。当客户端关闭网站的所有网页或关闭浏览器时,session对象中保存的数据会自动清除。由于Htp协议是一个无状态协议,不保留会话间的数据,因此通过session对象扩展了htp的功能。比如用户登录一个网站之后,登录信息会暂时保存在session对象中,打开不同的页面时,登录信息是可以共享的,一旦用户关闭浏览器或退出登录,就会清除session对象中保存的登录信息。

2.7.5 Application对象

Application对象是javax.servlet.ServletContext类的实例。主要用于保存用户信息,代码片段的运行环境;它是一个共享的内置对象,即一个容器中的多个用户共享一个application对象,故其保存的信息被所有用户所共享。

2.7.6 PageContext对象

PageContext对象是javax.servlet.jsp.PageContext类的实例。用来管理网页属性,为JSP页面包装页面的上下文,管理对属于JSP中特殊可见部分中已命名对象的访问,它的创建和初始化都是由JSP容器来完成的。

2.7.7 Config对象

Config对象是javax.servlet.ServletConfig类的实例。是代码片段配置对象,表示Servlet的配置。

2.7.8 Page

Page对象是javax.servlet.jsp.HttpJspPage类的实例。相当于this,用来处理JSP网页,它指的是JSP页面对象本身,或者说代表编译后的servlet对象,只有在JSP页面范围之内才是合法的。

2.7.9 Exception对象

我们可以为某个JSP页面设置错误处理页面,当JSP页面发生异常时,请求将会被跳转到指定的错误页面:

<%@ page contentType="text/html;charset=UTF-8" language="java"
         errorPage="/error.jsp" %>      <%--当前页面如果发生异常就跳转到error.jsp页面--%>
<html>
<head>
    <title>Title</title>
</head>
<body>

<%
    // 模拟异常
    int i = 1 / 0;
%>
</body>
</html>

错误处理页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" 
         isErrorPage="true" %>      <%--设置当前页面是一个错误处理页面--%>
<html>
<head>
    <title>Title</title>
</head>
<body>

<%--获取上一个页面触发的异常--%>
<h1>页面出现错误啦!错误信息:<%=exception.getMessage()%></h1>
</body>
</html>

Tips:

  • 1)只有当前的JSP页面设置了isErrorPage=true时才可以使用exception内置对象;

  • 2)并不是所有的JSP页面都有九大内置对象,只有错误页面才有九大内置对象,普通页面只有八大内置对象

三、EL表达式

3.1 EL表达式的作用

3.1.1 什么是EL

EL:Expression Language表达式语言

  • 语法:${ 变量名或表达式 }

3.1.2 EL表达式的作用:

1)用于输出作用域中的变量值

2)用于进行各种运算:算术,逻辑,关系,三元运算等

3.2 获取数据

3.2.1 指定域获取数据

四个与页面域有关的方法:

页面域操作有关的方法说明
void setAttribute(String key, Object value)向页面域中添加键和值
Object getAttribute(String key)从页面域中得到值
void removeAttribute(String key)删除页面域中键值对
Object findAttribute(String key)自动从四个作用域中去查某个键,从小到大的范围来查找,如果找到就停止。如果没有找到,返回null

page域的内容只能作用在当前页面

pageContext<request<session<ServletContext

3.2.2 示例:取出不同作用域中的值

  • 效果:

在这里插入图片描述

  • 代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    //向页面域中添加一个字符串
    pageContext.setAttribute("name", "页面域");
    //请求域
    request.setAttribute("name", "请求域");
    //会话域
    session.setAttribute("name", "会话域");
    //上下文域
    application.setAttribute("name", "上下文域");
%>

JSP写法:
<%=pageContext.getAttribute("name")%>
&nbsp;

EL的写法:
${pageScope.name}
<hr>

JSP写法:
<%=request.getAttribute("name")%>
&nbsp;

EL的写法:
${requestScope.name}
<hr>

JSP写法:
<%=session.getAttribute("name")%>
&nbsp;

EL的写法:
${sessionScope.name}
<hr>

JSP写法:
<%=application.getAttribute("name")%>
&nbsp;

EL的写法:
${applicationScope.name}
<hr>

JSP写法:
<%=pageContext.findAttribute("name")%>
&nbsp;

EL的写法:
${name}

<hr>
</body>
</html>

EL表达式默认从最小的域中取值,如果最小的域中取值,如果没有就往上一级域取值,以此类推;

3.2.3 小结:从四个作用域中取值

作用域Java代码EL的写法范围大小
页面域<%=pageContext.getAttribute(“键名”)%>${pageScope.键名}1
请求域<%=request.getAttribute(“键名”)%>${requestScope.键名}2
会话域<%=session.getAttribute(“键名”)%>${sessionScope.键名}3
上下文域<%=application.getAttribute(“键名”)%>${applicationScope.键名}4
自动查找<%=pageContext.findAttribute(“键名”)%>${键名}
  • 查看每个域对象的大小:

index04.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<h1>
    <%-- 在4个域对象中存入值 --%>
    <% pageContext.setAttribute("page", "hello"); %>
    <% request.setAttribute("request", "hello"); %>
    <% session.setAttribute("session", "hello"); %>
    <% application.setAttribute("application", "hello"); %>

    <%-- 查看每个域对象的范围大小 --%>
    <%=pageContext.getAttributesScope("page")%>
    <%=pageContext.getAttributesScope("request")%>
    <%=pageContext.getAttributesScope("session")%>
    <%=pageContext.getAttributesScope("application")%>

</h1>

</body>
</html>

效果如下:

在这里插入图片描述

3.3 EL表达式获取不同类型的数据

示例:用EL取出不同的数据类型

  • 执行效果:

在这里插入图片描述

  • 注意,键名中如果有特殊字符的写法
变量名[“键名”]
可以使用双引号或单引号,如:${map[“no3-no4”]}
  • index05代码:
<%@ page import="com.dfbz.entity.User" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="com.dfbz.entity.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>得到不同类型的值</title>
</head>
<body>
<%
    //将员工对象放在页面域
    User user = new User(1, "张三");

    //放到页面域中
    pageContext.setAttribute("user", user);
%>

<h2>得到JavaBean的属性值</h2>
<%--本质上是调用get方法--%>
ID:${user.id}, 用户名:${user.username}
<hr>
<%
    List<String> names = Arrays.asList("浙江金华", "福建圃田", "湖南怀化");
    //放在请求域中
    request.setAttribute("names", names);
%>

<h2>取出集合List中元素</h2>
${names[0]} &nbsp; ${names[1]} &nbsp; ${names[2]}

<%
    int[] nums = {100, 200, 300, 400};
//数组放在页面域
    pageContext.setAttribute("nums", nums);
%>

<h2>取出数组中元素</h2>
${nums[0]} &nbsp; ${nums[1]} &nbsp; ${nums[2]} &nbsp; ${nums[3]}

<%
    HashMap<String, String> maps = new HashMap<>();
    maps.put("no1", "辽宁辽阳");
    maps.put("no2", "山东威海");
    maps.put("no3-no4", "河北承德");

    //放在请求域
    request.setAttribute("maps", maps);
%>

<h2>取出Map中元素</h2>
<%--map对象.键名--%>
${maps.no1} &nbsp; ${maps["no2"]} &nbsp; ${maps["no3-no4"]}

</body>
</html>

3.4 练习题:

  • 如果一个会话域中保存了一个user对象,请问以下哪几种取值可以取出user对象的username属性值。

A: ${user.username}

B: ${sessionScope.user.username}

C: ${username}

D: <%=((User)pageContext.findAttribute(“user”)).getUsername() %>

E: <%=((User)session.getAttribute(“user”)).getUsername() %>

点我看答案

四、EL中使用表达式

4.1 算术表达式 :

算术运算符说明范例结果
+${1+1}2
-${2-1}1
*${1*1}1
/或div${5 div 2} 或${5 / 2}2.5
%或mod取余${5 mod 2}或 ${5%2}1

4.2 比较表达式

关系运算符说明范例结果
==或 eq等于(equal)${1 eq 1} 或 ${1==1}true
!= 或 ne不等于(not equal)${1 not equal 1}${1 != 1}false
< 或 lt小于(Less than)${1 lt 2} ${1<2}true
<=或 le小于等于(Less than or equal)${1 <= 1}true
> 或 gt大于(Greater than)${1 > 2}false
>=或 ge大于等于(Greater than or equal)${1 >=1}true

4.3 逻辑表达式 :

逻辑运算符说明范例结果
&& 或 and交集(与)${true and false}或${true && false}false
|| 或 or并集(或)${true or false } 或 `${true
! 或 not${not true}${! true}false

4.4 三元运算:

语法:${逻辑判断?真的值:假的值}

示例:${1>1?"hello":"no hello"}

4.5 判空表达式:

${empty 变量名}
如果变量名在作用域中为空,不存在,返回true
如果变量名为空串,返回true
变量名是一个集合,如果集合中没有元素,返回true

4.6 使用上面所有的运算符

<%@ page import="java.util.ArrayList" %>

<%@ page import="java.util.List" %>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
    <title>Title</title>
</head>
<body>
<h2>算术运算符</h2>
${1+1}<br>

${2-1}<br>

${1*1}<br>

${5 div 2}<br>

${5 /2 }<br>

${5 mod 2}<br>

${5%2}<br>

<h2>比较运算符</h2>

${1 eq 1}<br>

${1 != 1}<br>

${1 lt 2}<br>

${1 <= 1}<br>

${1 > 2}<br>

${1 >=1}<br>

<h2>关系运算符</h2>

${true and false}<br>

${true || false }<br>

${not true}<br>

<h2>三元运算</h2>

${5>6?"男":"女"}

<h2>判空表达式</h2>

${empty aaa} <br>

<%
    pageContext.setAttribute("bbb", "");

    //集合中没有元素
    List<String> names = new ArrayList<>();
//    names.add("吉林通化");

    pageContext.setAttribute("ccc", names);
%>

${empty bbb}<br>

${empty ccc}<br>

</body>

</html>

五、核心标签库

5.1 JSTL标签库

jstl:Java Standard Tag Library,Java标准标签库

格式:<前缀:标签名>

JSTL前缀URI固定写法,标识的作用作用
核心标签库chttp://java.sun.com/jsp/jstl/core用于页面上的逻辑控制,如:if、forEach

5.1.1 JSTL使用步骤

导包jar,每个标签底层其实都是用Java代码实现的。复制daoweb/WEB-INF/lib

创建JSP页面,使用taglib的指令

<%--prefix表示前缀,固定为c,uri 标识 --%>

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

在JSP页面中使用这些标签,如:<c:if>

  • 使用标签的格式:<前缀:标签名>,如果有主体标签,一定要加上结束标签

5.2 判断标签<c:if>

作用: 用于页面上判断

属性名是否支持EL属性类型属 性 描 述
test支持,必须是ELboolean如果EL中条件如果为真执行标签体内容,注:没有else

示例:如果用户提交的age值大于18,则显示你已经成年,否则显示未成年。

  • 执行效果

在这里插入图片描述

  • 代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--prefix表示前缀,固定为c,uri 标识 --%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head>
    <title>标签</title>
</head>
<body>
<%--param.age是EL中内置对象,用于获取本次提交的参数--%>
<c:if test="${param.age >=18}">
    你已经成年
</c:if>
<c:if test="${param.age < 18}">
    小盆友,你还未成年哦!
</c:if>

</body>
</html>

5.3 多分支标签choose

作用:用于多分支判断

标签名作用
choose类似于java中swtich, choose只是一个容器,包含下面两个元素
when可以出现多个,用于每个判断条件,类似于switch中case
otherwise如果上面所有的条件都不满足,执行这个内容。类似于switch中default

案例:通过输入分数,得到评级

在一个表单grade.jsp输入一个分数,提交给自己。然后在同一个页面中根据分数输出相应的等级,80~100优秀,60~80及格 0~60不及格 其它输出分数不正确。

在这里插入图片描述

  • 代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head>
    <title>Title</title>
</head>

<body>
<form action="index02.jsp">
    请输入分数:
    <input type="text" name="score" value="${param.score}">
    <input type="submit" value="评级">
</form>

<c:if test="${not empty param.score}">

    <c:choose>
        <c:when test="${param.score >=80 && param.score<=100}">
            <h2 style="color: red">优秀</h2>
        </c:when>

        <c:when test="${param.score >=60 && param.score<80}">
            <h2 style="color: green">良好</h2>
        </c:when>

        <c:when test="${param.score >=0 && param.score<60}">
            <h2 style="color: dodgerblue">不及格</h2>
        </c:when>

        <c:otherwise>
            <h2 style="color: orange">分数不正确</h2>
        </c:otherwise>
    </c:choose>
</c:if>
</body>
</html>

5.4 遍历标签<c:forEach>

作用: 用于遍历集合或数组

5.4.1 参数

属性名是否支持EL属性类型属性描述
itemstrue数组或集合使用EL表达式,代表集合或数组
varfalseStringvar的变量名代表集合中的每一个元素
varStatusfalseString代表每个元素的状态对象,一共有4个属性,属性的含义见下表
begintrueint遍历从哪个元素开始,默认从第一个元素开始
endtrueint遍历到哪个元素结束,默认遍历到最后一个元素
steptrueint代表步长,遍历时每次跳几个元素,默认每次跳过一个元素

5.4.2 varStatus属性:

属性数据类型含义
indexint当前元素的索引号,从0开始
countint遍历到当前位置,一共遍历了多少个元素(默认从1开始)
firstboolean如果当前遍历的是第1个元素,则返回true
lastboolean如果当前遍历的是最后1个元素,则返回true

5.4.3 遍历集合:

  • 示例:学生信息:包含编号,姓名,性别,成绩。

在这里插入图片描述

学生实体类:

public class Student {
    private Integer id;
    private String name;
    private Character gender;
    private Integer score;
}
  • 代码:
<%@ page import="java.util.Arrays" %>
<%@ page import="com.dfbz.entity.Student" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
    <style>
        table {
            width: 500px;
            border-collapse: collapse;
        }

        tr {
            height: 35px;
        }

        td {
            text-align: center;
        }
    </style>
</head>
<body>

<%

    List<Student> stuList = Arrays.asList(
            new Student(1, "张三", '1', 90),
            new Student(2, "李四", '1', 98),
            new Student(3, "王五", '0', 95)
    );
    request.setAttribute("stuList", stuList);
%>

<table border="1">

    <caption>学生信息表</caption>
    <tr>
        <th>状态</th>
        <th>学号</th>
        <th>姓名</th>
        <th>性别</th>
        <th>成绩</th>
    </tr>
    <%--
    items: 表示要遍历的集合,要使用EL
    var: 变量名,表示集合中的每个元素对象
    begin: 从哪个元素开始遍历,默认是0
    end: 到哪个元素结束
    varStatus: 表示一个对象名字,当前的行对象。
        有四个属性:
            first: 第1个元素返回true
            last: 最后1个元素返回true
            count: 遍历到当前元素时,一共遍历了几个元素,从1开始
            index: 当前元素的索引号,从0开始
    --%>

    <c:forEach items="${stuList}" var="stu" varStatus="row">

        <tr ${row.index % 2 ==0 ? "style='background-color:#ccc'":"style='background-color: yellow'"}>
            <td>${row.index}</td>
            <td>${stu.id}</td>
            <td>${stu.name}</td>
            <td>${stu.gender=='1'?"男":"女"}</td>
            <td>${stu.score}</td>
        </tr>

    </c:forEach>
</table>
</body>
</html>

5.4.4 遍历数组和Map:

<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>

<body>
<%
    int[] nums = {100,200,300,400};
    //数组放在页面域
    pageContext.setAttribute("nums", nums);

    //Map集合
    HashMap<String, String> maps = new HashMap<>();
    maps.put("no1", "甘肃陇南");
    maps.put("no2", "陕西商洛");
    maps.put("no3-no4", "黑龙江绥化");

    //放在请求域
    request.setAttribute("maps",maps);

%>

<h2>遍历数组</h2>
<c:forEach items="${nums}" var="n">

    ${n} &nbsp;

</c:forEach>

<h2>遍历Map</h2>
<c:forEach items="${maps}" var="entry">

    ${entry.key} ==> ${entry.value} <br>

</c:forEach>
</body>
</html>

六、三层架构与MVC

6.1 JavaWEB发展史

6.1.1 Model1

在Model1时代,所有的业务逻辑交给jsp单独处理完成,一个web项目只存在DB层和JSP层,所有的东西都耦合在一起,对后期的维护和扩展极为不利。

在这里插入图片描述

6.1.2 Model2 第一代

JSP Model2有所改进,把业务逻辑的内容放到了JavaBean中,而JSP页面负责显示以及请求调度的工作。虽然第二代比第一代好了些,但JSP还是把view和controller的业务耦合在一起。依然很不理想。

在这里插入图片描述

6.1.2 Model2 第二代

Model2第二代就是现在大力推广的和使用的MVC,将一个项目划分为三个模块,各司其事互不干扰,既解决了jsp所形成的耦合性,又增加了逻辑性、业务性以及复用性和维护性

在这里插入图片描述

6.2 什么是MVC

MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件架构分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

6.1.1 JavaWeb对MVC的实现

在这里插入图片描述

MVC把软件架构分为了三个部分:

  • Controller:也叫控制器;功能如下:
    • 1)接受前端的请求参数
    • 2)调用Model获取模型数据(一般来说就是我们Java中的对象)
    • 3)选择跳转的视图
  • Model:也叫模型;功能如下:
    • 1)接受控制器的参数
    • 2)访问数据库查询数据,封装成JavaBean(如何封装JavaBean就包含了我们之前说的业务处理、逻辑运算、统计等)
    • 3)返回JavaBean给控制器
  • View:也叫视图,主要就是响应给客户端,一般指的是JSP,视图通过jstl等技术取出数据遍历,进行页面的渲染;

6.3 三层架构开发模式

在这里插入图片描述

三层架构开发模式是软件开发的一种架构模式,他将我们的软件开发代码划分为了三个代码层次,每个代码层次各司其职,降低了代码之间的耦合度;使得我们的代码更加清晰,简洁;

三层架构分为控制层(controller层)业务层(service层)持久层(数据层,Dao层)

  • 控制层:又称表现层、web层等;控制层是请求来到后端的第一步操作,控制层主要完成以下三个操作
    • 1)接受前端前端传递的参数
    • 2)调用业务层进行业务逻辑处理
    • 3)根据业务层响应的结果最终决定页面的转发
  • 业务层:又称service层;业务层主要完成以下三个操作:
    • 1)接受控制层传递的参数,调用持久层查询数据库
    • 2)从持久层查询到数据之后开始进行业务的处理,如各种逻辑处理、复杂运算、统计、分析、数据报表等,业务层的代码往往是整个功能的核心
    • 3)将计算好的数据返回给表现层
  • 持久层:又称数据层、dao层等;数据主要的功能就是查询数据库,负责采用什么技术查询数据库,如何查询,将业务层传递过来的参数变成SQL语句等;
    • 1)接受业务传递的参数
    • 2)查询数据库
    • 3)将结果返回给业务层

6.4 MVC中的三层

  • 问:我们的JavaWeb开发使用哪种架构?既用MVC,又用三层结构

在这里插入图片描述

组成说明JavaWeb中的实现
Model模型层: 处理业务逻辑代码、处理数据库访问代码业务层、持久层
View表示层: 处理直接面向客户通过JSP、HTML、CSS、JS、JSTL、EL
Contoller控制器:
1)整个项目控制核心,所有的用户请求首先要到达控制器
2)由控制器去控制调用哪个业务功能
3)调用完毕以后,由控制器决定将哪个视图展现给最终的用户。
Servlet

MVC和三层架构很相似,可以这样说:在三层架构中有MVC的影子,MVC中也能看到三层架构的影子;确切的来说,MVC偏向软件的一个设计思想,三层架构更多的是落实到了代码层面;

不管是三层架构还是MVC都只是软件设计的一种思想(架构),不受编程语言限制;

七、综合案例:完成用户显示列表案例

7.1 案例需求

使用三层架构和MVC模式开发代码,完成用户显示列表功能。

7.2 案例效果

在这里插入图片描述

7.3 实现步骤

7.3.1 执行SQL语句

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL COMMENT 'ID',
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
  `gender` int(11) NULL DEFAULT NULL COMMENT '性别 0:男 1女',
  `age` int(11) NULL DEFAULT NULL COMMENT '年龄',
  `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '籍贯',
  PRIMARY KEY (`id`) USING BTREE
) ;

INSERT INTO `user` VALUES (1, 'admin', '111', 0, 20, '广东潮州');
INSERT INTO `user` VALUES (2, 'root', '222', 1, 22, '云南大理');
INSERT INTO `user` VALUES (3, 'zhangsan', '333', 1, 19, '江西萍乡');
INSERT INTO `user` VALUES (4, 'lisi', '444', 0, 23, '湖南郴州');

7.3.2 导入jar包、配置文件、实体类和工具类

1)导入jar包

在这里插入图片描述

2)准备配置文件

jdbc.properties:

username=root
password=admin
url=jdbc:mysql://localhost:3306/test
driverClassName=com.mysql.jdbc.Driver

3)实体类

public class User {

    private Integer id;
    private String username;
    private String password;
    private Integer gender;
    private Integer age;
    private String address;
}

7.3.3 数据源工具类

package com.dfbz.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * 数据源的工具类
 */
public class DataSourceUtils {

    private static DataSource ds;

    /**
     * 在静态代码块中创建数据源对象
     */
    static {
        //创建属性对象
        Properties info = new Properties();
        try (//得到输入流
             InputStream in = DataSourceUtils.class.getResourceAsStream("/jdbc.properties");) {
            //加载到属性对象中
            info.load(in);
            ds = DruidDataSourceFactory.createDataSource(info);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到数据源
     */
    public static DataSource getDataSource() {
        return ds;
    }


    /**
     * 从连接池中得到连接对象
     */
    public static Connection getConnection() {
        try {
            return ds.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


    /**
     * 释放资源
     */
    public static void close(Connection conn, Statement stmt, ResultSet rs) {
        //关闭结果集
        if (rs!=null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //关闭语句对象
        if (stmt!=null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //关闭连接对象
        if (conn!=null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭连接
     */
    public static void close(Connection conn, Statement stmt) {
        close(conn, stmt, null);
    }
}

7.3.4 验证码类

package com.dfbz.utils;

import javax.imageio.ImageIO;
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.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
import java.util.Random;

@WebServlet("/generateCode")
public class GenerateImageCodeServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    private static final char[] CH = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".toCharArray();
    private static final int IMAGE_WIDTH = 73;
    private static final int IMAGE_HEIGHT = 28;
    private static final int LINE_NUM = 30;
    private static final int RANDOM_NUM = 4;
    Random random = new Random();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("image/jpg");//设置相应类型,告诉浏览器输出的内容为图片
        response.setHeader("Pragma", "No-cache");//设置响应头信息,告诉浏览器不要缓存此内容
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expire", new Date().getTime());

        BufferedImage bi = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_BGR);
        Graphics g = bi.getGraphics();
        g.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        g.setColor(getRandomColor(110, 133));
        g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));
        // 绘制干扰线
        for (int i = 1; i <= LINE_NUM; i++) {
            int x = random.nextInt(IMAGE_WIDTH);
            int y = random.nextInt(IMAGE_HEIGHT);
            int xl = random.nextInt(13);
            int yl = random.nextInt(15);
            g.drawLine(x, y, x + xl, y + yl);
        }

        // 绘制随机字符
        StringBuilder sb = new StringBuilder();
        String str = null;
        for (int i = 0; i < RANDOM_NUM; i++) {
            g.setFont(new Font("Fixedsys", Font.CENTER_BASELINE, 18));
            g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121)));
            str = CH[random.nextInt(CH.length)] + "";
            g.drawString(str, 13 * i, 16);
            g.translate(random.nextInt(3), random.nextInt(3));
            sb.append(str);
        }
        g.dispose();
        request.getSession().setAttribute("safeCode", sb.toString());
        ImageIO.write(bi, "JPG", response.getOutputStream());
    }

    /**
     * 获得颜色
     */
    private Color getRandomColor(int fc, int bc) {
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc - 16);
        int g = fc + random.nextInt(bc - fc - 14);
        int b = fc + random.nextInt(bc - fc - 18);
        return new Color(r, g, b);

    }

}

7.3.5 用户登录

7.3.5.1 登录页面

login.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>

<form action="login" method="post">
    用户名:<input type="text" name="username">
    <hr>
    密码:<input type="password" name="password">
    <hr>
    验证码:<input type="text" name="checkCode"> <a href="javascript:location.reload()"><img src="generateCode" alt=""></a>
    <hr>
    <input type="submit" value="登录">

    <hr>
    <h3>${error}</h3>
</form>
</body>
</html>

7.3.5.2 LoginServlet:

package com.dfbz.controller;

import com.dfbz.service.UserService;

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;

/**
 * 控制器层
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    // 只要有关于user的业务都交给我来处理
    private UserService userService = new UserService();

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 1. 接受前端提交的参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String checkCode = request.getParameter("checkCode");

        // 对比验证码
        HttpSession session = request.getSession();

        // 服务器端的验证码
        Object safeCode = session.getAttribute("safeCode");

        if (!checkCode.equals(safeCode)) {

            // 说明验证码错误了!
            request.setAttribute("error","验证码错误");
            request.getRequestDispatcher("/login.jsp").forward(request, response);

            return;
        }

        // 2. 调用业务层进行业务处理

        // 调用login业务方法;根据用户名和密码查询数据库的条数
        Integer count = userService.login(username, password);

        // 3. 根据业务层返回的信息来决定跳转到哪个视图
        if (count <= 0) {
            // 没有查询到

            // 说明用户名或密码错误

            // 设置前端的提示语句
            request.setAttribute("error","用户名或密码错误");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return;
        }

        session.setAttribute("loginUser",username);

        // 查询到了 咱们应该是跳转到后台的servlet进行列表的查询,然后由这个servlet转发到list.jsp
        response.sendRedirect(request.getContextPath()+"/list");
    }
}

7.3.5.3 UserService:

package com.dfbz.service;

import com.dfbz.dao.UserDao;
import com.dfbz.entity.User;

import java.util.List;

/*
业务逻辑层:专门负责处理user的业务
 */
public class UserService {

    // 只要是要查询user的数据库信息都交给我来处理
    private UserDao userDao = new UserDao();

    /**
     * 用户登录方法:根据用户名和密码查询是否有这一条记录
     *
     * @param username
     * @param password
     * @return
     */
    public Integer login(String username, String password) {

        Integer count = userDao.countByUsernameAndPassword(username, password);

        return count;
    }
}

7.3.5.4 UserDao

package com.dfbz.dao;

import com.dfbz.entity.User;
import com.dfbz.utils.DataSourceUtils;

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

/**
 * 数据层:负责user类型的业务的SQL语句编写
 */
public class UserDao {


    /**
     * 根据用户名和密码查询数据库有多少条记录
     *
     * @param username
     * @param password
     * @return
     */
    public Integer countByUsernameAndPassword(String username, String password) {

        try {
            // 获取数据库连接
            Connection connection = DataSourceUtils.getConnection();

            // 创建预定义SQL对象
            PreparedStatement ps = connection.prepareStatement("select count(id) from user where username=? and password=?");

            ps.setString(1, username);
            ps.setString(2, password);

            // 获取结果集
            ResultSet rs = ps.executeQuery();

            Integer count = 0;

            if (rs.next()) {
                count = rs.getInt(1);
            }

            return count;

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }


        return null;
    }
}

7.3.6 用户列表

7.3.6.1 列表页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>

<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
    <!-- 指定字符集 -->
    <meta charset="utf-8">
    <!-- 使用Edge最新的浏览器的渲染方式 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>用户列表</title>
    <style type="text/css">
        td, th {
            text-align: center;
        }

    </style>

</head>

<body>
<div>
    <h2 style="color:red;text-align: center">欢迎您:${loginUser.username}</h2>
    <h3 style="text-align: center">通讯录:</h3>
    <table border="1" align="center" width="500" height="200">
        <tr style="background-color:#c4c7ce;">
            <th>ID</th>
            <th>用户名</th>
            <th>密码</th>
            <th>性别</th>
            <th>年龄</th>
            <th>地址</th>
        </tr>

        <%--使用forEach遍历元素--%>
        <c:forEach items="${userList}" var="user">
            <tr>
                <td>${user.id}</td>
                <td>${user.username}</td>
                <td>${user.password}</td>
                <td>${user.gender==0?'男':'女'}</td>
                <td>${user.age}</td>
                <td>${user.address}</td>
            </tr>
        </c:forEach>
    </table>
</div>
</body>
</html>

7.3.6.2 ListServlet:

package com.dfbz.controller;

import com.dfbz.entity.User;
import com.dfbz.service.UserService;

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;
import java.util.List;

@WebServlet("/list")
public class ListServlet extends HttpServlet {


    // 用于处理user的业务
    private UserService userService = new UserService();

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

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

        HttpSession session = request.getSession();
        Object loginUser = session.getAttribute("loginUser");

        if(loginUser == null){

            // 说明用户还未登录,重定向到登录页面
            response.sendRedirect(request.getContextPath()+"/login.jsp");

            // 要结束方法的运行,要不然重定向完毕后面的代码依旧执行
            return;
        }

        // 查询所有的用户详情
        List<User> userList = userService.findAll();
        request.setAttribute("userList", userList);

        // 跳转到列表页面
        request.getRequestDispatcher("/list.jsp").forward(request, response);
    }
}

7.3.6.3 UserService:

/**
 * 查询数据库中的所有用户
 * @return
 */
public List<User> findAll() {

    List<User> userList=userDao.findAll();

    return userList;
}

7.3.6.4 UserDao

/**
 * 查询数据库中的所有用户
 *
 * @return
 */
public List<User> findAll() {


    try {
        // 获取数据库连接
        Connection connection = DataSourceUtils.getConnection();

        // 获取预定于SQL语句对象
        PreparedStatement ps = connection.prepareStatement("select * from user");

        // 查询结果集
        ResultSet rs = ps.executeQuery();

        List<User> userList = new ArrayList<>();

        while (rs.next()) {

            Integer id = rs.getInt("id");
            String dbUsername = rs.getString("username");
            String password = rs.getString("password");
            Integer gender = rs.getInt("gender");
            Integer age = rs.getInt("age");
            String address = rs.getString("address");

            userList.add(new User(id, dbUsername, password, gender, age, address));

        }

        return userList;

    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }

    // 如果出现异常返回null
    return null;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字音频接口DAI之I2S/PCM

I2S/PCM数字音频接口概述数字音频接口DAI&#xff0c;即Digital Audio Interfaces&#xff0c;顾名思义&#xff0c;DAI表示在板级或板间传输数字音频信号的方式。相比于模拟接口&#xff0c;数字音频接口抗干扰能力更强&#xff0c;硬件设计简单&#xff0c;DAI在音频电路设计…

深度学习——循环神经网络RNN(笔记)

循环神经网络RNN&#xff1a;对于序列模型的神经网络 1.回顾&#xff1a;潜变量自回归模型 使用潜变量ht总结过去的信息 ①xt跟当前的ht和x(t-1)相关 ②ht跟ht-1和xt-1相关 ③n元语法模型中&#xff0c;单词xt在时间t的条件概率取决于前面n-1个单词 隐藏层和隐藏状态的区别…

【ESP32Cam项目1】:ESP32Cam人脸检测(ArduinoESP32底层、Python版opencv)

人脸检测项目效果图&#xff1a; 人脸检测效果视频&#xff1a; 暮年的主页 - 抖音 (douyin.com) 人脸检测项目目标&#xff1a; 大家好&#xff01;近期拿到了便宜的ESP32Cam开发板&#xff0c;摄像头让我想起来人脸识别&#xff0c;于是ESP32Cam人脸检测项目由此诞生。后期还…

一文总结ACE代码框架

一、前言ACE_Engine框架是OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;的UI开发框架&#xff0c;为开发者提供在进行应用UI开发时所必需的各种组件&#xff0c;以及定义这些组件的属性、样式、事件及方法&#xff0c;通过这些组件可以方便进行OpenHarmony…

JavaScript面试题

目录1.★★ 介绍一下JS的内置类型有哪些&#xff1f;2.★★★★ 介绍一下 typeof 区分类型的原理3.★★★ 介绍一下类型转换4.★★★★ 说说你对 JavaScript 的作用域的理解。什么是作用域链&#xff1f;5.★★ 解释下 let 和 const 的块级作用域6.★★★★ 说说你对执行上下文…

用Vue+Nodejs+Axios+express连接Sqlserver做一个动态网页demo

文章目录一、主要工具二、流程2.1. 安装Node2.2. 新建Vue工程并启动2.3. 前后端通信2.3.1. 修改前端2.3.2. 用axios来发起请求2.3.3. 创建服务端程序一、主要工具 Vue做前端页面Nodejs做服务器后端&#xff08;Nodejs是一个JS的运行环境&#xff0c;可以让JS像其它后端语言一样…

使用超体素上下文和基于图的优化从MLS点云对城市地区的树木进行实例分割

Abstract 在本文中&#xff0c;开发了一种用于从城市场景中的 MLS 数据集中提取树木的实例分割方法。所提出的方法利用超体素结构来组织点云&#xff0c;然后从超体素的局部上下文中提取去除趋势的几何特征。结合局部上下文的去趋势特征&#xff0c;将采用随机森林&#xff08…

Qt基于CTK Plugin Framework搭建插件框架--创建插件

文章目录一、前言二、工程搭建2.1、新建Qt工程2.2、CTK环境配置三、CTK Plugin Framework使用3.1、主函数启动插件框架3.2、插件的创建3.3、插件的使用一、前言 CTK保姆级编译教程&#xff1a;https://blog.csdn.net/Mr_robot_strange/article/details/128547331?spm1001.201…

JavaGUI:多功能计算器(五)--Swing实现双语数据包+菜单切换(完整源码)

JavaGUI&#xff1a;多功能计算器&#xff08;五&#xff09;–Swing实现双语数据包菜单切换&#xff08;完整源码&#xff09; 【背景提示】 “软件国际化”就是实现多种语言显示切换。 1.在前端网页上&#xff0c;可通过探测本地化语言环境实现自动切换&#xff1b; 2.在操…

C++ 20 原子引用 (一)

C 20 原子引用 &#xff08;一&#xff09; std::atomic_ref{} std::atomic_ref类型对其引用的对象进行原子操作。 使用std::atomic_ref 进行多线程读写时不会造成数据争用。被引用对象的生命周期必须超过std::atomic_ref 。操作std::atomic_ref 的子对象是未定义行为。 错…

Docker版RabbitMQ安装延迟队列插件及延迟队列项目应用实战

前言 在项目中经常有延迟业务处理的背景&#xff0c;此时可以借助于Rabbitmq的延迟队列进行实现&#xff0c;但Rabbitmq本身并不支持延迟队列&#xff0c;但可以通过安装插件的方式实现延迟队列 环境准备 首先确认目前项目使用的Rabbitmq的版本&#xff0c;这里博主的版本是3.…

STM32系列(HAL库)——使用ESP8266-01S物联网模块连接Onenet云平台上报DHT11温湿度

前言 本篇主要讲解如何使用ESP8266-01S物联网模块连接Onenet云平台&#xff0c;并上报DHT11模块的温湿度数据。本文单片机主控采用STM32F405RGT6&#xff0c;使用其他主控的话基本要求有2个串口&#xff0c;一个串口用于调试使用&#xff0c;另一个用于ESP模块通讯。 一、前…

SOLIDWORKS 2023工程图和出详图新功能 创建更智能化 更高精度的工程详图

工程图是传达您设计意图的重要文档&#xff0c;您设计的产品越复杂&#xff0c;越需要详细注释说明。SOLIDWORKS 2023增强的工程图和出详图功能将帮助您创建更智能化、更高精度的工程详图&#xff0c;并且扩展新功能使您的设计工作延伸到更多的业务领域。您现在可以从更高层级的…

C 程序设计教程(15)—— 选择结构程序设计练习题

C 程序设计教程&#xff08;15&#xff09;—— 选择结构程序设计练习题 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用户阅读。 目录C 程序设计教程&#xff08;1…

20230110配置ubuntu18.04为开机自动登录

20230110配置ubuntu18.04为开机自动登录 百度搜索&#xff1a;ubuntu 18.04 开机自动登录 https://blog.csdn.net/yang1994/article/details/124446319 通过配置文件启用/禁用Ubuntu 18.04自动登录 超级用户可以通过编辑custom.conf配置文件的方式&#xff0c;来为自己或任何其…

计算机如何存储浮点数和定点数?

1 浮点数的不精确性 能不能用二进制表示所有实数&#xff0c;然后在二进制下计算它的加减乘除呢&#xff1f; 打开Chrome Console&#xff0c;输入0.3 0.6&#xff1a; 简单加法在js算出结果居然不是准确的0.9&#xff0c;而是0.8999999999999999&#xff0c;why&#xff1…

火山语音丨AI创作惊艳四方 诸多挑战仍在路上

2022年8月&#xff0c;一幅名为《太空歌剧院》的数字画作获得冠军同时引发了巨大争议&#xff0c;AIGC&#xff08;AI产生内容&#xff1a;AI-Generated Content&#xff09;出圈的事件便频频出现在大众视野。同年11月30日OpenAI发布的聊天机器人模型ChatGPT免费开放&#xff0…

从0到1完成一个Vue后台管理项目(二十、地图涟漪、线图)

往期 从0到1完成一个Vue后台管理项目&#xff08;一、创建项目&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;二、使用element-ui&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;三、使用SCSS/LESS&#xff0c;安装图标库&#xff09; 从0到1完成一个Vu…

缓存穿透、布隆过滤器、布谷鸟过滤器

1.概述 缓存穿透&#xff1a; 当查询的数据在缓存&#xff08;redis&#xff09;中没有时&#xff0c;一般业务上就会去查询数据存储&#xff08;数据库&#xff09;&#xff0c;这种情况称为缓存穿透。穿透的数量太大会造成数据存储撑不住&#xff08;数据库&#xff09;而宕…

基于控制器软件需求事项进行单元测试和单元测试规范

基于需求事项的单元测试是什么&#xff1f; ​ 大多数汽车行业都遵循 ISO 26262 中定义的标准&#xff0c;这是 ISO 制定的汽车功能安全国际标准。 根据 ISO 26262 标准软件单元测试 (ISO 26262-6-9)&#xff0c;单元验证是验证要验证的单元&#xff08;功能或功能&#xff09…