JavaWeb自学笔记(二)

JavaWeb自学笔记(二)

学习视频:BV12J411M7Sj

8、JSP

Java Server Pages: Java服务端页面,和Servlet一样,用于动态web技术

写法和html相近

区别:

  • html只给用户静态数据
  • jsp页面中可以潜伏java代码,可以给用户提供动态数据

8.1 JSP原理

问:jsp是怎么运行的?

  • 代码层面jsp没有变化

  • 服务器中

    (根据系统配置可能有所不同)查看自己的用户/AppData/local/JetBrains/IntelliJidea/tomcat路径中有一个work目录。

    在这里插入图片描述

浏览器想服务器发送请求,不管访问什么资源,其实都在访问Servlet。

jsp最终会被转换成java类,这个类继承了Servlet

jsp生成的类中有三个常见方法

//初始化
public void jspInit() {
}

//销毁
protected void _jspDestroy() {
}

//JSPService
public void _jspService(HttpServletRequest var1, HttpServletResponse var2) ;
  1. 判断请求

  2. 内置了一些对象

    final javax.servlet.jsp.PageContext pageContext; //页面上下文
    javax.servlet.http.HttpSession session = null;  //session
    final javax.servlet.ServletContext application;  //applicationContext
    final javax.servlet.ServletConfig config;   //config
    javax.servlet.jsp.JspWriter out = null;  //out
    final java.lang.Object page = this;  //page:当前
    HttpServletRequest request;     //请求
    HttpServletResponse  response;  //响应
    
  3. 输出页面前增加的代码

    response.setContentType("text/html");  //设置相应页面类型
    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("<html>\n");
    out.write("<body>\n");
    out.write("<h2>Hello Wd!</h2>\n");
    out.write("</body>\n");
    out.write("</html>\n");
    
  4. 以上的对象可以在jsp中直接使用

    <html>
    <body>
    <h2>Hello World!</h2>
        
     <%
        //这里调用java对象
        String name="alice";
        %>   
    name:<%=name%>
    </body>
    </html>
    

    在这里插入图片描述

​ 在jsp页面中,java代码会原封不动地输出,html代码都会专用out.write写入。

8.2 JSP基本语法

需要的依赖

<dependencies>
    <!--        servlet依赖-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <!--        jsp依赖-->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
    </dependency>
    <!--        JSTL表达式依赖-->
    <dependency>
        <groupId>javax.servlet.jsp.jstl</groupId>
        <artifactId>jstl-api</artifactId>
        <version>1.2</version>
    </dependency>

    <!--        standard标签库-->
    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>

</dependencies>

jsp支持java语法

8.2.1 jsp表达式

index.jsp

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

<%--  JSP表达式
作用:将程序的输出放到客户端
用法   <%= 变量或表达式%>
--%>
<%= new java.util.Date()%>

  </body>
</html>

在这里插入图片描述

8.2.2 jsp脚本片段

index.jsp

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

<%--  JSP表达式
作用:将程序的输出放到客户端
用法   <%= 变量或表达式%>
--%>
<%= new java.util.Date()%>
<%--jsp脚本片段--%>

<%
  int sum=0;
  for(int i=0;i<50;i++){
    sum+=i;
    out.println("<h1>sum["+i+"]="+sum+"</h1>");
  }
%>

  </body>
</html>

在这里插入图片描述

8.2.3 脚本片段再实现

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


<%--jsp脚本片段1--%>

<%
  int sum=0;
  for(int i=0;i<50;i++){
    sum+=i;
    out.println("<h1>sum["+i+"]="+sum+"</h1>");
  }
%>
  
<%--jsp脚本片段2--%>
<%
  int b=100;
%>
      

  </body>
</html>

一个jsp页面下的脚本片段处于同一个作用域中

<%-- 在脚本中嵌入html元素--%>
<%
  for(int i=0;i<5;i++){
%>
<h1> xxxxxtyyyyy <%=i%> </h1>
<% }  %>

8.2.4 jsp声明

<%!
  static{
    System.out.println("loading page");
  }
  private int globalvar=110000;
  public void staticMethod(){
    System.out.println("this is a static method");
  }
%>

注:JSP声明会被编译到JSP生成的java类中。其他的脚本会被生成到_jspService方法中。

在这里插入图片描述

<!--HTML注释-->
<%--JSP注释--%>

HTML的注释可以在客户端显示,JSP注释不会。

8.3 jsp指令

<%@page args......%>
<%@ include file="xxx"%>

自定义错误页面

目录结构

在这里插入图片描述

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%-- 如果不在web.xml中配置错误跳转的话,可以加上这一句
    <%@ page errorPage="error/500.jsp" %>
--%>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

<%
  //算数错误会跳转到500
  int x=1/0;
%>

  </body>
</html>

500.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--定制的500错误页面--%>

<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1 align="center" font-color="red">500</h1>
    <img src="${pageContext.request.contextPath}/img/500page.png" alt="null">
</body>
</html>

404.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1 align="center" font-color="red">404</h1>
<img src="${pageContext.request.contextPath}/img/404page.jpeg" alt="null">
</body>
</html>

web.xml

<error-page>
    <error-code>404</error-code>
    <location>/error/404.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/error/500.jsp</location>
</error-page>

测试效果

在这里插入图片描述

网页拼接

在这里插入图片描述

header.jsp

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

footer.jsp

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

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--<%@ page errorPage="error/500.jsp" %>--%>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

<%--  三个页面合并为一个,这里要注意合并的页面中是否有重名的变量--%>
<%@ include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@ include file="common/footer.jsp"%>
<hr>

<%--  jsp标签
  拼接页面,本质还是三个页面--%>
  <jsp:include page="common/header.jsp"/>
  <h1>网页主体</h1>
  <jsp:include page="common/footer.jsp"/>

  </body>
</html>

在这里插入图片描述

8.4 9个内置对象

  • PageContext 存储
  • Request 存储
  • Response
  • Session 存储
  • Application ServletContext 存储
  • config ServletConfig
  • out
  • page 不用了解
  • exception
<%
    //保存的数据只在一个页面中有效
    pageContext.setAttribute("name1","robot1");
    //保存的数据只在一次请求中有效,请求转发会携带这个数据
    request.setAttribute("name2","robot2");
    //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
    session.setAttribute("name3","robot3");
    //保存的数据只在服务器中有效,从打开服务器到关闭服务器
    application.setAttribute("name4","robot4");
%>

request:客户端向服务器发送请求,产生的数据,用户看完就没用了。如:新闻,看完就可以直接删除。

session:客户端向服务器发送请求,产生的数据,用户用完后可能还会用。如:购物车。

application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用。如:聊天程序。

8.5 JSP标签、JSTL标签、EL表达式

需要的依赖

<!--        JSTL表达式依赖-->
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>

<!--        standard标签库-->
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>

EL表达式:${}

  • 获取数据
  • 执行运算
  • 获取web开发的常用对象(不常用)

jsp表达式

参数传递测试

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

<%--
  http://localhost:8080/jsptag.jsp?name=infinite&age=123
--%>


<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="infinite"></jsp:param>
    <jsp:param name="age" value="123"></jsp:param>
</jsp:forward>

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

<%--取出参数--%>
用户: <%=request.getParameter("name")%>
age:<%=request.getParameter("age")%>

</body>
</html>

在这里插入图片描述

JSTL标签

https://www.runoob.com/jsp/jsp-jstl.html

目的:扩展标签的功能

核心标签 (重要)

在这里插入图片描述

格式化标签

SQL标签

XML标签

JSTL使用步骤

  • 引入对于的taglib
  • 使用其中的方法
  • 在tomcat中要引入相关的jstl包,否则会报错:JSTL解析错误
管理员登录

coretag.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--通过 taglib引入标签库--%>
<%-- 标签库的位置上网复制即可--%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h4>if 测试</h4>
<hr>


<form action="coretag.jsp" method="get">
    <%--
      EL表达式获取表单中的数据
      ${param.参数名}
    --%>
    <input type="text" name="username" value="${param.username}">
    <input type="submit" value="登录">
</form>

<%--判断是不是管理员--%>
<c:if test="${param.username=='admin'}" var="isadmin">
    <c:out value="管理员登录"/>
</c:if>
<c:out value="${isadmin}"></c:out>

</body>
</html>

测试结果

在这里插入图片描述

成绩评定

corewhen.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--定义一个变量score  值为85--%>
<c:set var="score" value="85"/>

<c:choose>
    <c:when test="${score>=90}">
        A
    </c:when>
    <c:when test="${score>=80}">
        B
    </c:when>
    <c:when test="${score>=70}">
        C
    </c:when>
    <c:when test="${score>=60}">
        D
    </c:when>
    <c:when test="${score<60}">
        E
    </c:when>
</c:choose>

</body>
</html>
遍历数组
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    ArrayList<String> people = new ArrayList<>();
    people.add(0,"张三");
    people.add(1,"李四");
    people.add(2,"王五");
    people.add(3,"赵六");
    people.add(4,"田七");
    request.setAttribute("list",people);
%>

<%--var  每次遍历的变量
    items  要遍历的对象
--%>
<c:forEach var="people" items="${list}">
    <c:out value="${people}"/><br>
</c:forEach>
<hr>

<%--   for(int i=1;i<=3;i+=2)--%>
<c:forEach var="people" items="${list}" begin="1" end="3" step="2">
    <c:out value="${people}"/> <br>
</c:forEach>


</body>
</html>

9、JavaBean

实体类

JavaBean有特定的写法:

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法

一般用来和数据库的字段做映射 ORM(对象关系映射)

  • 表–>类
  • 字段–>属性
  • 行记录–>对象

People.java

假设有一个存储个人信息的数据表。people对象代表相关记录

package com.infinite.pojo;

public class People {
    private int id;
    private String name;
    private int age;
    private String address;

    //constructor()
    //getter() and setter()
}

javabean.jsp

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

<%
    //People people=new People();
    //people.setAddress();
    //.....
    //people.getAddress();
    //.....
%>

<jsp:useBean id="people" class="com.infinite.pojo.People"/>
<jsp:setProperty name="people" property="address" value="A市"/>
<jsp:setProperty name="people" property="age" value="18"/>
<jsp:setProperty name="people" property="id" value="250"/>
<jsp:setProperty name="people" property="name" value="alice"/>

姓名:<jsp:getProperty name="people" property="name"/>
id:<jsp:getProperty name="people" property="id"/>
年龄:<jsp:getProperty name="people" property="age"/>
地址:<jsp:getProperty name="people" property="address"/>

</body>
</html>

测试效果

在这里插入图片描述

10、MVC三层架构

MVC: Model、view、Controller 模型、视图、控制器

10.1 早期的架构

在这里插入图片描述

用户直接访问控制层,控制层可以直接操作数据库

servlet-->CRUD-->db
缺点:程序臃肿,难维护
servlet的代码包括:处理请求、响应、试图跳转、处理JDBC、处理业务代码、处理逻辑代码

JDBC作为数据库操作的中间件,相当于在控制层和数据库之间又多了一层,用于解决Mysql、Oracle、SqlServer等不同厂商数据库的兼容性问题。同样的中间件还有ODBC、QODBC(QT相关)

注:虽然JSP也可以嵌入java代码,但是为了加强代码的可维护性,要尽量避免这么做。其他层同理。

10.2、改进的MVC三层架构

在这里插入图片描述

Model

  • 业务处理:业务逻辑(Service)
  • 数据持久层:CRUD(Dao)

View

  • 展示数据
  • 提供链接发起Servlet请求(a、form、img…)

Controller(Servlet)

  • 接受用户请求:(req:请求参数、session信息)
  • 交给业务层处理对应的代码
  • 控制视图的跳转

一个登录的流程

登录-->接受用户的登录请求-->处理用户的请求(获取用户的登录参数:username、password)-->交给业务层处理登陆业务(判断用户名密码是否正确:事务)-->Dao层查询用户名和密码是否正确-->db

11、Filter(过滤器)

目的:过滤网站的数据

  • 处理中文乱码
  • 登录验证

在这里插入图片描述

跟Servlet一样,要实现过滤器,可以通过相关的接口实现。

11.1 将消息过滤为utf-8编码

目录

在这里插入图片描述

ShowServlet.java

package com.infinite.servlet;

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

public class ShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //resp.setCharacterEncoding("utf-8");  该操作交给过滤器实现
        resp.getWriter().write("张三李四");   //若不加处理会直接显示一堆问号
    }

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

CharacterEncodingFilter

package com.infinite.filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
    //初始化
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化完成");
    }

    //chain: 链。可能有好几个过滤器
    /*
    1.过滤器中的所有代码,在过滤特定请求的时候都会执行
    2.必须要让过滤器执行
    filterChain.doFilter(servletRequest,servletResponse)方法
    * */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");

        System.out.println("过滤器执行前");
        filterChain.doFilter(servletRequest,servletResponse);   //让请求继续执行,否则程序会被截止
        System.out.println("过滤器执行后");
    }

    //销毁:web服务器关闭后,过滤器会销毁
    @Override
    public void destroy() {
        System.out.println("CharacterEncodingFilter已销毁");
    }
}

在这里插入图片描述

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">

    <servlet>
        <servlet-name>ShowServlet</servlet-name>
        <servlet-class>com.infinite.servlet.ShowServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/servlet/show</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.infinite.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
<!--        只要是/servlet下的请求,都会经过这个过滤器-->
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>

</web-app>

测试效果

在这里插入图片描述

在这里插入图片描述

12、监听器

现已不常用

实现一个监听器接口,用以观察并反馈用户的动作

查看同时在线人数

OnlineCountListener.java

package com.infinite.listener;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class OnlineCountListener implements HttpSessionListener {
    //创建session监听器
    //一旦创建session就会触发这个事件
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        ServletContext ctx = httpSessionEvent.getSession().getServletContext();
        Integer onlineCount=(Integer) ctx.getAttribute("OnlineCount");

        if(onlineCount==null){
            onlineCount=new Integer(1);
        }
        else{
            int count=onlineCount.intValue();
            onlineCount=new Integer(count+1);
        }
        ctx.setAttribute("OnlineCount",onlineCount);
    }

    //销毁session监听器
    //一旦销毁session就会触发这个事件
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        ServletContext ctx = httpSessionEvent.getSession().getServletContext();
        Integer onlineCount=(Integer) ctx.getAttribute("OnlineCount");

        System.out.println(httpSessionEvent.getSession().getId());

        if(onlineCount==null){
            onlineCount=new Integer(0);
        }
        else{
            int count=onlineCount.intValue();
            onlineCount=new Integer(count-1);
        }
        ctx.setAttribute("OnlineCount",onlineCount);
    }
}

/*
session的销毁:
1.手动销毁   getSession().invalidate();
2.自动销毁   web.xml中自定义session过期时间
* */

index.jsp

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

  <h1>当前有<span><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span></h1>


  </body>
</html>

web.xml

<!--    注册监听器-->
<listener>
    <listener-class>com.infinite.listener.OnlineCountListener</listener-class>
</listener>

<session-config>
    <session-timeout>10</session-timeout>
</session-config>

测试效果

在这里插入图片描述

13、过滤器、监听器的常见应用

监听器:GUI中常用

用户登录跳转

需求:用户登录后才能进入主页,注销后不能再进入主页

  1. 用户登录后,向Session中放入用户的数据

  2. 进入主页的时候要判断用户是否已经登录。(用过滤器实现)

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
        HttpServletRequest request=(HttpServletRequest) servletRequest;
        HttpServletResponse response=(HttpServletResponse) servletResponse;
    
    
    
        if(request.getSession().getAttribute(Constant.USER_SESSION)==null){
            response.sendRedirect("/error.jsp");
        }
    
        filterChain.doFilter(servletRequest,servletResponse);
    }
    

目录

在这里插入图片描述

SysFilter.java

package com.infinite.filter;

import com.infinite.util.Constant;

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

public class SysFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request=(HttpServletRequest) servletRequest;
        HttpServletResponse response=(HttpServletResponse) servletResponse;


        System.out.println(request.getSession().getAttribute(Constant.USER_SESSION));

        if(request.getSession().getAttribute(Constant.USER_SESSION)==null){
            response.sendRedirect("/error.jsp");
        }

        filterChain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

LoginServlet

package com.infinite.servlet;

import com.infinite.util.Constant;

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

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取前端请求参数
        String username = req.getParameter("username");

        if(username.equals("admin")){ //登录成功
            req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());
            resp.sendRedirect("/sys/success.jsp");
        }
        else{
            resp.sendRedirect("/error.jsp");
        }

    }

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

LogoutServlet

package com.infinite.servlet;

import com.infinite.util.Constant;

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

public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object user_session=req.getSession().getAttribute(Constant.USER_SESSION);

        if(user_session!=null){
            req.getSession().removeAttribute(Constant.USER_SESSION);
            resp.sendRedirect("/login.jsp");
        }
        else{
            resp.sendRedirect("/login.jsp");
        }
    }

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

login.jsp

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

<h1>登录</h1>

<form action="/servlet/login" method="post">
    <input type="text" name="username" required>
    <input type="submit">

</form>

</body>
</html>

error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1 align="center" font-color="red">用户名错误或没有权限</h1>
<a href="/login.jsp">返回登录页面</a>
</body>
</html>

sys/success.jsp

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

<h1>主页</h1>
<p><a href="/servlet/logout">注销</a></p>
</body>
</html>

web.xml

<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.infinite.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/servlet/login</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>LogoutServlet</servlet-name>
    <servlet-class>com.infinite.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LogoutServlet</servlet-name>
    <url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>



<filter>
    <filter-name>SysFilter</filter-name>
    <filter-class>com.infinite.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SysFilter</filter-name>
    <url-pattern>/sys/*</url-pattern>
</filter-mapping>

测试效果

在这里插入图片描述

14、JDBC

目的:为不同厂商的数据库提供统一驱动接口

在这里插入图片描述

14.1、基本用法

users表

CREATE TABLE `users` (
  `id` int NOT NULL,
  `name` varchar(40) DEFAULT NULL,
  `password` varchar(40) DEFAULT NULL,
  `email` varchar(60) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

INSERT INTO users(id,name,password,email,birthday) VALUES(1,'张三','123456','zs@qq.com','2000-01-01');
INSERT INTO users(id,name,password,email,birthday) VALUES(2,'李四','123456','ls@qq.com','2000-01-01');
INSERT INTO users(id,name,password,email,birthday) VALUES(3,'王五','123456','ww@qq.com','2000-01-01');

pom.xml

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

TestJdbc.java

package com.infinite.jdbc;

import java.sql.*;

public class TestJdbc {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8  用以防止中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username="root";
        String password="123456";

        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.连接数据库 。 数据库对象
        Connection connection = DriverManager.getConnection(url, username, password);
        //3.向数据库发送SQL语句的对象statement。可用于执行SQL语句
        Statement statement = connection.createStatement();
        //4.编写SQL。此处返回查询的结果集
        String sql="select * from users";
        ResultSet resultSet = statement.executeQuery(sql);

        //4.1增删改
        //sql="delete from users where id=a";
        //int i=statement.executeUpdate(sql);


        while(resultSet.next()){
            System.out.println("id="+resultSet.getObject("id"));
            System.out.println("name="+resultSet.getObject("name"));
            System.out.println("password="+resultSet.getObject("password"));
            System.out.println("email="+resultSet.getObject("email"));
            System.out.println("birthday="+resultSet.getObject("birthday"));
        }

        //6.关闭数据库连接
        resultSet.close();
        statement.close();
        connection.close();
    }
}

测试效果

在这里插入图片描述

14.2 预编译sql用法

package com.infinite.jdbc;

import java.sql.*;
import java.util.Date;

public class TestJdbc2 {
    public static void main(String[] args) throws Exception {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8  用以防止中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username="root";
        String password="123456";

        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.连接数据库。 数据库对象
        Connection connection = DriverManager.getConnection(url, username, password);
        //3.使用预编译SQL
        String sql="insert into users(id,name,password,email,birthday) value(?,?,?,?,?);";
        //4.预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setInt(1,4); //给第一个'?'占位符设置值
        preparedStatement.setString(2,"赵六"); //给第二个'?'占位符设置值
        preparedStatement.setString(3,"123456");
        preparedStatement.setString(4,"zl@qq.com");
        preparedStatement.setDate(5, new java.sql.Date(new java.util.Date().getTime()));

        //5.执行SQL
        int i=preparedStatement.executeUpdate();

        if(i>0) {
            System.out.println("插入成功");
        }

        //6.关闭数据库连接
        preparedStatement.close();
        connection.close();
    }
}

junit单元测试

@Test

pom.xml

<!--        单元测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>3.8.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
</dependency>

TestJdbc3.java

package com.infinite.jdbc;

import org.testng.annotations.Test;

public class TestJdbc3 {
    //这里可以直接运行,不必启动main方法
    @Test
    public void test(){
        System.out.println("Hello");
    }
}

测试效果

在这里插入图片描述

事务

ACID:原子性、一致性、隔离性、持久性。 目的:保护数据的安全

开启事务
事务提交
事务回滚
关闭事务

A:1000
B:1000

A(900)--100-->B(1100)

account表

CREATE TABLE `account` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(40) DEFAULT NULL,
  `money` float DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;


INSERT INTO account('name',money) VALUES('A',1000);
INSERT INTO account('name',money) VALUES('B',1000);
INSERT INTO account('name',money) VALUES('C',1000);

TestJdbc3.java

package com.infinite.jdbc;

import org.testng.annotations.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TestJdbc3 {
    @Test
    public void test() throws Exception {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8  用以防止中文乱码
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";
        Connection connection=null;

        try {
            //1.加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.连接数据库 。 数据库对象
            connection = DriverManager.getConnection(url, username, password);

            //3.通知数据库开启事务。此处关闭了自动提交
            connection.setAutoCommit(false);

            String sql = "update account set money=money-100 where name-'A'";
            connection.prepareStatement(sql).executeUpdate();

            //制造异常
            //int i = 1 / 0;

            String sql2 = "update account set money=money-100 where name-'B'";
            connection.prepareStatement(sql2).executeUpdate();
            connection.commit();
            System.out.println("success");
        }
        catch (Exception e){
            try{
                connection.rollback();
            }
            catch (SQLException e1){
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
        finally {
            connection.close();
        }

    }
}

项目:超市订单管理系统(SMBMS)

需求

在这里插入图片描述

数据库对象:

在这里插入图片描述

项目搭建准备工作

  1. 搭建一个maven项目

  2. 配置tomcat并测试

  3. 导入jar包(依赖)

    1. jsp、servlet、mysql驱动、jstl、standard等
  4. 创建项目包结构(pojo用于存实体类)

    在这里插入图片描述

  5. 对应数据库编写实体类(ORM映射:表-类映射)

  6. 编写基础公共类

    1. 数据库配置文件
    # resources/db.properties
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/smbms?useSSL=true&useUnicode=true&characterEncoding=utf-8
    username=root
    password=a13587491757A
    
    1. 编写操作数据库的类

      package com.infinite.dao;
      
      import java.io.IOException;
      import java.io.InputStream;
      import java.sql.*;
      import java.util.Properties;
      
      /**
       * @author ShmeBluk
       * @version 1.0
       * @ClassName: BaseDAO
       * @Desc: 数据库操作基类
       * @package com.infinite.dao
       * @project smbms
       * @date
       */
      public class BaseDao {
      
          private static String driver;
          private static String url;
          private static String user;
          private static String password;
      
          /**
           * 静态代码块,读取配置信息
           */
          static {
              Properties prop = new Properties();
              InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
              try {
                  prop.load(is);
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
              driver = prop.getProperty("driver");
              url = prop.getProperty("url");
              user = prop.getProperty("user");
              password = prop.getProperty("password");
      
          }
      
          /**
           * @return Connection
           * @throws ClassNotFoundException
           * @throws SQLException
           * @Desc 获取数据库连接
           */
          public static Connection getConnection() throws ClassNotFoundException, SQLException {
              Class.forName(driver);
              Connection conn = DriverManager.getConnection(url, user, password);
              return conn;
          }
      
          /**
           * @param conn
           * @param args
           * @return ResultSet 查询结果集
           * @throws SQLException
           * @Desc 通用的查询操作
           */
          public static ResultSet query(Connection conn, String sql, Object... args) throws SQLException {
              PreparedStatement ps = conn.prepareStatement(sql);
              for (int i = 0; i < args.length; i++) {
                  ps.setObject(i+1, args[i]);
              }
              ResultSet rs = ps.executeQuery();
              rs.getMetaData();
              return rs;
          }
      
          /**
           * @param conn
           * @param sql
           * @param args
           * @return int 受影响的行数
           * @throws SQLException
           * @Desc 通用的增删改操作
           */
          public static int update(Connection conn, String sql, Object... args) throws SQLException {
              PreparedStatement ps = conn.prepareStatement(sql);
              for (int i = 0; i < args.length; i++) {
                  ps.setObject(i+1, args[i]);
              }
              int column = ps.executeUpdate();
              return column;
          }
      
          /**
           * @Desc  关闭资源操作
           * @param resultSet ResultSet
           * @param ps PreparedStatement
           * @param conn Connection
           * @return boolean 是否修改成功
           */
          public static boolean closeResource(ResultSet resultSet, PreparedStatement ps, Connection conn) {
              boolean flag = true;
              try {
                  if (resultSet != null)
                      resultSet.close();
              } catch (SQLException throwables) {
                  flag = false;
                  throwables.printStackTrace();
              }
      
              try {
                  if (ps != null)
                      ps.close();
              } catch (SQLException throwables) {
                  flag = false;
                  throwables.printStackTrace();
              }
      
              try {
                  if (conn != null)
                      conn.close();
              } catch (SQLException throwables) {
                  flag = false;
                  throwables.printStackTrace();
              }
      
              return flag;
          }
      }
      
    2. 编写字符编码过滤器(Filter/CharacterEncodingFilter.java)

  7. 导入静态资源

登录功能

流程图:

在这里插入图片描述

  1. 编写前端页面

  2. 设置首页

    <!--web.xml-->
    <!--    设置欢迎页面-->
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
    
  3. 编写dao层用户登录的接口

    //获取登录的用户
    public User getLoginUser(Connection conn, String userCode) throws SQLException;
    
  4. 实现第三步的接口

    package com.infinite.dao.user;
    
    
    import com.infinite.dao.BaseDao;
    import com.infinite.pojo.User;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import static com.infinite.dao.BaseDao.closeResource;
    import static com.infinite.dao.BaseDao.query;
    
    
    /**
     * @author ShmeBluk
     * @version 1.0
     * @ClassName: UserDAOImpl
     * @Desc: 针对user数据表操作的具体实现类
     * @package com.shme.dao
     * @project smbms
     * @date 2020/6/23 9:52
     */
    public class UserDaoImp1 implements UserDao {
    
        public User getLoginUser(Connection conn, String userCode) throws SQLException {
    
            String sql = "select * from smbms_user where userCode=?";
            ResultSet rs=BaseDao.query(conn,sql,userCode);
            User user=new User();
            if(conn!=null) {
                while (rs.next()) {
                    user = new User();
                    user.setId(rs.getInt("id"));
                    user.setUserCode(rs.getString("userCode"));
                    user.setUserName(rs.getString("userName"));
                    user.setUserPassword(rs.getString("userPassword"));
                    user.setGender(rs.getInt("gender"));
                    user.setBirthday(rs.getDate("birthday"));
                    user.setPhone(rs.getString("phone"));
                    user.setAddress(rs.getString("address"));
                    user.setUserRole(rs.getInt("userRole"));
                    user.setCreatedBy(rs.getInt("createdBy"));
                    user.setCreationDate(rs.getTimestamp("creationDate"));
                    user.setModifyBy(rs.getInt("modifyBy"));
                    user.setModifyDate(rs.getTimestamp("modifyDate"));
                }
                BaseDao.closeResource(rs,null,null);
            }
            return user;
        }
    }
    
  5. 业务层(service)接口

    //用户登录接口
    public User login(String userCode, String password);
    
  6. 业务层实现

package com.infinite.service.user;

import com.infinite.dao.BaseDao;
import com.infinite.dao.user.UserDao;
import com.infinite.dao.user.UserDaoImp1;
import com.infinite.pojo.User;
import org.junit.Test;

import java.sql.Connection;
import java.sql.SQLException;

public class UserServiceImp1 implements UserService{

    //业务层会引用dao层,所以要调入dao层
    private UserDao userDao;
    public UserServiceImp1(){
        userDao=new UserDaoImp1();
    }

    /**
     * @Desc 通过传入的用户名查询数据库中的信息
     * @param userCode 用户名(英文缩写)
     * @return User 数据库中查到的用户
     */
    public User login(String userCode) {
        Connection connection=null;
        User user=null;

        try{
            connection= BaseDao.getConnection();
            user=userDao.getLoginUser(connection,userCode);
        }
        catch (ClassNotFoundException | SQLException e){
            e.printStackTrace();
        }
        finally {
            BaseDao.closeResource(null,null,connection);
        }
        return user;
    }

}
  1. 编写Servlet(控制层,调用业务层代码)

    登录功能

    
    package com.infinite.servlet.user;
    
    import com.infinite.pojo.User;
    import com.infinite.service.user.UserService;
    import com.infinite.service.user.UserServiceImp1;
    import com.infinite.util.Constants;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class LoginServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取用户名和密码
            String userCode=req.getParameter("userCode");
            String password=req.getParameter("userPassword");
            System.out.println("前端:"+userCode+":"+password);
    
            //和数据库中的密码进行比较,调用业务层
            UserService userService=new UserServiceImp1();
            User user=userService.login(userCode);  //查询用户
            System.out.println(user);
            System.out.println("数据库:"+user.getUserCode()+":"+user.getUserPassword());
            if(user.getId()!=null){
                //将用户的信息放入Session
                if(password.equals(user.getUserPassword())) {
                    req.getSession().setAttribute(Constants.USER_SESSION, user);
                    resp.sendRedirect("jsp/frame.jsp");
                    System.out.println("登录成功");
                }
                else{
                    req.setAttribute("error","密码错误");
                    req.getRequestDispatcher("login.jsp").forward(req,resp);
                    System.out.println("密码错误");
                }
            }
            else{
                req.setAttribute("error","用户不存在");
                req.getRequestDispatcher("login.jsp").forward(req,resp);
                System.out.println("用户不存在");
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

    注册功能

  2. 测试

可能遇到的问题

Could not initialize class dao.BaseDao。实际表现为登录后反馈500。

可参考博客:https://blog.csdn.net/GodGump/article/details/109348414?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4.pc_relevant_default&utm_relevant_index=6

注销功能

logoutServlet.java

package com.infinite.servlet.user;

import com.infinite.util.Constants;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getSession().removeAttribute(Constants.USER_SESSION);
        resp.sendRedirect(req.getContextPath()+"/login.jsp");
    }

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

web.xml

<!--退出请求注册-->
<servlet>
    <servlet-name>logoutServlet</servlet-name>
    <servlet-class>com.infinite.servlet.user.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>logoutServlet</servlet-name>
    <url-pattern>/jsp/logout.do</url-pattern>
</servlet-mapping>

登录拦截优化

SysFilter.java

package com.infinite.filter;

import com.infinite.pojo.User;
import com.infinite.util.Constants;

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

public class SysFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("SysFilter初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req=(HttpServletRequest) request;
        HttpServletResponse resp=(HttpServletResponse) response;
        User user=(User)req.getSession().getAttribute(Constants.USER_SESSION);

        System.out.println(user);
        if(user==null){
            resp.sendRedirect(req.getContextPath()+"/error/403.jsp");
            System.out.println("用户未登录");
        }
        else{
            System.out.println("用户已登录");
            chain.doFilter(req,resp);
        }
        System.out.println("SysFilter已过滤");
    }

    @Override
    public void destroy() {
        System.out.println("SysFilter销毁");
    }
}

web.xml

<!--登陆过滤器-->
<filter>
    <filter-name>sysFilter</filter-name>
    <filter-class>com.infinite.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>sysFilter</filter-name>
    <url-pattern>/jsp/*</url-pattern>
</filter-mapping>

修改密码

  1. 导入相关的前端素材

    <li><a href="${pageContext.request.contextPath }/jsp/pwdmodify.jsp">密码修改</a></li>
    
  2. 写项目时,建议从底层向上写(如Dao–>Service–>Servlet)

  3. UserDao层

     public int updatePassword(Connection comm,String newPassword,int id) throws SQLException;
    
  4. UserDao实现

    //UserDaoImp1.java
    public int updatePassword(Connection conn, String newPassword, int id) throws SQLException {
            String sql="update `smbms_user` set `userPassword`=? where `id`=?";
            int update=BaseDao.update(conn,sql,newPassword,id);
            return update;
    }
    
  5. UserServive层

    public Boolean updatePassword(String newPassword, int id);
    
  6. UserService实现

    //UserServiceImp1.java
    public Boolean updatePassword(String newPassword, int id) {
        Boolean flag=false;
        Connection conn=null;
        int update=0;
        try{
            conn=BaseDao.getConnection();
            update=userDao.updatePassword(conn,newPassword,id);
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            if(update>0){
                flag=true;
            }
            BaseDao.closeResource(null,null,conn);
        }
        return flag;
    }
    
  7. UserServlet层(通过将常用代码片段提取成新方法,实现代码复用)

     private void updatePassword(HttpServletRequest req,HttpServletResponse resp)throws ServletException, IOException{
         Object o=req.getSession().getAttribute(Constants.USER_SESSION);
         String newPassword=req.getParameter("newpassword");
    
         boolean flag=false;
    
         if(o!=null && newPassword!=null && newPassword.length()!=0){
             UserService userService=new UserServiceImp1();
             flag=userService.updatePassword(newPassword,((User)o).getId());
             if(flag){
                 req.setAttribute(Constants.MSG,"密码修改成功,请重新登录。");
                 req.getSession().removeAttribute(Constants.USER_SESSION);
                 resp.sendRedirect(req.getContextPath()+"/relogin.jsp");
                 System.out.println("密码修改成功");
                 return ;
             }
             else{
                 req.setAttribute(Constants.MSG,"密码修改失败,请使用原密码登录。");
             }
         }
         else{
             req.getRequestDispatcher("/jsp/pwdmodify.jsp").forward(req,resp);
             System.out.println("密码修改失败。");
         }
     }
    

使用Ajax优化密码修改功能

js/pwdmodify.js

var oldpassword = null;
var newpassword = null;
var rnewpassword = null;
var saveBtn = null;

$(function(){
	oldpassword = $("#oldpassword");
	newpassword = $("#newpassword");
	rnewpassword = $("#rnewpassword");
	saveBtn = $("#save");
	
	oldpassword.next().html("*");
	newpassword.next().html("*");
	rnewpassword.next().html("*");
	
	oldpassword.on("blur",function(){
		$.ajax({
			type:"GET",
			url:path+"/jsp/user.do",
			data:{method:"pwdmodify",oldpassword:oldpassword.val()}, //ajax传递的参数
			dataType:"json",   //目前比较主流的前后端交互方式
			success:function(data){
				if(data.result == "true"){ //旧密码正确
					validateTip(oldpassword.next(),{"color":"green"},imgYes,true);
				}else if(data.result == "false"){ //旧密码输入不正确
					validateTip(oldpassword.next(),{"color":"red"},imgNo + " 原密码输入不正确",false);
				}else if(data.result == "errorSession"){ //当前用户session过期,请重新登录
					validateTip(oldpassword.next(),{"color":"red"},imgNo + " 当前用户session过期,请重新登录",false);
				}else if(data.result == "error"){ //旧密码输入为空
					validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请输入旧密码",false);
				}
			},
			error:function(data){
				//请求出错
				validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请求错误",false);
			}
		});
		
		
	}).on("focus",function(){
		validateTip(oldpassword.next(),{"color":"#666666"},"* 请输入原密码",false);
	});
	
	newpassword.on("focus",function(){
		validateTip(newpassword.next(),{"color":"#666666"},"* 密码长度必须是大于6小于20",false);
	}).on("blur",function(){
		if(newpassword.val() != null && newpassword.val().length >= 6
				&& newpassword.val().length < 20 ){
			validateTip(newpassword.next(),{"color":"green"},imgYes,true);
		}else{
			validateTip(newpassword.next(),{"color":"red"},imgNo + " 密码输入不符合规范,请重新输入",false);
		}
	});
	
	
	rnewpassword.on("focus",function(){
		validateTip(rnewpassword.next(),{"color":"#666666"},"* 请输入与上面一致的密码",false);
	}).on("blur",function(){
		if(rnewpassword.val() != null && rnewpassword.val().length >= 6
				&& rnewpassword.val().length < 20 && newpassword.val() == rnewpassword.val()){
			validateTip(rnewpassword.next(),{"color":"green"},imgYes,true);
		}else{
			validateTip(rnewpassword.next(),{"color":"red"},imgNo + " 两次密码输入不一致,请重新输入",false);
		}
	});
	
	
	saveBtn.on("click",function(){
		oldpassword.blur();
		newpassword.blur();
		rnewpassword.blur();
		if(
			oldpassword.attr("validateStatus") == "true" &&
			newpassword.attr("validateStatus") == "true"
			&& rnewpassword.attr("validateStatus") == "true"){
			if(confirm("确定要修改密码?")){
				$("#userForm").submit();
			}
		}
		
	});
});

fastjson依赖

<!--fastjson-->
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.62</version>
</dependency>

UserServlet层

private void modifyPassword(HttpServletRequest req,HttpServletResponse resp)throws IOException{
    User o=(User)req.getSession().getAttribute(Constants.USER_SESSION);
    String oldpassword=req.getParameter("oldpassword");
    System.out.println("Session中的密码:" + o.getUserPassword());
    System.out.println("用户输入的旧密码:" + oldpassword);

    HashMap<String ,String> resultMap=new HashMap<>();

    if(o==null){
        resultMap.put("result","errorSession");
    }
    else if(StringUtils.isNullOrEmpty(oldpassword)){
        resultMap.put("result","error");
    }
    else{
        if(o.getUserPassword().equals(oldpassword)){
            resultMap.put("result","true");
        }
        else{
            resultMap.put("result","false");
        }
    }

    //设置返回json字符串
    resp.setContentType("application/json");
    PrintWriter out=resp.getWriter();
    out.write(JSONArray.toJSONString(resultMap));
    out.flush();
    out.close();
}

用户管理功能

图示:

在这里插入图片描述

  1. 导入分页的工具类

    com.infinite.util.PageSupport.java

    package com.infinite.util;
    
    public class PageSupport {
    
        //数据库中数据总条目数
        private int totalDataNumber;
    
        //当前页码
        private int currentPageCode;
    
        //每页显示条目数(页面大小)
        private int pageSize;
    
        //总页数
        private int PageNumber;
    
    
        //页码getter
        public int getCurrentPageCode() {
            return currentPageCode;
        }
    
        //页码setter
        public void setCurrentPageCode(int currentPageCode) {
            //判断输入页码是否大于0
            if (currentPageCode > 0 && currentPageCode <= PageNumber) {
                this.currentPageCode = currentPageCode;
            }
        }
    
    
        //页面大小getter
        public int getPageSize() {
            return pageSize;
        }
    
        //页面大小setter
        public void setPageSize(int pageSize) {
            //判断页面大小是否大于零
            if (pageSize > 0) {
                this.pageSize = pageSize;
            }
        }
    
    
        //页数getter
        public int getPageNumber() {
            return PageNumber;
        }
    
        //页数setter
        public void setPageNumber(int pageNumber) {
            PageNumber = pageNumber;
        }
    
    
        //数据总数getter
        public int getTotalDataNumber() {
            return totalDataNumber;
        }
    
        //数据总数setter
        public void setTotalDataNumber(int totalDataNumber) {
            //判断totalDataNumber是否大于零
            if (totalDataNumber > 0) {
                this.totalDataNumber = totalDataNumber;
                setPageNumberByRs();
            }
        }
    
    
        //计算查询的数据能够显示的总页数
        public void setPageNumberByRs() {
    
            //判断是否定义了pageSize
            if (pageSize > 0) {
                /**
                 * 能走到这里说明`totalDataNumber>0&&pageSize>0`
                 * 那么相除的结果:要么为零,要么大于零
                 */
                if (totalDataNumber % pageSize == 0) { //刚好除尽
                    PageNumber = totalDataNumber / pageSize;
                } else/* (totalDataNumber % pageSize > 0) */{ //有余数,总页数加一页
                    PageNumber = (totalDataNumber / pageSize) + 1;
                }
            } else {
                PageNumber = 0;
            }
        }
    }
    
  2. 导入用户列表页面

1、获取用户数量

  1. UserDao

    public int getUserCount(Connection conn, String userName, int userRole) throws SQLException;
    
  2. UserDaoImp1

    public int getUserCount(Connection conn, String userName, int userRole) throws SQLException {
        StringBuffer sql=new StringBuffer();
        sql.append("select count(1) as count from smbms_user u , smbms_role r where u.userRole=r.id");
    
        //若存在用户名筛选条件
        if(!StringUtils.isNullOrEmpty(userName)){
            sql.append(" and u.userName like ?");
            userName="%"+userName+"%";
            System.out.println("userName: "+userName);
        }
        //若存在角色筛选条件
        if(userRole>0){
            sql.append(" and u.userRole = ?");
        }
        System.out.println("UserDaoImpl->getUserCount():" + sql);
    
        ResultSet rs;
        if((!StringUtils.isNullOrEmpty(userName)) && (userRole>0)){//用户和角色都存在
            rs=query(conn,sql.toString(),userName,userRole);
            System.out.println("情况一");
        }
        else if ((!StringUtils.isNullOrEmpty(userName)) && (userRole <= 0)) { //用户名存在,用户角色不存在
            rs = query(conn, sql.toString(), userName);
            System.out.println("情况二");
        } 
        else if ((StringUtils.isNullOrEmpty(userName)) && (userRole > 0)) { //用户名不存在,用户角色存在
            rs = query(conn, sql.toString(), userRole);
            System.out.println("情况三");
        } 
        else /*((StringUtils.isNullOrEmpty(userName)) && (userRole < 0))*/ { //用户名和用户角色都不存在
            rs = query(conn, sql.toString());
            System.out.println("情况四");
        }
        //获得符合条件的用户个数
        int i=0;
        if(rs.next()){
            i=rs.getInt("count");
            System.out.println("rs中的个数: "+i);
        }
        closeResource(rs,null,null);
        return i;
    }
    
  3. UserService

    int getUserCount(String userName,int userRole);
    
  4. UserServiceImp1

    public int getUserCount(String userName, int userRole){
        Connection conn=null;
        int count=0;
        try{
            conn=BaseDao.getConnection();
            count=userDao.getUserCount(conn,userName,userRole);
        }
        catch (ClassNotFoundException e1){
            e1.printStackTrace();
        }
        catch (SQLException e2){
            e2.printStackTrace();
        }
        finally {
            BaseDao.closeResource(null,null,conn);
        }
        return count;
    }
    

2、获取用户列表

  1. UserDao

    List<User> getUserList(Connection conn, String userName, int userRole, int currentPageCode, int pageSize) throws SQLException;
    
  2. UserDaoImp1

    public List<User> getUserList(Connection conn, String userName, int userRole, int currentPageCode, int pageSize) throws SQLException {
        ArrayList<User> userList = new ArrayList<>();
        StringBuffer sql = new StringBuffer();
        sql.append("select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole=r.id");
    
        //如果有用户名筛选条件
        if (!StringUtils.isNullOrEmpty(userName)) {
            sql.append(" and u.userName like ?");
            userName = "%" + userName + "%";
        }
        //如果有角色筛选条件
        if (userRole > 0) {
            sql.append(" and u.userRole=?");
        }
    
        //单页记录数
        int offset = (currentPageCode - 1) * pageSize;
        sql.append(" order by r.id limit ?,?");
    
        ResultSet rs;
        if ((!StringUtils.isNullOrEmpty(userName)) && (userRole > 0)) { //用户名和用户角色都存在
            rs = query(conn, sql.toString(), userName, userRole, offset, pageSize);
            System.out.println("情况一");
            System.out.println("sql:" + sql.toString());
            System.out.println("用户名:" + userName);
            System.out.println("用户角色:" + userRole);
            System.out.println("起始索引:" + offset);
            System.out.println("页面大小:" + pageSize);
        } else if ((!StringUtils.isNullOrEmpty(userName)) && (userRole <= 0)) { //用户名存在,用户角色不存在
            rs = query(conn, sql.toString(), userName, offset, pageSize);
            System.out.println("情况二");
            System.out.println("sql:" + sql.toString());
            System.out.println("用户名:" + userName);
            System.out.println("起始索引:" + offset);
            System.out.println("页面大小:" + pageSize);
        } else if ((StringUtils.isNullOrEmpty(userName)) && (userRole > 0)) { //用户名不存在,用户角色存在
            rs = query(conn, sql.toString(), userRole, offset, pageSize);
            System.out.println("情况三");
            System.out.println("sql:" + sql.toString());
            System.out.println("用户角色:" + userRole);
            System.out.println("起始索引:" + offset);
            System.out.println("页面大小:" + pageSize);
        } else /*((StringUtils.isNullOrEmpty(userName)) && (userRole < 0))*/ { //用户名和用户角色都不存在
            rs = query(conn, sql.toString(), offset, pageSize);
            System.out.println("情况四");
            System.out.println("sql:" + sql.toString());
            System.out.println("起始索引:" + offset);
            System.out.println("页面大小:" + pageSize);
        }
    
        while (rs.next()) {
            User user = new User();
            user.setId(rs.getInt("id"));
            user.setUserCode(rs.getString("userCode"));
            user.setUserName(rs.getString("userName"));
            user.setGender(rs.getInt("gender"));
            user.setBirthday(rs.getDate("birthday"));
            user.setPhone(rs.getString("phone"));
            user.setUserRole(rs.getInt("userRole"));
            user.setUserRoleName(rs.getString("userRoleName"));
            userList.add(user);
        }
    
        BaseDao.closeResource(rs,null,null);
        return userList;
    }
    
  3. UserService

    List<User> getUserList(String userName, int userRole, int currentPageCode, int pageSize)
    
  4. UserServiceImp1

    public List<User> getUserList(String userName, int userRole, int currentPageCode, int pageSize){
        Connection conn=null;
        List<User>userList=null;
        try{
            conn=BaseDao.getConnection();
            if(currentPageCode>0 && pageSize>0){
                userList=userDao.getUserList(conn,userName,userRole,currentPageCode,pageSize);
                System.out.println(userList);
            }
        }
        catch (ClassNotFoundException e1){
            e1.printStackTrace();
        }
        catch (SQLException e2){
            e2.printStackTrace();
        }
        finally {
            BaseDao.closeResource(null,null,conn);
        }
        return userList;
    }
    

3、获取角色操作

角色相关的操作要另外写一个包,以实现职责统一

  1. RoleDao

    package com.infinite.dao.role;
    
    import com.infinite.pojo.Role;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.util.List;
    
    public interface RoleDao {
        /**
         * 获取角色列表
         * @param conn Connection 数据库连接
         * @return List<Role> 角色集合
         */
        List<Role> getRoleList(Connection conn) throws SQLException;
    }
    
  2. RoleDaoImp1

    package com.infinite.dao.role;
    
    import com.infinite.pojo.Role;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    import static com.infinite.dao.BaseDao.query;
    
    public class RoleDaoImp1 implements RoleDao{
        /**
         * 获取角色列表
         * @param conn Connection 数据库连接
         * @return List<Role> 角色集合
         */
        @Override
        public List<Role> getRoleList(Connection conn) throws SQLException {
            String sql = "select * from smbms_role";
            ResultSet rs = query(conn, sql);
            ArrayList<Role> roleList = new ArrayList<>();
            while (rs.next()){
                Role role = new Role();
                role.setId(rs.getInt("id"));
                role.setRoleCode(rs.getString("roleCode"));
                role.setRoleName(rs.getString("roleName"));
                roleList.add(role);
            }
            return roleList;
        }
    }
    
  3. RoleService

    package com.infinite.service.role;
    
    import com.infinite.pojo.Role;
    import java.util.List;
    
    /**
     * @author ShmeBluk
     * @version 1.0
     * @ClassName: RoleService
     * @Desc: 角色service层接口
     * @package com.infinite.service
     * @project smbms
     * @date 2020/7/10 15:32
     */
    public interface RoleService {
        /**
         * 获取用户角色列表
         * @return List<Role> 用户列表
         */
        List<Role> getRoleList();
    }
    
  4. RoleServiceImp1

    package com.infinite.service.role;
    
    import com.infinite.dao.BaseDao;
    import com.infinite.dao.role.RoleDao;
    import com.infinite.dao.role.RoleDaoImp1;
    import com.infinite.pojo.Role;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.util.List;
    
    public class RoleServiceImp1 implements RoleService{
        private RoleDao roleDAO;
    
        public RoleServiceImp1(){
            roleDAO = new RoleDaoImp1();
        }
    
        /**
         * 获取用户角色列表
         * @return List<Role> 用户列表
         */
        @Override
        public List<Role> getRoleList() {
            Connection conn = null;
            List<Role> roleList = null;
            try {
                conn = BaseDao.getConnection();
                roleList = roleDAO.getRoleList(conn);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            } finally {
                BaseDao.closeResource(null,null,conn);
            }
            return roleList;
        }
    }
    

4、用户显示的Servlet

  1. 获取前端的数据
  2. 通过传入参数判断请求是否需要执行
  3. 为了实现分页,需要计算出当前页面和总页面、页面大小等
  4. 用户列表展示
  5. 返回到前端

UserServlet.java

private void query(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
    //从请求中获取参数
    String queryName=req.getParameter("queryName");
    String pageIndex=req.getParameter("pageIndex");
    String temp=req.getParameter("queryUserRole");
    int queryUserRole=0;  //初始化赋值,避免查询时出现异常

    //页面大小
    int pageSize=Constants.PAGE_SIZE;
    //当前页码
    int currentPageCode=1;

    //判断是否有用户名筛选
    if(queryName==null){
        //没有用户名限制,就赋值为空字符串,避免查询报错
        queryName="";
    }
    //判断是否有角色筛选
    if(temp!=null && !temp.equals("")){
        queryUserRole=Integer.parseInt(temp);
    }
    //判断传入页码是否正确
    if(pageIndex!=null){
        try{
            currentPageCode=Integer.parseInt(pageIndex);
        }
        catch (NumberFormatException e){
            e.printStackTrace();
            resp.sendRedirect("error.jsp");
        }
    }

    //获取符合条件的用户个数
    UserService userService=new UserServiceImp1();
    int totalDataNumber=userService.getUserCount(queryName,queryUserRole);

    //计算数据显示的总页数
    PageSupport pageSupport=new PageSupport();
    pageSupport.setCurrentPageCode(currentPageCode);
    pageSupport.setPageSize(pageSize);
    pageSupport.setTotalDataNumber(totalDataNumber);

    int pageNumber=pageSupport.getPageNumber(); //总页数

    //控制首页和尾页
    if(currentPageCode<1){
        currentPageCode=1;
    }
    else if(currentPageCode>pageNumber){
        currentPageCode=pageNumber;
    }

    //将查到的用户数据存入Attribute中
    List<User> userList=userService.getUserList(queryName,queryUserRole,currentPageCode,pageSize);
    Iterator<User> iterator=userList.iterator();
    while(iterator.hasNext()){
        User user=iterator.next();
        System.out.println("用户: "+user);
    }
    req.setAttribute("userList",userList);

    //将查询到的角色数据存入Attribute中
    RoleService roleService = new RoleServiceImp1();
    List<Role> roleList = roleService.getRoleList();
    for(Role role : roleList){
        System.out.println("用户角色:"+role);
    }
    req.setAttribute("roleList", roleList);

    //将需要的参数存到Attribute中
    req.setAttribute("queryUserName", queryName);
    req.setAttribute("queryUserRole", queryUserRole);
    req.setAttribute("totalPageCount", pageNumber);
    req.setAttribute("totalCount", totalDataNumber);
    req.setAttribute("currentPageNo", currentPageCode);

    //转发:url不变
    req.getRequestDispatcher("userlist.jsp").forward(req, resp);
}

后续的增删改等功能总体思想和查询一样
ist = roleDAO.getRoleList(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
BaseDao.closeResource(null,null,conn);
}
return roleList;
}
}




### 4、用户显示的Servlet

1. 获取前端的数据
2. 通过传入参数判断请求是否需要执行
3. 为了实现分页,需要计算出当前页面和总页面、页面大小等
4. 用户列表展示
5. 返回到前端

> UserServlet.java

```java
private void query(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
 //从请求中获取参数
 String queryName=req.getParameter("queryName");
 String pageIndex=req.getParameter("pageIndex");
 String temp=req.getParameter("queryUserRole");
 int queryUserRole=0;  //初始化赋值,避免查询时出现异常

 //页面大小
 int pageSize=Constants.PAGE_SIZE;
 //当前页码
 int currentPageCode=1;

 //判断是否有用户名筛选
 if(queryName==null){
     //没有用户名限制,就赋值为空字符串,避免查询报错
     queryName="";
 }
 //判断是否有角色筛选
 if(temp!=null && !temp.equals("")){
     queryUserRole=Integer.parseInt(temp);
 }
 //判断传入页码是否正确
 if(pageIndex!=null){
     try{
         currentPageCode=Integer.parseInt(pageIndex);
     }
     catch (NumberFormatException e){
         e.printStackTrace();
         resp.sendRedirect("error.jsp");
     }
 }

 //获取符合条件的用户个数
 UserService userService=new UserServiceImp1();
 int totalDataNumber=userService.getUserCount(queryName,queryUserRole);

 //计算数据显示的总页数
 PageSupport pageSupport=new PageSupport();
 pageSupport.setCurrentPageCode(currentPageCode);
 pageSupport.setPageSize(pageSize);
 pageSupport.setTotalDataNumber(totalDataNumber);

 int pageNumber=pageSupport.getPageNumber(); //总页数

 //控制首页和尾页
 if(currentPageCode<1){
     currentPageCode=1;
 }
 else if(currentPageCode>pageNumber){
     currentPageCode=pageNumber;
 }

 //将查到的用户数据存入Attribute中
 List<User> userList=userService.getUserList(queryName,queryUserRole,currentPageCode,pageSize);
 Iterator<User> iterator=userList.iterator();
 while(iterator.hasNext()){
     User user=iterator.next();
     System.out.println("用户: "+user);
 }
 req.setAttribute("userList",userList);

 //将查询到的角色数据存入Attribute中
 RoleService roleService = new RoleServiceImp1();
 List<Role> roleList = roleService.getRoleList();
 for(Role role : roleList){
     System.out.println("用户角色:"+role);
 }
 req.setAttribute("roleList", roleList);

 //将需要的参数存到Attribute中
 req.setAttribute("queryUserName", queryName);
 req.setAttribute("queryUserRole", queryUserRole);
 req.setAttribute("totalPageCount", pageNumber);
 req.setAttribute("totalCount", totalDataNumber);
 req.setAttribute("currentPageNo", currentPageCode);

 //转发:url不变
 req.getRequestDispatcher("userlist.jsp").forward(req, resp);
}

后续的增删改等功能总体思想和查询一样

着重理解javaweb的原理,后续学习框架(SSM,Spring等等)后,javaweb中的内容会被不断封装简化,需要写的代码量也会减少。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值