• 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

      
      
  • 相关阅读:
    日志收集
    解决spawn-fcgi child exited with: 1
    confluence启动关闭
    Informatica 启动、停止工作流命令
    启动obiee
    oracle修改连接空闲自动断开
    ORA-00845: MEMORY_TARGET not supported on this system
    svn执行clean up命令时报错
    手游推广
    phonegap/cordova 升级版本
  • 原文地址:https://www.cnblogs.com/karlshuyuan/p/14096654.html
Copyright © 2020-2023  润新知