javaWeb

1 web的基本概念

狂神说【javaWeb】






进阶路程

2 web服务器




3 tomcat

下载tomcat

官网http://tomcat.apache.org/

解压后





4 HTTP







5 maven

maven环境搭建



配置环境变量 :

/conf下的settings.xml中设置

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

image.png

<1ocalRepository>D:Environmentapache-maven-3.6.2maven-repo</localRepository>

在IDEA中使用maven

根据模板创建maven项目

  1. 启动idea
  2. 创建一个mavenWeb项目
    New project(1)
    New project(2)
    New project(3)
  3. 等待资源加载
  4. maven本地仓库中多了很多包
    maven-repo
  5. IDEA中的maven设置
    setting-maven

创建一个普通的maven项目

项目文件结构

在IDEA中配置TomCat

添加tomcat配置
选择tomcat本地
配置tomcat
解决错误
虚拟路径映射

maven

目录树

maven 设置jdk版本

<properties>
	<maven.compiler.source>14</maven.compiler.source>
	<maven.compiler.target>14</maven.compiler.target>
</properties>

一些问题

IDEA全局配置

设置
maven配置

统一javaapps版本

tomcat中的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"
         metadata-complete="true">
</web-app>

6 servlet *

servlet简介

  • sun公司开发动态Web的技术
  • 是sun公司的一个接口, 如果要开发一个servlet程序, 只需要两个小步骤
    1 编写一个类实现servlet接口
    2 把写好的java类部署到web服务器中
  • 把实现了servlet的java程序叫做, servlet

hello servlet

sun公司有两个默认的实现类: HTTPServlet GenericServlet

Servlet继承关系

  1. 构建一个普通的maven项目, 删掉src文件夹, 以后的学习就可以在这个项目里面
  2. 关于maven父子工程的理解
    父项目中会有
<modules>
<module>servlet-01</module>
</modules>

子项目中会有

<parent>
       <artifactId>HelloServlet</artifactId>
       <groupId>com.karl</groupId>
       <version>1.0-SNAPSHOT</version>
</parent>

父项目的java子项目可以直接使用
son extends parent

  1. Maven 环境优化
    3.1 修改web.xml为最新的
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"
         metadata-complete="true">
</web-app>

3.2 将Maven结构搭建完整
4. 编写一个servlet程序
4.1 编写一个普通类
4.2 实现Servlet接口, 继承HTTPServlet

package com.karl.servlet;

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

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        resp.getOutputStream();
        PrintWriter writer = resp.getWriter();//响应流
        writer.println("hello, servlet! ");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}
  1. 编写Servlet的映射
    为什么需要映射: 我们写的是java程序, 但需要通过浏览器访问, 浏览器需要连接web服务器, 所以我们需要在web服务中注册我们写的Servlet, 还需要给他一个浏览器能访问的路径;
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.karl.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. 配置tomcat
    注意配置项目发布的目录
  2. 启动测试

servlet 原理

Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会
servlet原理图

Maping

一个servlet可以指定多个映射
一个servlet可以指定通用路径映射

<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
</servlet-mapping>

指定后缀映射
后缀映射
优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;

servletContext对象

web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用

  • 共享数据 : 我在这个Servlet中保存的数据,可以在另外一个servlet中拿到 ;
    servletContext
    放置数据类
package com.karl.servlet;

import javax.servlet.ServletContext;
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 HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        this.getInitParameter();//初始化参数
//        this.getServletConfig();//servlet配置
//        this.getServletContext();//servlet上下文

        ServletContext context = this.getServletContext();
        String username = "karl";//数据
        context.setAttribute("username", username);//将一个数据保存到了servletContext中
    }
}

读取数据类

package com.karl.servlet;

import javax.servlet.ServletContext;
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 GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String)context.getAttribute("username");

        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().println("名字:"+username);
    }
}

servletContext应用

获取初始化参数

<!--可以配置一些web应用初始化参数-->
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
    </context-param>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//读取初始化参数
        ServletContext context = this.getServletContext();
        String url = (String)context.getInitParameter("url");
        resp.getWriter().println(url);
    }

转发和重定向

doGet(){
...
//        RequestDispatcher requestDispatcher = context.getRequestDispatcher("");//转发的路径
//        requestDispatcher.forward(req,resp);//实现转发
        context.getRequestDispatcher("").forward(req, resp);
...
}

转发(上)和重定向(下)


读取资源文件

poperties
classpath: java和resource路径
classpath路径
读取资源文件
思路: 需要一个文件流;

response

下载文件

HttpServletResponse

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse;

  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要给客户端响应一些信息:找HttpServletResponseI

简单分类

  • 负责向浏览器发送数据的方法
   public ServletOutputStream getOutputStream() throws IOException;//其他流

   public PrintWriter getWriter() throws IOException;//写中文
  • 向浏览器发送响应头的方法
public void setDateHeader(String name, long date);

public void addDateHeader(String name, long date);

public void setHeader(String name, String value);

public void addHeader(String name, String value);

public void setIntHeader(String name, int value);

public void addIntHeader(String name, int value);

public void setCharacterEncoding(String charset);

public void setContentLength(int len);

public void setContentType(String type);

public void setBufferSize(int size);

下载文件

//1 要下载的文件路径;
String realPath = "E:\桌面快捷方式源\code\java\project\HelloServlet\response\src\main\resources\林奚.png";
System.out.println(realPath);
//2 要下载的文件名;
String fileName = realPath.substring(realPath.lastIndexOf("\") + 1);
System.out.println(fileName);
//3 浏览器支持我们下载文件, 中文文件名用URLEncoder.encoder()编码, 否则有可能乱码;
resp.setHeader("Content-Disposition","attachment;filename = "+ URLEncoder.encode(fileName, StandardCharsets.UTF_8));
//4 获取下载文件的输入流;
FileInputStream in = new FileInputStream(realPath);
//5 创建缓冲区;
int len = 0;
byte[] buffer = new byte[1024];
//6 获取outputStream对象;
ServletOutputStream out = resp.getOutputStream();
//7 将FileOutputStream流写入到buffer缓冲区;使用OutputStream将缓冲区中的数据输出到客户端;
while ((len = in.read(buffer))>0){
    out.write(buffer, 0, len);
}
//8 关闭流
in.close();
out.close();

验证码

前端实现验证码: js
后端实现: 需要用到java的图片类

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //浏览器5秒刷新
        resp.setHeader("refresh", "3");
        //在内存中创建一个图片
        BufferedImage image = new BufferedImage(80, 100, BufferedImage.TYPE_INT_RGB);
        //得到图片
        Graphics2D g = (Graphics2D)image.getGraphics();
        //设置图片的背景颜色
        g.setColor(Color.white);
        g.fillRect(0,0,80,20);
        //给图片写数据
        g.setColor(Color.blue);
        g.setFont(new Font(null,Font.BOLD,20));
        g.drawString(makeNum(),0,20);
        //告诉浏览器这个响应用图片的形式打开
        resp.setContentType("image/png");
        //网站有缓存, 不让浏览器缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control", "no-cache");
        resp.setHeader("Pragma", "nocache");
        //把图片写给浏览器
        boolean write = ImageIO.write(image, "png", resp.getOutputStream());

    }
    //生成随机数
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(9999999) + "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7 - num.length(); i++){
            sb.append("0");
        }
        num = sb.toString()+num;
        return num;
    }
//生成随机数
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(9999999) + "";
        num = "0".repeat(Math.max(0, 7 - num.length())) +num;
        return num;
    }

重定向

B一个web资源收到客户端A请求后,B他会通知A客户端去访问另外一个web资源C,这个过程叫重定向

常见场景 :

  • 用户登录
/*
resp.setHeader("Location" , "/r/img");
resp.setstatus(302);
*/
resp.sendRedirect("/r/img");//重定向时候一定要注意路径问题,否则404;

重定向和转发的区别
相同点 : 页面都会跳转
不同点 : 转发的时候URL不会变化; 重定向时URL会变化;

7 cookie和session

cookie

有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话;你能怎么证明你是西开的学生?
1.发票
西开给你发票
2.学校登记
西开标记你来过了
一个网站,怎么证明你来过?
客户端
服务端
1.服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了; cookie
2.服务器登记你来过了,下次你来的时候我来匹配你; seesion

保存会话的两种技术

cookie

  • 客户端技术(响应, 请求)

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息?我们可以把信息或者数据放在Session中!

常见:网站登录之后,你下次不用再登录了,第二次访问直接就上去了!

1.从请求中拿到cookie信息
2.服务器响应给客户端cookie

public class CookieDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //服务器,告诉你,你来的时间,把这个时间封装成为一个信件,你下带来,我就知道你来了
        //解决中文乱码
        req.setCharacterEncoding("utf-8");
        resp.setHeader("Content-type", "text/html;charset=UTF-8");
        resp.setCharacterEncoding("utf-8");
        PrintWriter out = resp.getWriter();
        Cookie[] cookies = req.getCookies();//返回数组,cookie可能存在多个
        //判断cookie是否存在
        if (null != cookies){
            out.write("您上一次访问的时间: ");
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("lastLoginTime")){
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastLoginTime);
                    out.write(date.toString());
                }
            }
        }else {
            out.write("这是您第一次访问本站! ");
        }
        //服务给客户端响应一个cookie
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
        //设置cookie有效期为一天, 默认为一次会话
        cookie.setMaxAge(24*60*60);
        resp.addCookie(cookie);
    }

cookie:一般会保存在本地的用户目录下appdata;

一个网站cookie是否存在上限: (聊聊细节问题)

  • 一个Cookie只能保存一个信息;
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie;
  • Cookie大小有限制4kb;
  • 300个cookie浏览器上限

删除Cookie;

  • 不设置有效期,关闭浏览器,自动失效;
  • 设置有效期时间为0 ;

编码解码

URLEncoder.encode("卡尔", "utf-8")
URLDecoder. decode(cookie.getvalue(, "utf-8")

session

session

什么是Session:

  • 服务器会给每一个用户(浏览器)创建一个Seesion对象;
  • 一个Seesion独占一个浏览器,只要浏览器没有关闭,这个Session就存在;
  • 用户登录之后,整个网站它都可以访问! -->保存用户的信息;保存购物车的信息....

session: 会话:

用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话 ;

session 存入键值对

//解决乱码问题
req.setCharacterEncoding( "UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType( "text/html;charset=utf-8");
//得到Session
Httpsession session = req.getSession();
//给Session中存东西
session.setAttribute( name: "name" , value: "秦疆");
//获取Session 的ID
string sessionId = session.getId();
//判断session是不是新创建
if (session.isNew()){
resp.getwriter().write( s: "session创建成功,ID: "+sessionId);
}else {
resp.getwriter().write( s: "session以及在服务器中存在了,ID: "+sessionId);
}

session 存入对象

person类

public class Person {
    private String name;
    private int age;
    public Person() {
    }
    public Person( String name,int age) {
        this.name = name;
        this.age = age;
    }
    public string getName() {
        return name;
    }
    public void setName ( String name) {
        this.name = name;
    }
    public int getAge( ) {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

将person对象存入session

//得到Session
Httpsession session = req.getsession();
//给Session中存东西
session.setAttribute( name: "name" ,new Person( name:"秦疆" , age: 1));

取出person对象

//解决乱码问题
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setcontentType( "text/htm1;charset=utf-8");
//得到Session
Httpsession session = req.getsession( );
Person person = (Person) session.getAttribute( name: "name" );
system.out.println(person.toString());

移除session对象和注销session

Httpsession session = req.getSession();
session.removeAttribute(name: "name");//移除session对象
session.invalidate();  //手动注销session

web.xml

<!--设置session默认的失效时间-->
<session-config>
    <!--15分钟后session自动失效,以分钟为单位-->
    <session-timeout>15</session-timeout>
</session-config>

使用场景:

  • 保存一个登录用户的信息;·购物车信息;
  • 在整个网站中经常会使用的数据,我们将它保存在Session中;

Session和cookie的区别:

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费).
  • Session对象由服务器创建;

8 JSP

什么是Jsp?

java servlet pages : Java服务器端页面,也和Servlet—样,用于动态Web技术!

最大的特点:

  • 写JSP就像在写HTML

区别:

  • HTML只给用户提供静态的数据
  • JSP页面中可以嵌入JAVA代码,为用户提供动态数据;

Jsp原理

思路:JSP到底怎么执行的!

  • 代码层面没有任何问题

  • 服务器内部工作

    • tomcat中有一个work目录;
    • IDEA中使用Tomcat的会在IDEA的tomcat中生产一个work目
      IDEA中tomcat的工作空间
      地址:c: users Administrator.Inte1liJIdea2018.1system omcatUnnamed_javaweb-session-cookiework catalina loca1hostRooTorgapache jsp

发现页面转变成了java程序
index_jsp
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!
JSP最终也会被转换成为一个Java类!

JSP本质上就是一个Servlet

//初始化
public void _jspinit() {
}
//销毁
public void _jspDestroy() {
}
/ / JSPservice
public void _jspservice(.HttpservletRequest request,HttpservletResponse resp){
}

1.判断请求
2.内置一些对象

final javax.servlet.jsp. Pagecontext pagecontext;       //页面上下文
javax.servlet.http.Httpsession session = nu71;          //session
final javax.serv1et.servletcontext application;         //app1ication contextfinal 
javax.servlet.serv1etconfig config;                     // config
javax.servlet.jsp . 3spwriter out = nu17;               // out
fina7 java.1ang. object page = this;                    //page:当前
HttpservletRequest request                              //请求
HttpservletResponse response                            //响应

3.输出页面前增加的代码

response. setcontentType( "text/html");                                                           //设置响应的页面类型
pagecontext = _jspxFactory.getPagecontext(this, request, response, nu71, true, 8192, true);
_jspx_page_context = pagecontext;
application = pagecontext. getservletcontext();
config = pagecontext.getservletconfig();
session = pagecontext.getsession();
out = pagecontext.getout();
_jspx_out = out;

4.以上的这些个对象我们可以在JSP页面中直接使用!
JSP原理

在JSP页面中;
只要是JAVA代码就会原封不动的输出;
如果是HTML代码,就会被转换为: out.write( "<html> "); 这样的格式输出到前端;

JSP基础语法和指令

maven的依赖

pom.xml
-------
<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>jst1-api</artifactId>
    <version>1.2</version>
  </dependency>
  <!-- standard -->
  <dependency>
    <groupid>taglibs</groupId>
    <artifactId>standard</artifactId><version>1.1.2</version>
  </dependency>
</dependencies>

JSP基础语法

任何语言都有自己的语法,JAVA中有,JSP作为java技术的一种应用,支持Java所有语法,它还拥有一些自己扩充的语法 !(了解,知道即可! )

<%--
--JSP表达式
--作用:用来将程序的输出,输出到客户端<%=变量或者表达式%>
--%>

<%= new java.util.Date();%>
<%--jsp脚本片段--%>

<%
int sum = ;
for (int i = 1; i <=100 ; i++) {
sum+=i;
}
out.println( "<h1>Sum="+sum+"</h1>");
%>
<%--在代码嵌入HTML元素--%>
<% for ( int i = 0; i < 5; i++){ %>
<h1>Hello,world<%=i %></h1>
<% } %>

jsp声明 : 会被编译到JSP生成Java的类中! 其他的,就会被生成到_jspService方法中!
在JSP,嵌入Java代码即可!

<% %>
<%= %>
<%! %>
<%--注释--%>

JSP的注释,不会在客户端显示,HTML就会!

JSP指令

<%apage args. . .. %>
<%@include file=""%>

<%--@include会将两个页面合二为一—-%>
<%@include file="common/header.jsp "%>
<h1>网页主体</h1>
<%ainclude file="common/footer.jsp"%>

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

内置对象及作用域

9大内置对象

  • PageContext 存内容
  • Request 存内容
  • Response
  • Session 存内容
  • Application 【SerlvetContext】存内容
  • config【SerlvetConfig】
  • out
  • page
  • exception

存储内容的内置对象

<%--存储内容的内置对象--%>
<%
  pageContext.setAttribute("name1", "秦疆1号");    //保存的数据只在一个页面中有效
  request.setAttribute("name2" ,"秦疆2号");        //保存的数据只在一次请求中有效,请求转发会携带这个数据
  session.setAttribute("name3" , "秦疆3号");       //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览版多结经
  application.setAttribute("name4" , "秦疆4号");   //保存的数据只在服务器中有效,从打开服务器到关团
%>

<%--脚本片段中的代码,会被原封不动生成到xxx_JSP.java: 要求 : 这里面的代码必须保证Java语法正确--%>
<%
  //从pageContext取出,我们通过寻找的方式来
  //从底层到高层(作用域):
  String name1 = (String) pageContext.findAttribute("name1");
  String name2 = (string);pageContext.findAttribute("name2");
  string name3 = (String) pageContext.findAttribute( "name3");
  string name4 = (String) pageContext.findAttribute("name4");
  string name5 = (String) pageContext.findAttribute( "name5");//不存在
%>
<%--使用EL表达式输出${}--%>
<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>

request: 客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!
session: 客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;
application: 客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊夫数据;

JSP标签, JSTL标签, EL表达式

pom.xml
-------
<!-- STL表达式的依赖-->
<dependency>
  <groupId>javax.servlet.jsp.jstl</groupId>
  <artifactId>jst1-api</artifactId>
  <version>1.2</version>
</dependency>
<!-- standard标签库-->
<dependency>
  <groupId>taglibs</groupId>
  <artifactId>standard</artifactId>
  <version>1.1.2</version>
</dependency>

EL表达式

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

jsp标签

<%--jsp:incLude--%>
<%-- http://LocaLhost:8080/jsptag.jsp?name=kuangshen&age=12 --%>
<jsp: forward page="/jsptag2.jsp">
  <jsp: param name="name" value="kuangshen"></jsp:param><jsp:param name="age" value="12"></jsp:param>
</jsp:forward>

JSTL标签

JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和Java代码一样!

JSTL标签库使用步骤:

  • 引入对应的taglib
  • 使用其中的方法
  • 在Tomcat也需要引入jstl的包,否则会报错:JSTL解析错误
<%--引入JSTL核心标签库,我们才能使用JSTL标签-%>
<%taglib prefix="c" uri="http://java.sun.com/jsp/jst1/core"%>

JSTL core标签

<form action="coreif.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}" />
<%--定义一个变量score,值为85--%>
<c:set var="score" value="55"/>
<c:choose>
  <c :when test="${score>=90}">
    你的成绩为优秀
  </c :when>
  <c : when test="${score>=80}">
    你的成绩为一般
  </c:when>
  <c :when test="${score>=70}">
    你的成绩为良好
  </c :when>
  <c :when test="${score<=60}">
    你的成绩为不及格
  </c :when>
</c:choose>
<%
  ArrayList<String> people = new ArrayList>;
  people.add(O, "张三");
  people.add(1, "李四");
  people.add(2 , "王五");
  people.add(3 , "赵六");
  people.add(4, "田七");
  request.setAttribute("list" , people);
%>

<%--
--var ,每一次遍历出来的变量
--items,要遍历的对象
--begin,哪里开始
--end,到哪里
--step,步长
--%>
<c:forEach var="people" items="${7ist}">
  <c:out Value="${people}"/> br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
  <c:out value="${people}"/><br>
</c:forEach>

9 javaBean

实体类
JavaBean有特定的写法:

  • 必须要有一个无参构造属性必须私有化
  • 必须有对应的get/set方法;
  • 一般用来和数据库的字段做映射ORM;
    ORM:对象关系映射
<%
  //People peopLe = new People();peoplLe.setAddress( );
  //people.setId();
  //people.setAge();
  //peopLe.setName();
%>
<jsp:useBean id="people" class="com.kuang.pojo.People" scope="page"/>
<jsp:setProperty name="people" property="address" value="西安"/>
<jsp:setProperty name="people" property="id" value="1"/>
<jsp:setProperty name="people" property="age" value="3"/>
<jsp:setProperty name="people" property="name" value="小小"/>

<%--<%=people.getAddress( )%>--%>
姓名: <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" />

10 MVC三层架构

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

10.1 早些年

早些年的架构

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

servlet--CRUD-->数据库弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
程序猿调用
JDBC
Mysql oracle sqlserver ....

10.2 MVC三层架构

image-20201121172433120

Model

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

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

controller (Servlet)

  • 接收用户的请求: (req:请求参数、Session信息....)

  • 交给业务层处理对应的代码

  • 控制视图的跳转

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

11 过滤器(Filter)

什么是过滤器(Filter)

Filter:过滤器,用来过滤网站的数据;

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

image-20201121174126385

Filter开发步骤:

  1. 导包

    <dependencies>
    <!--        servlet依赖-->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
            </dependency>
    <!--        JSP依赖-->
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.1</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>
    <!--        连接数据库-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.49</version>
            </dependency>
        </dependencies>
    
  2. 编写过滤器

    1. 注意: 导包 import javax.servlet.*;​

    2. 实现Filter接口, 重写对应的方法

      package com.karl.filter;
      
      import javax.servlet.*;
      import java.io.IOException;
      
      public class CharacterEncodingFilter implements Filter {
          //初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
          public void init(FilterConfig filterConfig) throws ServletException {
              System.out.println("CharacterEncodingFilter初始化");
          }
          // Chain :链
          /*
              1.过滤中的所有代码,在过滤特定请求的机候都会执行
              2.必须要让过滤器继续通行
              chain.doFilter( request,response);
          */
      
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
              request.setCharacterEncoding("utf-8");
              response.setCharacterEncoding("utf-8");
              response.setContentType("text/html;charset=utf-8");
              System.out.println("doFilter! 1");
              chain.doFilter(request,response);//让请求继续走,如果不写,程序到这里就被拦截停止!
              System.out.println("doFilter! 2");
          }
      
          //销毁: web服务器关闭的时候,过滤会销毁
          public void destroy() {
              System.out.println("CharacterEncodingFilter销毁");
          }
      }
      
    3. web.xml 中配置 filter

      <filter>
          <filter-name>CharacterEncodingFilter</filter-name>
          <filter-class>com.karl.filter.CharacterEncodingFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>CharacterEncodingFilter</filter-name>
          <url-pattern>/servlet/*</url-pattern>
      </filter-mapping>
      

12 监听器

实现一个监听器的接口

  1. 编写一个监听器

    package com.karl.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    //统计网站在线人数: 统计session
    public class OnlineCountListener implements HttpSessionListener {
        @Override
        //创建session监听:看你的一举一动
        //一旦创建Session就会触发一次这个事件!
        public void sessionCreated(HttpSessionEvent httpSessionEvent) {
            ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
            Integer onlineCount = (Integer)servletContext.getAttribute("OnlineCount");
            if (null == onlineCount){
                onlineCount = 1;
            }else {
                int count = onlineCount;
                onlineCount = count + 1;
            }
            servletContext.setAttribute("OnlineCount", onlineCount);
        }
    
        @Override
        //销毁session监听
        //一旦销毁Session就会触发一次这个事件!
        public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        }
    }
    
  2. web.xml中配置监听器

    <listener>
        <listener-class>com.karl.listener.OnlineCountListener</listener-class>
    </listener>
    
  3. 看情况使用

13 过滤器的常见使用

登录: 用户登录之后才能进入主页!用户注销后就不能进入主页了!

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

    package com.karl.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 LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取前端请求的参数
            String username = req.getParameter("username");
            if (username.equals("admin")){//登录成功
                req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
                resp.sendRedirect(req.getContextPath()+"/sys/success.jsp");
            }else {
                resp.sendRedirect(req.getContextPath()+"/error.jsp");
            }
        }
    }
    
  2. 进入主页的时候要判断用户是否已经登录; 要求:在过滤器中实现!

    package com.karl.filter;
    
    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 servletReq = (HttpServletRequest)servletRequest;
            HttpServletResponse servletResp = (HttpServletResponse) servletResponse;
    
            if(null == servletReq.getSession().getAttribute("USER_SESSION")){
                servletResp.sendRedirect(servletReq.getContextPath()+"/error.jsp");
            }
    
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
  3. 注销

    package com.karl.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.HashMap;
    
    public class LogoutServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Object user_session = req.getSession().getAttribute("USER_SESSION");
            if (null != user_session){
                req.getSession().removeAttribute("USER_SESSION");
                resp.sendRedirect(req.getContextPath()+"/index.jsp");
            }else {
                resp.sendRedirect(req.getContextPath()+"/index.jsp");
            }
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

14 JDBC

什么是JDBC : Java连接数据库!

JDBC示意图

需要jar包的支持:

  • java.sql
  • javax.sql
  • mysql-conneter-java.... 连接驱动((必须要导入)

导入数据库依赖

<! --mysq1的驱动-->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysq1-connector-java</artifactId>
	<version>5.1.47</version>
</dependency>
CREATE TABLE users(
	id lNT PRIMARY KEY,
    `name` VARCHAR(40),
    `password` VARCHAR(40),
    email VARCHAR(60),
    birthday DATE
);
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', 'Is@qq.com'; '2000-01-01');
NSERT INTO users(id, `name`, `password`, email, birthday)
VALUES(3,'王五','123456','ww@qq.com' ; '2000-01-01'");
package com.karl.test;
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 : CRUD
	Statement statement = connection.createstatement();
	//4.编写SQL
	string sql = "select * from users";
	//5.执行查询SQL,返回一个Resultset :结果集
	Resultset rs = statement.executeQuery(sql);
	while (rs.next()){
		system.out.println("id="+rs.getobject("id"));
		system.out.println("name="+rs.getobject("name"));
		system.out.println("password="+rs.getobject("password"));
		system.out.println("email="+rs.getobject("email"));
        system.out.println("birthday="+rs.getobject("birthday"));
	}
	//6.关闭连接,释放资源(一定要做)先开后关
	rs.close();
	statement.close();
	connection.close();

IDEA中连接数据库

JDBC固定步骤:

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 向数据库发送SQL的对象Statement : CRUD
  4. 编写SQL(根据业务,不同的SQL)
  5. 执行SQL
  6. 关闭连接

预编译

//1.加载驱动
class.forName( "com.mysq1.jdbc.Driver" ) ;
//2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url,username,password);
//3.编写SQL
string sql = "insert into users(id,name,password,email, birthday) values (?,?,?,?,?);";
//4.预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt( parameterIndex: 1, x: 4);//给第一个占位符?的值赋值为1;
preparedStatement.setString( parameterlndex: 2,x:"狂神说Java");//给第二个占位符?的值赋值为狂神说Java;
preparedStatement.setString( parameterlndex: 3, x:"123456");//给第三个占位符?的值赋值为123456;
preparedStatement . setString( parameterlndex: 4, x:"24736743@qq.com");//给第四个占位符?的值赋值;
preparedStatement.setDate( parameterlndex: 5,new Date(new java.util.Date().getTime()));
//5.执行SQL
int i = preparedstatement.executeUpdate();
if (i>0){
	system.out.print1n("插入成功@");
}
//6.关闭连接,释放资源(一定要做)先开后关
preparedStatement.close();
connection.close();

遇到的问题

java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

SMBMS系统

数据库

image-20201123203716364

项目如何搭建?

项目搭建准备工作

  1. 搭建一个maven web项目

  2. 配置Tomcat

  3. 测试项目是否能够跑起来

  4. 导入项目中会遇到的jar包;

    jsp,Servlet,mysql驱动,jstl,stand...5.

    <dependencies>
      <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
      </dependency>
      <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2.1-b03</version>
      </dependency>
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.49</version>
      </dependency>
        <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp.jstl</groupId>
      <artifactId>jstl-api</artifactId>
      <version>1.2</version>
    </dependency>
    </dependencies>
    
  5. 创建项目包结构

    image-20201123205527256

  6. 编写实体类;
    ORM映射:表-类映射

  7. 编写基础公共类

    1. 数据库配置文件

      driver = com.mysql.jdbc.Driver
      url = jdbc:mysql://localhost:3306?useUnicode=true&charEncoding=utf-8
      username = root
      password = root
      
    2. 数据库公共类

      package com.karl.dao;
      
      import java.io.IOException;
      import java.io.InputStream;
      import java.sql.*;
      import java.util.Properties;
      
      //操作数据库的公共类
      public class BaseDao {
          public static String driver;
          public static String url;
          public static String username;
          public static String password;
      
          //静态代码块,类加载的时候就初始化了
          {
              Properties properties = new Properties();
              //通过类加载器读取对应的资源
              InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
              try {
                  properties.load(is);
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
              driver = properties.getProperty("driver");
              url = properties.getProperty("url");
              username = properties.getProperty("username");
              password = properties.getProperty("password");
          }
      
          //获取数据库的连接
          public static Connection getConnection(){
              Connection connection = null;
              try {
                  Class.forName(driver);
                  connection = DriverManager.getConnection(url, username,password);
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return connection;
          }
      
          //查询公共方法
          public static ResultSet execute(Connection connection, String sql, Object[] params, ResultSet resultSet, PreparedStatement preparedStatement) throws SQLException {
              //硕编译的saL.在后面直接执行就可以了
              preparedStatement = connection.prepareStatement(sql);
              for (int i = 0; i < params.length; i++) {
                  //setObject,占位符从1开始,但是我们的数组是从e开始!
                  preparedStatement.setObject(i+1, params);
              }
              resultSet = preparedStatement.executeQuery();
              return resultSet;
          }
      
          //增删改公共方法
          public static int execute(Connection connection, String sql, Object[] params, PreparedStatement preparedStatement) throws SQLException {
              preparedStatement = connection.prepareStatement(sql);
              for (int i = 0; i < params.length; i++) {
                  //setObject,占位符从1开始,但是我们的数组是从e开始!
                  preparedStatement.setObject(i+1, params);
              }
              int updateRows = preparedStatement.executeUpdate();
              return updateRows;
          }
      
          //释放资源
          public static boolean closeResource(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){
              boolean flag = true;
              if (null != resultSet){
                  try {
                      resultSet.close();
                      //GC回收
                      resultSet = null;
                  } catch (SQLException throwable) {
                      throwable.printStackTrace();
                      flag = false;
                  }
              }
              if (null != connection){
                  try {
                      connection.close();
                      //GC回收
                      connection = null;
                  } catch (SQLException throwable) {
                      throwable.printStackTrace();
                      flag = false;
                  }
              }
              if (null != preparedStatement){
                  try {
                      preparedStatement.close();
                      //GC回收
                      preparedStatement = null;
                  } catch (SQLException throwable) {
                      throwable.printStackTrace();
                      flag = false;
                  }
              }
              return flag;
          }
      }
      
    3. 字符编码过滤器

      package com.karl.filter;
      
      
      import javax.servlet.*;
      import java.io.IOException;
      
      public class CharacterEncodingFilter implements Filter {
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
      
          }
      
          @Override
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
              request.setCharacterEncoding("utf-8");
              response.setCharacterEncoding("utf-8");
      
              chain.doFilter(request,response);
          }
      
          @Override
          public void destroy() {
      
          }
      }
      

      web.xml

      <filter>
          <filter-name>CharacterEncodingFilter</filter-name>
          <filter-class>com.karl.filter.CharacterEncodingFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>CharacterEncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
      
  8. 导入静态资源文件

登录功能实现

image-20201123221614747

  1. 编写前端页面

  2. 设置首页

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

    package com.karl.dao.user;
    
    import com.karl.pojo.User;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    public interface UserDao {
        //得到要登录的用户
        public User getLoginUser(Connection connection, String userCode) throws SQLException;
    
    }
    
  4. 编写Dao接口的实现类

    package com.karl.dao.user;
    
    import com.karl.dao.BaseDao;
    import com.karl.pojo.User;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class UserDaoImpl implements UserDao {
        @Override
        public User getLoginUser(Connection connection, String userCode) throws SQLException {
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            User user = null;
            if (null != connection){
                String sql = "select * from smbms_user where userCode=?";
                Object[] params = {userCode};
    
    
                resultSet = BaseDao.execute(connection,preparedStatement,resultSet,sql,params);
                if (resultSet.next()){
                    user = new User();
                    user.setId(resultSet.getInt("id"));
                    user.setUserCode(resultSet.getString("userCode"));
                    user.setUserName(resultSet.getString( "userName"));
                    user.setUserPassword(resultSet.getString("userPassword" ));
                    user.setGender(resultSet.getInt("gender" ));
                    user.setBirthday(resultSet.getDate("birthday" ));
                    user.setPhone(resultSet.getString("phone" ));
                    user.setAddress(resultSet.getString("address"));
                    user.setUserRole(resultSet.getInt("userRole"));
                    user.setCreatedBy(resultSet.getInt("createdBy" ));
                    user.setCreationDate(resultSet.getTimestamp("creationDate"));
                    user. setModifyBy(resultSet.getInt("modifyBy" ));
                    user.setModifyDate(resultSet.getTimestamp("modifyDate"));
                }
                BaseDao.closeResource(null, preparedStatement,resultSet);
            }
            return user;
        }
    }
    
  5. 业务层接口

    public User login (String userCode, String password);
    
  6. 业务层实现类

    public class UserServiceImpl implements UserService{
        //业务层都会调用dao层,所以我们要引入Dao层;
        private UserDao userDao;
    
        public UserServiceImpl() {
            userDao = new UserDaoImpl();
        }
    
        @Override
        public User login(String userCode, String password) {
            Connection connection = null;
            User user = null;
            try {
                connection = BaseDao.getConnection();
                //通过业务层调用对应的具体数据库操作
                user = userDao.getLoginUser(connection, userCode);
    
            } catch (SQLException throwable) {
                throwable.printStackTrace();
            }finally {
                BaseDao.closeResource(connection,null,null);
            }
            return user;
        }
    
  7. 登录servlet

    package com.karl.servlet.user;
    
    import com.karl.pojo.User;
    import com.karl.service.user.UserService;
    import com.karl.service.user.UserServiceImpl;
    import com.karl.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 {
        //servlet: 控制层业务层 service
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("LoginServlet start...");
            String userCode = req.getParameter("userCode");
            String userPassword = req.getParameter("userPassword");
    
            //和数据库中的密码对比, 调用业务层
            UserService userService = new UserServiceImpl();
            User user = userService.login(userCode, userPassword);//查出登录的人了
            if (null != user && userPassword.equals(user.getUserPassword())){//有此人且密码正确, 可以登录
                //将信息放入session中
                req.getSession().setAttribute(Constants.USER_SESSION, user);
                resp.sendRedirect(req.getContextPath() + "/jsp/frame.jsp");//重定向
            }else{//用户名或者密码错误, 不可登录
                //转发回登录页面,顺带提示它,用户名或者密码错误;
                req.setAttribute("error", "用户名或密码不正确");
                req.getRequestDispatcher("/login.jsp").forward(req,resp);//转发
            }
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  8. 登录servlet的web.xml配置

        <!--登录servlet-->
        <servlet>
            <servlet-name>LoginServlet</servlet-name>
            <servlet-class>com.karl.servlet.user.LoginServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>LoginServlet</servlet-name>
            <url-pattern>/login.do</url-pattern>
        </servlet-mapping>
    
  9. 注销servlet和servlet配置

    package com.karl.servlet.user;
    
    import com.karl.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 {
            //移除用户的Constants. USER_SESSION
            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);
        }
    }
    
    <!--    注销servlet-->
        <servlet>
            <servlet-name>LogoutServlet</servlet-name>
            <servlet-class>com.karl.servlet.user.LogoutServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>LogoutServlet</servlet-name>
            <url-pattern>/jsp/logout.do</url-pattern>
        </servlet-mapping>
    
  10. 未登录过滤

    package com.karl.filter;
    
    import com.karl.pojo.User;
    import com.karl.util.Constants;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.net.http.HttpRequest;
    
    public class SysFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @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);//过滤器,从session中获取用户,
            if (null == user){
                resp.sendRedirect(req.getContextPath()+"/error.jsp");
            }
            else{
                chain.doFilter(request, response);
            }
        }
    
        @Override
        public void destroy() {
    
        }
    }
    

    web.xml

    <!--    未登陆过滤-->
        <filter>
            <filter-name>SysFilter</filter-name>
            <filter-class>com.karl.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></1i>
    
  2. 写项目,建议从底层向上写

  3. UserDao接口

        //修改当前用户密码
        int updatePwd(Connection connection, String id, String password) throws SQLException;
    
  4. UserDao接口实现类

        //修改当前用户密码
        @Override
        public int updatePwd(Connection connection, String id, String password) throws SQLException {
            String sql = "update smbms_user set userPassword = ? where id = ?";
            Object[] params = {password, id};
            return BaseDao.executeU(connection, sql, params);
        }
    
  5. UserService接口

        //修改密码业务
        public int updatePwd(String id, String pwd);
    
  6. UserService实现类

        //修改密码业务
        @Override
        public boolean updatePwd(String id, String pwd) throws SQLException {
            boolean flag = false;
            Connection connection = null;
            connection = BaseDao.getConnection();
            if (userDao.updatePwd(connection, id, pwd)>0){
                flag = true;
            }
    
            BaseDao.closeResource(connection,null,null);
            return flag;
        }
    
  7. servlet配置

    <!--    用户操作-->
        <servlet>
            <servlet-name>UserServlet</servlet-name>
            <servlet-class>com.karl.servlet.user.UserServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>UserServlet</servlet-name>
            <url-pattern>/jsp/user.do</url-pattern>
        </servlet-mapping>
    
  8. servlet

  9. 实现复用需要提取方法

修改密码的js(Ajax)

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()},
			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 === "sessionerror"){//当前用户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 > 5
				&& 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 > 5
				&& 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();
			}
		}
		
	});
});
//js(Ajax)验证
    private void pwdmodifyServlet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String oldpassword = req.getParameter("oldpassword");
        //从session里面拿密码
        User user = (User) req.getSession().getAttribute(Constants.USER_SESSION);
        //用map传递参数 结果集
        HashMap<String, String> resultHashMap = new HashMap<>();

        if (null == user){      //session过期
            resultHashMap.put("result", "sessionerror");
        }else if (oldpassword.isEmpty()){       //得到的密码为空
            resultHashMap.put("result", "error");
        }else {     //密码不为空
            if (oldpassword.equals(user.getUserPassword())){        //密码正确
                resultHashMap.put("result", "true");
            }else {     //密码错误
                resultHashMap.put("result", "false");
            }
        }
        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(JSONArray.toJSONString(resultHashMap));
        writer.flush();
        writer.close();
    }

用户管理实现

image-20201201102327043

  1. 导入分页的工具类

    package com.karl.util;
    
    public class PageSupport {
    	//当前页码-来自于用户输入
    	private int currentPageNo = 1;
    	
    	//总数量(表)
    	private int totalCount = 0;
    	
    	//页面容量
    	private int pageSize = 0;
    	
    	//总页数-totalCount/pageSize(+1)
    	private int totalPageCount = 1;
    
    	public int getCurrentPageNo() {
    		return currentPageNo;
    	}
    
    	public void setCurrentPageNo(int currentPageNo) {
    		if(currentPageNo > 0){
    			this.currentPageNo = currentPageNo;
    		}
    	}
    
    	public int getTotalCount() {
    		return totalCount;
    	}
    
    	public void setTotalCount(int totalCount) {
    		if(totalCount > 0){
    			this.totalCount = totalCount;
    			//设置总页数
    			this.setTotalPageCountByRs();
    		}
    	}
    	public int getPageSize() {
    		return pageSize;
    	}
    
    	public void setPageSize(int pageSize) {
    		if(pageSize > 0){
    			this.pageSize = pageSize;
    		}
    	}
    
    	public int getTotalPageCount() {
    		return totalPageCount;
    	}
    
    	public void setTotalPageCount(int totalPageCount) {
    		this.totalPageCount = totalPageCount;
    	}
    	
    	public void setTotalPageCountByRs(){
    		if(this.totalCount % this.pageSize == 0){
    			this.totalPageCount = this.totalCount / this.pageSize;
    		}else if(this.totalCount % this.pageSize > 0){
    			this.totalPageCount = this.totalCount / this.pageSize + 1;
    		}else{
    			this.totalPageCount = 0;
    		}
    	}
    	
    }
    
  2. 导入用户列表页

获取用户数量

  1. UserDaoImpl

    
        /**
         * 根据用户名或者角色名得到用户的总数
         *
         * @param connection 数据库的连接
         * @param username   用户名
         * @param userRole   用户角色
         * @return int 数量
         */
        @Override
        public int getUserCont(Connection connection, String username, int userRole) throws SQLException {
            int count = 0;//用户数量
            if (null == connection) {
                return 0;
            }
            StringBuilder sql = new StringBuilder();//新建字符串缓冲区用来存储SQL语句
            sql.append("select count(1) as count from smbms_user u, smbms_role r where u.userRole = r.id ");
            ArrayList<Object> list = new ArrayList<>();//index由0开始
            if (!username.isEmpty()){
                sql.append("and u.userName like ? ");
                list.add("%"+username+"%");//sql中使用like模糊查询时参数需要%%包裹
            }
            if (!username.isEmpty()){
                sql.append("and u.userRole = ? ");
                list.add(userRole);
            }
            // 把list转化为数组
            Object[] objects = list.toArray();
            ResultSet resultSet = BaseDao.executeQ(connection, sql.toString(), objects);//查询, 并捕获sql异常
    
            if (resultSet.next()){
                count = resultSet.getInt("count");//从结果集中的到的数量
            }
            BaseDao.closeResource(connection,null,resultSet);
            return count;
        }
    
  2. UserServiceIpml

    
    
原文地址:https://www.cnblogs.com/karlshuyuan/p/14096654.html