JavaWeb

Java Web

1. 基本概念

1.1 前言

web开发

  • web 网页 www.baidu.com
  • 静态web
    • html,css
    • 提供给所有人看的数据始终不会发生变化
  • 动态web
    • 淘宝 几乎是所有的网站
    • 提供给所有人看的数据始终会发生变化 每个人在不同的时间 不同的地点看到的信息各不相同!
    • 技术栈: servlet/ISP ASP PHP

在Java中 动态web资源开发的技术统称为JavaWeb

1.2 web应用程序

web应用程序 可以提供浏览器访问的程序;

  • a.html b.html…多个web资源 这些web资源可以被外界访问 对外界提供服务
  • 访问到的任何一个页面或者资源 都存在于这个世界的某一个计算机上
  • URL
  • 这些统一的web资源会被放在同一个文件夹下 web应用程序–>Tomcat服务器
  • 一个web应用由多部分组成(静态web 动态web)
    • html css js
    • jsp servlet
    • Java程序
    • jar包
    • 配置文件(properties)

web应用程序编写完毕后 若想要提供给外界访问 需要一个服务器来统一管理

1.3 静态web

  • *.htm *.html这些都是网页的后缀 如果服务器上一直存在这些东西 我们就可以直接进行读取

  • 静态web存在的缺点

    • web页面无法动态更新 所有用户看到的都是同一个页面

      • 轮播图 点击特效 伪动态
      • JavaScript[实际开发中 用的非常多]
      • VBScript
    • 它无法和数据库交互(数据无法持久化 用户无法交互)

1.4 动态web

页面会动态的展示 “web的页面展示的效果 因人而异”

动态web的缺点

  • 假如服务器的动态web资源出现了错误 我们需要重新编写我们的后台程序 重新发布

    • 停机维护

动态web的优点

  • web页面可以动态更新 所有用户看到的都是同一个页面

    • 轮播图 点击特效 伪动态
    • JavaScript[实际开发中 用的非常多]
    • VBScript
  • 它可以和数据库交互(数据持久化 注册 商品买卖 用户交互…)

2 web服务器

2.1 技术讲解

ASP

  • 微软国内最早流行的就是ASP

  • 在HTML中嵌入了VB的脚本 ASP+COM

  • 在ASP开发中 基本一个页面(基本一个页面都有几千行的业务代码 页面机器混乱)

    <h1><%System.out.println("你好")%><h1>
    
  • 维护成本太高

  • C#

  • IIS

PHP

  • PHP开发速度很快 功能很强大 跨平台 代码很简单
  • 无法承载巨大的访问量(局限性) 但是大部分的网站都是中小型

JSP /Servlet

B/S 浏览器和服务器

C/S 客户端和服务器

  • sun公司主推的B/S架构
  • 基于Java语言(所有的大公司 和一些开元的组件 都是Java写的)
  • 可以承载三高问题(高性能 高并发 高性能)
  • 语法类似ASP ASP–>JSP 加强市场强度

2.2 web服务器

服务器是一种被动的操作 用来处理用户的一些请求 和给用户一些响应信息

IIS

微软的ASP windows中自带的

Tomcat

Tomcat是Apache 软件基金会的Jakarta 项目中的一个核心项目,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,,成为目前比较流行的Web 应用服务器。

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,目前Tomcat最新版本为9.0.37**。**

下载Tomcat

  1. 安装 or 解压
  2. 了解配置文件及目录结构
  3. 这个东西的作用

3. Tomcat

3.1 安装Tomcat

Tomcat官方:https://tomcat.apache.org/

3.2 Tomcat

文件夹文件说明

启动 关闭Tomcat

访问测试http://localhost:8080/

可能遇到的问题

  1. Java环境变量没有配置
  2. 闪退问题需要配置兼容性
  3. 乱码问题 配置文件中的设置

3.3 Tomcat配置

可以配置启动的端口号

可以配置主机的名称

  • Tomcat默认端口 8080

  • mysql 3306

  • http 80

  • https 443

      <Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
    

可以配置主机的名称

  • 默认的主机名称为 localhost ->127.0.0.1
  • 默认网站应用存放位置为 webapps
  <Host name="localhost"  appBase="webapps"unpackWARs="true" autoDeploy="true">

面试题

网站是如何进行访问的

  1. 输入一个域名

  2. 检查本机的 C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射

    1. 有 返回对应的ip地址

      127.0.0.1 www.localhost.com
      
    2. 没有去DNS找 找到的话就返回 找不到就返回找不到

3.4 发布一个web网站

不会就先模仿

  • 将自己写的网站 放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下 就可以访问了问斩应该有的结构了

    -- webapps:Tomcat服务器的web目录--ROOT--lhc 网站的目录名--WEB-INF-web.xml 网站配置文件-classes Java程序-lib web 应用所依赖的jar包-index.html 默认的首页-static-css-style.css-js-img-....
    

4 HTTP

4.1 什么是HTTP

HTTP

HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。

HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。

  • 文本 html 字符串
  • 超文本 图片 音乐 视频 定位 地图…
  • 端口 80

Https

  • 端口 443

4.2 两个时代

  • http1.0

    • HTTP/1.0 客户端可以与web服务器连接 只能获得一个web资源 断开连接
  • http2.0

    • HTTP/1.1:客户端可以与web服务器连接 能获得多个web资源

4.3 HTTP请求

  • 客户端—发请求(Request)—服务器

百度:

Request URL: https://www.baidu.com/  请求地址
Request Method: GET    //get方法 post方法
Status Code: 200 OK     //状态码
Remote(远程) Address: 163.177.151.110:443

1.请求行(general)

  • 请求行中的请求方式 GET
  • 请求方式:Get/post HEAD DELETE PUT
    • get 请求能够携带的参数比较少 大小有限制 会在浏览器的URL地址栏显示数据雷人 不安全 但是高效
    • post 请求能够携带的参数没有限制 大小没限制 不会在浏览器的URL地址栏显示数据雷人 安全 但是低效

2 消息头(response)

Accept:告诉浏览器 他所支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISP8859-1
Accept-Language: 告诉浏览器它的语言环境
Cache-Control:缓冲控制
Connection:告诉浏览器 请求完成是断开还是保持连接
HOST:主机地址

4.4 HTTP响应

  • 服务器—响应—客服端

百度:

Cache-Control: private  //缓冲控制
Connection: keep-alive  //连接
Content-Encoding: gzip
charset=utf-8 //编码
Content-Type: text/html; //类型
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9   //语言
Cache-Control: max-age=0
Connection: keep-alive

1. 响应体(request)

Accept:告诉浏览器 他所支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISP8859-1
Accept-Language: 告诉浏览器它的语言环境
Cache-Control:缓冲控制
Connection:告诉浏览器 请求完成是断开还是保持连接
HOST:主机地址
Refrush:告诉客户端 多久刷新一次
Location:让网页重写定位

2.响应状态码

200:请求响应成功

3**:请求重定向

  • 重定向:重新到我给你的新位置上去

4**:找不到资源

  • 资源不存在 404

5**:服务器代码错误 500 502网关错误

常见面试题

当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来 经历了什么?

5 Maven

为什么要学习这个技术

  1. 在javaweb开发中 需要使用大量的jar包 我们要手动导入
  2. 如何能够让一个东西自动帮我导入这个和配置这个jar包

由此Maven诞生了

5.1 Maven架构管理工具

我们目前用来就是方便导入jar包的

Maven的核心思想 约定大于配置

  • 有约束 不要去违反

Maven会规定好你该去如何去编写我们的Java代码 必须按照这个规范来

5.2 下载安装Maven

官方 https://maven.apache.org/

下载完解压即可:

电脑的所有环境最好放一起

5.3 配置环境变量

在我们的系统环境变量中

配置如下

  • M2_HOME maven目录下的bin目录
  • MAVEN_HOME maven的目录
  • 在系统的path中配置 %MAVEN_HOME%\bin

测试是否成功

5.4 阿里云镜像

  • mirrors

    • 作用 加速我们的下载
  • 国内建议使用阿里云的镜像
    • https://developer.aliyun.com/article/512821

5.5 本地仓库

在本地的仓库 远程仓库

建立一个本地仓库 (新建文件夹 maven-repo)

5.6 在IDEA中使用Maven

  1. 启动IDEA

  2. 等待项目初始化

6.

  1. IDEA中的Maven设置

  1. 到这里 Maven就已经配置完成了

5.7 创建一个普通的Maven项目

不选择要导入的maven包 直接创建一个普通的Maven项目

选择了javaweb的项目 这个只有在Web应用下才有

5.8 标记文件夹功能

5.9 在IDEA中配置Tomcat

5.10 pom文件

pom.xml是Maven的核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!--Maven版本和头文件-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion>
<!--这里就是我们刚才配置的GAV--><groupId>com.lhc</groupId><artifactId>javaweb-01-maven</artifactId><version>1.0-SNAPSHOT</version>
<!--Packaging:项目的打包方式jar:java应用war:JavaWeb应用--><packaging>war</packaging><name>javaweb-01-maven Maven Webapp</name><!-- FIXME change it to the project's website --><url>http://www.example.com</url>
<!--配置--><properties>
<!--项目的默认构建编码--><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--编码版本--><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties>
<!--项目依赖--><dependencies>
<!--具体依赖的jar包配置文件--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency></dependencies>
<!--项目构建用的东西--><build><finalName>javaweb-01-maven</finalName><pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --><plugins><plugin><artifactId>maven-clean-plugin</artifactId><version>3.1.0</version></plugin><!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --><plugin><artifactId>maven-resources-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version></plugin><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.22.1</version></plugin><plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version></plugin><plugin><artifactId>maven-install-plugin</artifactId><version>2.5.2</version></plugin><plugin><artifactId>maven-deploy-plugin</artifactId><version>2.8.2</version></plugin></plugins></pluginManagement></build>
</project>

maven由于他的约定大于配置 我们之后可能遇到我们写的配置文件 无法被导出或者生效的问题 解决方案

<!--在build中配置resources 来防止我们资源导出失败的问题-->
<build><resources><resource><directory>src/main/resources</directory><excludes><exclude>**/*.properties</exclude><exclude>**/*.xml</exclude></excludes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources>
</build>

5.11 IDEA操作

Maven中jar包的联系的关联图

5.12 遇到的问题

1.Maven3.6.2

解决方法 降级为3.6.1

2.Tomcat闪退

配置Tomcat start.bat文件(目前不知道怎么解决)

3.IDEA每次都要重复配置Maven

在IDEA中全局默认配置中去配置

4.maven默认web项目中的web.xml版本问题

替换为wenbapp4.0版本和Tomcat一致

<?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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"><display-name>Welcome to Tomcat</display-name><description>Welcome to Tomcat</description></web-app>

5.Maven项目中无法配置Tomcat

必须要的配置 :为什么会有这个问题 我们访问一个网站 需要制定一个文件夹名字

切记 下面的配置文件是你现在的项目 不是其他的

还有 一定要打开Tomcat服务 不然怎么调整也没用

还有 一定要打开Tomcat服务 不然怎么调整也没用

还有 一定要打开Tomcat服务 不然怎么调整也没用

1.

6.maven仓库的使用

进入官方https://mvnrepository.com/?cf_chl_captcha_tk=a48f18039660094440761e1b6d230ce6a69c55f8-1602326539-0-Afkz8Ted5KWfCo94r18BZ1Np84NIY65dJzT-JICrG8uKuvDHc7d-Vj3KkCSmvqWeivkNh-6pDMkZlW4_GZfollylgMnsz4bsA3sgmXHNuQRa89eW_4iPugscHbCD8MSdAKmS1zgUmaL5HGqMV3I0z3LK351OLOdCVvPbVQ57dGc-17W1Mg-TUEiVQS0hL5JfJi1GioiVogtA28MlXOmYAJAeGAw6_Mbew9qG38W2yGGQZ45voy_d1toUH8IgPY3h-87F-vB378PXe_xno313C-M4asXkOYRzKzn3F6pnmX8cqvQUaCqF1hLgvTocE4Q9V2AtDiXRS5Yd1pTeKOt0iXNsA1Af-5Yt3dxIBi9Mpr8CFTgcPZB–rCU7mdxI7iEq22JYDL8KU_bPEBddTMDztzk6vWvB8bKTLsVbmxb-6yvxT2sIxru83u6Y2oqpvIasLeyAz5p2z5KiwkVDRgg8V900O-OXi2MTwy1h3XXZLCcvguicxaSYruWdBepEITZNXOA_fXDA6R2dPNsnIz8myRet7ZfGvu8o5IYEiL-y64v


6.Servlet

6.1 Servlet简介

  • Servlet就是Sun公司开发动态web的一门技术
  • Sun公司在这些API中提供了一个接口 Servlet 如果你想开发一个Servlet程序 只需要完成两个小步骤
    • 编写一个类 实现Servlet接口
    • 把开发好的Java类部署到web服务器中

把实现了Servlet接口的Java程序叫做 Servlet

6.2 HelloServlet

Servlet接口有两个默认的实现类 HttpServlet,GenericServlet

  1. 构建一个普通Maven项目 删掉里面的src目录 以后我们的学习就在这个项目里面简历moudel 这个空的工程就是Maven的主工程

  2. guanyu Maven父子工程的理解:

    父项目中会有

    <modules><module>servlet-01</module>
    </modules>
    

    子项目中会有

    <parent><artifactId>javaweb-02-servlet</artifactId><groupId>com.lhc</groupId><version>1.0-SNAPSHOT</version>
    </parent>
    

    父项目中的java子项目可以直接使用

    son extends father
    
  3. Maven环境优化

    1. 修改web.xml为最新的
    2. 将maven的结构搭建完整
  4. 编写一个Servlet程序

    1. 编写一个普通类

    2. 实现Servlet接口 我们这里直接继承HttpServlet

    3. public class HelloServlet extends HttpServlet {//由于get和post只是请求实现的不同的方式 可以互相调用 业务逻辑一样@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletOutputStream outputStream = resp.getOutputStream();PrintWriter writer = resp.getWriter();//响应流writer.println("hello servlet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
      }
      
  5. 编写Servlet的映射

    为什么需要映射 我们写的是java程序 但是要通过浏览器访问

    浏览器需要连接web服务器

    所以我们需要在web服务器中注册我们写的Servlet

    还需要给他一个浏览器能够访问的路径

    <!--注册Servlet-->
    <servlet><servlet-name>hello</servlet-name><servlet-class>com.lhc.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径-->
    <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  6. 配置Tomcat

    注意配置项目发布的路径就可以了

  7. 启动测试

6.3 Servlet原理

Servlet是由Web服务器调用

web服务器在收到浏览器请求之后 会:

6.4 Mapping问题

  1. 一个Servlet可以指定一个映射路径(http://localhost:8080/hello)

    <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  2. 一个Servlet可以指定多个映射路径(http://localhost:8080/s1/hello1 http://localhost:8080/s1/hello2 http://localhost:8080/s1/hello3 )

    <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello1</url-pattern>
    </servlet-mapping>
    <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello3</url-pattern>
    </servlet-mapping>
    
  3. 一个Servlet可以指定通用映射路径(比如访问http://localhost:8080/s1/qwjkejka)

    <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
    
  4. 默认请求路径(怎么访问都是hello这个servlet)

    <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/*</url-pattern>
    </servlet-mapping>
    
  5. 指定一些后缀或者前缀等等…(比如访问http://localhost:8080/s1/dsklajdlkaj.lhc http://localhost:8080/s1/hello1/dasdasjh.lhc )*前面不能写/ 但是只要是最后是.lhc就可以映射到

        <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>*.lhc</url-pattern></servlet-mapping>
    
  6. 优先级问题

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

6.5 ServletContext

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

1.共享数据

我在这个Servlet中保存的数据 可以在另外一个Servlet中拿到

设置要拿走的username数据的类

public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//this.getInitParameter()  初始化参数//this.getServletConfig()  Servlet配置//this.getServletContext();Servlet上下文ServletContext context = this.getServletContext();String username="林宏程";//数据context.setAttribute("username",username);//将一个数据保存在了ServletContext 名字为username 值为 林宏程System.out.println("hello");}
}

设置一个获取username数据的类

public class GetServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();String username = (String) context.getAttribute("username");resp.setContentType("text/html");//配置content的传输格式resp.setCharacterEncoding("utf-8");//配置content的编码resp.getWriter().println("名字"+username);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

配置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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"><servlet><servlet-name>hello</servlet-name><servlet-class>com.lhc.servlet.HelloServlet</servlet-class>
<!--        <init-param>-->
<!--            <param-name></param-name>-->
<!--            <param-value></param-value>-->
<!--        </init-param>--></servlet><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping><servlet><servlet-name>getc</servlet-name><servlet-class>com.lhc.servlet.GetServlet</servlet-class></servlet><servlet-mapping><servlet-name>getc</servlet-name><url-pattern>/getc</url-pattern></servlet-mapping></web-app>

访问的结果 需要先访问/hello 再访问/getc才能获取到username

2.获取初始化参数

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

3.请求转发

public class ServletDemo04  extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();System.out.println("进入了ServletDemo04");//RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//转发的请求路径//requestDispatcher.forward(req,resp);//调用forward实现请求转发context.getRequestDispatcher("/gp").forward(req,resp);}
}

请求转发和重定向的区别

A B C是3个网站 A需要C的数据

请求转发过程

重定向

4.读取资源文件

Properties

  • 在java目录下新建Properties
  • 在resource目录下新建Properties

发现 都被打包了同一个目录下 classes 我们俗称为classpath(类路径)

但是放在java下的db.properties需要在pom.xml加入

<!--在build中配置resources 来防止我们资源导出失败的问题-->
<build><resources><resource><directory>src/main/resources</directory><excludes><exclude>**/*.properties</exclude><exclude>**/*.xml</exclude></excludes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources>
</build>

思路 需要一个文件流

username=lhc
password=123456

然后用InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");获取里面的流

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");Properties prop1 = new Properties();prop1.load(is);String user1 = prop1.getProperty("username");String pwd1 = prop1.getProperty("password");resp.getWriter().println("lhc_username="+user1);resp.getWriter().println("lhc_password="+pwd1);InputStream si = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/lhc/servlet/aa.properties");Properties prop2 = new Properties();prop2.load(si);String user2 = prop2.getProperty("username");String pwd2 = prop2.getProperty("password");resp.getWriter().println("lt_username="+user2);resp.getWriter().println("lt_password="+pwd2);
}

访问测试即可

5.假如resource文件夹或者java文件夹打包失败

6.6HttpServletResponse

响应

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

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

1.简单的分类

负责向浏览器发送数据的方法

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;

负责想浏览器发送响应头的方法

void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
void setStatus(int var1);

响应的状态码

int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

2.常见应用

  1. 向浏览器输出消息(resp.getWriter().println(“lt_username=”)

  2. 下载文件

    1. 要获取下载文件的路径
    2. 下载的文件名叫什么
    3. 想办法让浏览器能够支持下载我们需要的东西
    4. 获取下载文件的输入流
    5. 创建缓冲区
    6. 获取OutputStream对象
    7. 将FileOutputStream流写入到buffer缓冲区
    8. 使用OutputStream将缓冲器中的数据输出到客户端

mapping不再说明

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1. 要获取下载文件的路径String realPath ="F:\\JAVA的学习\\6.JavaWeb\\javaweb-02-servlet\\response\\target\\classes\\a.jgp";System.out.println("下载文件的路径"+realPath);//2. 下载的文件名叫什么String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);//3. 想办法让浏览器能够支持下载我们需要的东西 如果文件有中文 URLEncoder.encode()编码 否则有可能有乱码resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"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缓冲区while((len=in.read(buffer))>0){out.write(buffer,0,len);}in.close();out.close();//8. 使用OutputStream将缓冲器中的数据输出到客户端
}

3.验证码

验证码怎么来的?

  • 前端实现
  • 后端实习 需要用到java的图片类 生成一个图片

mapping不再说明

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//如果让浏览器5S刷新一次resp.setHeader("refresh","3");//在内存中创建一个图片BufferedImage image = new BufferedImage(80,20,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/jpg");//网站存在缓冲 不让浏览器缓冲resp.setDateHeader("expires",-1);resp.setHeader("Cache-Control","no-cache");resp.setHeader("Pragma","no-cache");//把图片写给浏览器ImageIO.write(image,"jpg",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");}String s = sb.toString() + num;//保证num是7位 如果随机小于7位数就用0填充return num;
}

4.实现重定向

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

常见场景

  • 用户登入
void sendRedirect(String var1) throws IOException;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//        resp.setHeader("Location","/response_war/img");//        resp.setStatus(302);//重定向代码resp.sendRedirect("/response_war/img");//重定向
}

面试题 请你聊聊重定向和转发的区别

相同点

  • 页面都会实现跳转

不同点

  • 请求转发的时候 url不会产生变化(输入目的就可以)
  • 重定向的时候 url地址栏会发生变化(输入绝对路径)

请求转发过程

重定向

模拟登入

RequestTest.java

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("进入了这个请求");//处理请求String username = req.getParameter("username");//获取前端发来的usernameString password = req.getParameter("password");//获取前端发来的passwordSystem.out.println(username+"====="+password);//重定向的时候 一定要注意路径问题(绝对网页路径) 否则404resp.sendRedirect("/r/success.jsp");}

index.jsp

<html>
<body>
<h2>Hello World!</h2>
<%--这里提交的路径 需要寻找到项目的路径--%>
<%--${pageContext.request.contextPath()}代表当前的项目--%>
<form method="get" action="${pageContext.request.contextPath}/login">用户名<input type="text" name="username">密码<input type="password" name="password"><input type="submit"></form>
</body>
</html>

success.jsp

<html>
<head><title>Title</title>
</head>
<body>
<h1>成功登入</h1>
</body>
</html>

从这里可以得出一个理解:

后台和前端的连接就是servlet mapping来连接的 index.jsp里有一个${pageContext.request.contextPath}/login

${pageContext.request.contextPath}指定当前页面 /login是通过mapping映射的/login才找到了 RequestTest.java 然后再通过RequestTest.java 处理这个请求 用resp.sendRedirect("/r/success.jsp");重定向到success.jsp 而控制台里输出 {进入了这个请求 1025993689=====1} 也说明前端的内容已经被我们后端获取到了

6.7HttpServletRequest

HttpServletRequest代表客户端的请求 用户通过Http协议访问服务器 HTTP请求中的所有信息会被封装到HttpServletRequest 通过这个HttpServletRequest的方法 获取客户端的所有信息

1.获取前端传递的参数

2.请求转发

重定向和转发的区别

相同点

  • 页面都会实现跳转

不同点

  • 请求转发的时候 url不会产生变化(输入目的就可以) 307
  • 重定向的时候 url地址栏会发生变化(输入绝对路径) 302

请求转发过程

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");String[] hobbies = req.getParameterValues("hobbies");//后台接受中文乱码的问题req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");System.out.println(username);System.out.println(password);System.out.println(hobbies);//通过请求转发//说明 这里的/就代表当前的web引用req.getRequestDispatcher("/success.jsp").forward(req,resp);resp.setCharacterEncoding("utf-8");}
}

7.Cookie Session

7.1会话

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

有状态会话:一个同学来过教室 下次再来教室 我们会知道这个同学 曾经来过 称之为有状态会话

如何证明自己是福建工程学院的学生?

你 福建工程学院

  1. 学生证 福建工程学院给你学生证
  2. 学校登记 福建工程学院标记你是这个学院的学生

一个网站 怎么证明你来过

客户端 服务器

  1. 服务端给客户端一个信件 客户端下次访问服务端带上信件就可以了 (cookie)
  2. 服务器登记你来过了 下次你来的时候我匹配你 (session)

7.2保存会话的两种技术

cookie

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

session

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

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

7.3cookie

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lfngq64z-1603629176227)(…/图片/image-20201017200941908.png)]

  1. 从请求中拿到cookie信息

  2. 服务器响应给客服端cookie

  3. Cookie[] cookies = req.getCookies();//获得cookie
    cookie.getName()//获得cookie中的key
    cookie.getValue()//获得cookie中的value
    Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");//新建一个cookie
    cookie.setMaxAge(24*60*60);//设置cookie的有效期
    resp.addCookie//响应给客户端一个cookie
    
  4. cookie 一般会保存在本地的 用户目录下appdata;

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

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

删除cookie

  • 不设置有效期 关闭浏览器 自动失效
  • 设置有效期时间为0 可以直接删除cookie

编码解码

//解码 这个是解决cookie的乱码
out.write(URLDecoder.decode(cookie.getValue(), "UTF-8"));
//编码  这个是解决cookie的乱码
Cookie cookie = new Cookie("name", URLEncoder.encode("林宏程", "UTF-8"));

cookie的实际使用

保存用户上一次访问的时间

//保存用户上一次访问的时间
public class CookieDemo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//服务器 告诉你 你来的时间 把这个时间封装成一个 信件 你下次带来 我就知道你来了//解决中文乱码 chrome要编码改成GBK才能解决乱码req.setCharacterEncoding("GBK");resp.setCharacterEncoding("GBK");PrintWriter out = resp.getWriter();//cookie 服务器端从客户端获取Cookie[] cookies = req.getCookies();//这里返回数组 说明cookie可能存在多个 这里是第一次创建 所以获得的cookie肯定是空的 在第二次执行的时候会把新建的cookie赋值给这个cookies//判断 cookie是否存在if (cookies!=null){//如果存在怎么办?out.write("你上一次访问的时间是:");for (int i = 0; i < cookies.length; i++) {Cookie cookie = cookies[i];//获取cookie的名字if (cookie.getName().equals("lastLoginTime")){//获取cookie中的值long lastLoginTime = Long.parseLong(cookie.getValue());Date date = new Date(lastLoginTime);out.write(date.toLocaleString());}}}else{out.write("这是你第一次访问本站");}//服务器给客户端响应一个cookieCookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");//有效期为24*60*60秒 为1天cookie.setMaxAge(24*60*60);resp.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

删除cookie

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//创建一个cookie 名字必须要和删除的名字一致Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");//将cookie有效期设为0 立马过去cookie.setMaxAge(0);resp.addCookie(cookie);}

解决中文传值乱码问题(解码编码)

//中文数据传递
public class CookieDemo03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决中文乱码req.setCharacterEncoding("GBK");resp.setCharacterEncoding("GBK");Cookie[] cookies = req.getCookies();PrintWriter out = resp.getWriter();if (cookies != null) {//如果存在怎么办?out.write("你的名字:");for (int i = 0; i < cookies.length; i++) {Cookie cookie = cookies[i];//获取cookie的名字if (cookie.getName().equals("name")) {//获取cookie中的值//解码 这个是解决cookie的乱码out.write(URLDecoder.decode(cookie.getValue(), "UTF-8"));}}} else {out.write("这是你第一次访问本站");}//编码  这个是解决cookie的乱码Cookie cookie = new Cookie("name", URLEncoder.encode("林宏程", "UTF-8"));resp.addCookie(cookie);}

7.4Session(重点)

什么是Session?

  • 服务器会给每个客服端(浏览器)创建一个Session
  • 一个Session独占一个浏览器 只要浏览器没有关闭 这个Session就存在
  • 用户登入之后 整个网站他都可以访问 -->保存用户的信息 保存购物车的信息

常用的一些方法

Session和Cookie的区别

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

区别小总结:Session像是一个储藏柜 客户端需要SessionID才能拿到储藏柜里的资源 Cookie是直接把储藏柜里的资源让客户端拿走 下次来的时候直接使用这个资源

使用场景:

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

使用Session

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");//得到SessionHttpSession session = req.getSession();//给Session中存东西session.setAttribute("name",new Person("林宏程",24));//获取Session的idString sessionId = session.getId();//判断Session是不是新建的if (session.isNew()){resp.getWriter().write("session创建成功,ID"+sessionId);}else {resp.getWriter().write("session已经存在了"+sessionId);}//Session创建的时候做了什么事情
//        Cookie cookie = new Cookie("JSESSIONID", "71804CF271369B39C1BF1EC0280BDE16");
//        resp.addCookie(cookie);}

调用Session

person对象

public class Person {private String name;private int age;
}

使用(创建Session在上面的 Session使用)

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");//得到SessionHttpSession session = req.getSession();Person person = (Person)session.getAttribute("name");System.out.println(person.toString());}

注销Session

手动注销

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();session.removeAttribute("name");//手动注销sessionsession.invalidate();
}

设置有效期(在web.xml)

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

思考 假如你用两个浏览器去访问这些网站 但是你是需要的资源是同样的

8 JSP

需要的导入包

<dependencies><!--servlet依赖--><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><!--jsp依赖--><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.3</version></dependency><!--JSTL表达式的依赖--><!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api --><dependency><groupId>javax.servlet.jsp.jstl</groupId><artifactId>jstl-api</artifactId><version>1.2</version></dependency><!--standard标签库--><!-- https://mvnrepository.com/artifact/taglibs/standard --><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency></dependencies>

8.1什么是JSP

JSP已经过时 这里的内容只需要了解 理解代码即可

Java Server page : Java服务器端页面 也和Servlet一样 用于动态Web技术

最大的特点

  • 写JSP就像在写HTML
  • 区别
    • HTML只给用户提供静态的数据
    • JSP页面中嵌入Java代码 为用户提供动态数据

8.2 JSP原理

JSP到底怎么执行的?

  • 代码层面没有任何问题

  • 服务器内部工作

    Tomcat中有一个work目录

    IDEA中使用Tomcat的会在IDEA中Tomcat中产生一个work目录

页面转变成了Java程序

浏览器向服务器发送请求 不管访问什么资源 其实都是在访问servlet

JSP最终也会转换成一个Java类!

JSP本质就是个Servlet

//初始化
public void _jspInit() {}
//销毁
public void _jspDestroy() {}
//JSP Service
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)throws java.io.IOException, javax.servlet.ServletException
  1. 判断请求

  2. 内置了一些对象

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

    response.setContentType("text/html; charset=UTF-8");//这是响应的页面类型
    pageContext = _jspxFactory.getPageContext(this, request, response,null, false, 8192, true);
    _jspx_page_context = pageContext;
    application = pageContext.getServletContext();
    config = pageContext.getServletConfig();
    out = pageContext.getOut();
    _jspx_out = out;
    
  4. 以上的这些个对象我们可以在JSP页面中直接使用

在JSP页面中 只要是Java代码 就会原封不动的输出

如果是HTML代码 就会转换成:

out.write("<html>/r/n")

这样的格式输出到前端

8.3 JSP基础语法

任何语言都有自己的语法 JAVA中有 JSP作为java技术的一种应用 他拥有一些自己扩充的语法(了解 知道即可)

Java所有语法都支持

JSP表达式

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

JSP脚本片段

<%--JSP脚本片段--%>
<%int sum=0;for (int i = 0; i < 100; i++) {sum+=i;}out.println("<h1>sum="+sum+"<h1>");
%>

脚本片段的再实现

<%--在代码中嵌入HTML元素--%>
<%for (int i = 0; i < 5; i++) {
%><h1>你好!<%=i %></h1>
<%}
%>

JSP声明

<%!static {System.out.println("Loading Servlet");}private int globalVar=0;public void lhc(){System.out.println("进入了方法lhc");}
%>

JSP声明 会被编译到JSP生成Java的类中 其他的会被生成到_jspService方法中

在JSP 嵌入Java即可

<%%>
<%=%>
<%!%>
<%--注释--%><!--我是HTML注释-->
<%--JSP的注释--%>

JSP的注释不会在客服端显示 HTML会

8.4 JSP指令

jsp3

<%@ page args... %>
<%@ include File %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html>
<head><title>Title</title>
</head>
<body><%-- <%@ include %>会将两个页面合二为一 直接把代码写到_jsp.java中 --%>
<%@ include file="common/header.jsp" %>
<h1>我是主体</h1>
<%int i=10;//因为他是直接用put.write输出 所以在这个页面不会报错 在web执行的时候 才会调用 那个时候才会报错 所以用下面的更加好%>
<%@ include file="common/footer.jsp" %><hr><%-- 拼接页面 在静态方法中调用这2个页面 --%>
<%--JSP标签 这里的路径是web--%>
<jsp:include page="/common/header.jsp"/>
<h1>我是主体</h1>
<%int i=10;//因为这个实现是直接调用本类静态方法 所以他会直接报错(i 已经定义)
%>
<jsp:include page="/common/footer.jsp"/></body>
</html>

header

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

footer

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

实际页面(没有测试 变量i调用的问题)

8.5 九大内置对象

pageContext 存东西
Request 存东西
Response
Session 存东西
Application(ServletContext) 存东西
config(ServletConfig)
out
page 几乎不用
exception

4个内置对象的作用域

生成各自Attribute

pageContext.setAttribute("name1", "pageContext");//保存的数据只在一个页面有效
request.setAttribute("name2", "request");//保存的数据只在一次请求中有效 请求转发会携带这个参数
session.setAttribute("name3", "session");//保存的数据只在一次会话中有效 打开浏览器到关闭浏览器
application.setAttribute("name4", "application");//保存的数据只在服务器中有效 打开服务器到关闭服务器//这里做了个小测试 如果用请求转发(pageContext.forward)到 pageDemo02.jsp request还是可以读取到的 但是如果用重定向(response.sendRedirect)这里的request就读取不到了
response.sendRedirect("pageDemo02.jsp");
pageContext.forward("pageDemo02.jsp");//在重定向中 A到C的时候没有转发只有请求 所以丢失了request的数据了
//而请求转发中 他是A请求B B转发C C请求B B转发A (这个理解不知道是不是对的)

转到第二个页面后去查找

<%//通过pageContext取出 我们通过寻找的方式来找//从底层到高层(作用域) page-->request-->session-->application//JVM 双亲委派机制:一个类使用方法找不到的时候 会不断向父类去找有没有存在这个方法 如果找不到就报异常 如果和根类名字一样会被无视 (听着高大上 其实很简单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><%-- EL表达式会自动过滤不存在的 但是这个不会--%>
<h3><%=name5%></h3>

原理图

请求转发过程

重定向

更改作用域

//可以设置他的作用域
pageContext.setAttribute("hello","hello",pageContext.SESSION_SCOPE);
//session.setAttribute("hello","hello"); 等价上面的代码

总结

  • request 客户端向服务器发送请求 产生的数据 用户看完就没用了 比如 新闻 用户看完就没用的

  • session 客户端向服务器发送请求 产生的数据 用户用完 一会还有用 比如 购物车

  • application 客户端向服务器发送请求 产生的数据 用户用完 其他用户还可能使用 比如 QQ聊天数据

8.6 JSP标签 JSTL标签 EL表达式

EL表达式

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

JSP标签

设值

<h1>jsptag1</h1>
<%--<jsp:include page=""--%>
<jsp:forward page="jsptag2.jsp"><jsp:param name="name" value="lhc"/><jsp:param name="age" value="24"/>
</jsp:forward>

取值

<h1>jsptag2</h1><br><%--取出参数--%>
name:  <%=request.getParameter("name")%> <br>
age:   <%=request.getParameter("age")%>

JSTL表达式

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

格式化标签

SQL标签

XML标签

核心标签(部分掌握)

JSTL标签库使用步骤

  • 引入对应的taglib

    <%--引入JSTL核心表艰苦 我们才能使用JSTL标签--%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
  • 使用其中的方法

  • 在Tomcat的lib包也需要引入JSTL的包 否则会报错 JSTL解析错误

IF使用
<h4>if测试</h4>
<hr><form action="coreif.jsp" method="get"><%--EL表达式获取表单中的数据${param.参数名}--%><input type="text" name="username" value="${param.username}"><input type="submit" value="登入"></form>
<%--判断如果提交的用户名管理员 则登入成功--%>
<%--<%--%>
<%--    if(request.getParameter("username").equals("admin")){--%>
<%--        out.print("登入成功");--%>
<%--    }--%>
<%--%>--%><c:if test="${param.username=='admin'}" var="admin"><c:out value="管理员欢迎你"/>
</c:if>
<c:out value="${isAdmin}"/>

when使用
<%--定义一个变量score 值为85--%>
<c:set value="85" var="score"/><c:choose><c:when test="${score>=90}">你的成绩为优秀</c:when><c:when test="${score<=90}">你的成绩为一般</c:when></c:choose>

foreach使用
<%ArrayList<String> people = new ArrayList<>();people.add(0,"张三");people.add(1,"李四");people.add(2,"王五");people.add(3,"赵六");request.setAttribute("list",people);%>
<%--
var 每一次遍历出来的变量
item 要遍历的对象
begin  哪里开始
step    步长
end     哪里结束
--%>
<c:forEach var="people" items="${list}"><c:out value="${people}"/> <br>
</c:forEach><hr><c:forEach  items="${list}" begin="1" step="2" end="3"><c:out value="${people}"/> <br>
</c:forEach>

这里只出来上面的遍历 下面的没出来

9 JavaBean

实体类

JavaBean有特定的写法

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

一般用来和数据库的字段做映射 ORM

ORM 对象关系映射

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

people表

id name age address
1 林宏程1 3 温州
2 林宏程2 4 温州
3 林宏程3 5 温州
class people{private int id;private String name;private int age;private String address;
}
class A{new people(1,"林宏程1",3,"温州")new people(2,"林宏程1",4,"温州")new people(3,"林宏程1",5,"温州")
}

10MVC三层架构

什么MVC:model view controller 模型/视图/控制器

10.1早些年开发

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

servlet--CRUD-->数据库
弊端 程序十分臃肿
servlet的代码中 处理请求 响应 视图跳转 处理JDBC 处理业务代码 处理逻辑代码架构 没有什么是加一层解决不了的程序员调用
|
JDBC
|
Mysql

10.2三层架构

Model

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

View

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

Controller

  • 接受用户的请求 (request.请求参数 Session信息…)

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

  • 控制跳转

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

11.Filter(重点)

这里的代码无法实现 目前无法解决这个bug 显示没有导入javax.servlet.Servlet 但是实际上导入了

Filter 过滤器 用来过滤网站的数据

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

Filter开发步骤

  1. 导包

  2. 编写过滤器(切记是这个包)

public class CharacterEncodingFilter implements Filter{//初始化 web服务器启动 就已经初始化了 随时等待过滤对象public void init(FilterConfig filterConfig) throws ServletException {System.out.println("CharacterEncodingFilter 初始化");}//chain 链/*1.过滤中的所有代码 在过滤特定请求的时候回执行2.必须要让过滤器继续同行*/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("CharacterEncodingFilter 执行前");chain.doFilter(request,response);//让我们的请求继续走 如果我们不写 程序到这里就被拦截停止了System.out.println("CharacterEncodingFilter 执行后");}//销毁 web服务器关闭的时候 过滤会销毁public void destroy() {System.out.println("CharacterEncodingFilter 销毁");}
}
  1. web.xml配置Filter过滤器(新的版本已经更改这样了 原来是用servlet来映射的)

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

12.监听器

实现个监听器的接口:

  1. 编写一个监听器

    public class OnlineCountListener implements HttpSessionListener {//创建session监听 看你的一举一动//一旦创建一个session 就会触发一次这个事件public void sessionCreated(HttpSessionEvent se) {ServletContext ctx = se.getSession().getServletContext();Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");if(onlineCount==null){onlineCount=new Integer(1);}else {int count=onlineCount.intValue();onlineCount = new Integer(count++);}ctx.setAttribute("OnlineCount",onlineCount);}//销毁session监听//一旦销毁一个session 就会触发一次这个事件public void sessionDestroyed(HttpSessionEvent se) {ServletContext ctx = se.getSession().getServletContext();Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");if(onlineCount==null){onlineCount=new Integer(0);}else {int count=onlineCount.intValue();onlineCount = new Integer(count--);}ctx.setAttribute("OnlineCount",onlineCount);}}
    
  2. web.xml注册监听器

    <!--注册监听器-->
    <listener><listener-class>com.lhc.listener.OnlineCountListener</listener-class>
    </listener>
    
  3. 看情况是否使用

13.过滤器 监听器常见应用

监听器 GUI编程中经常使用

package com.lhc.listener;import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;public class TestPanel {public static void main(String[] args) {Frame frame = new Frame("你好!");//新建一个窗体Panel panel = new Panel(null);//面板frame.setLayout(null);//设置窗体的布局frame.setBounds(300, 300, 500, 500);frame.setBackground(new Color(0, 0, 255));//设置背景颜色panel.setBounds(50, 50, 300, 300);frame.setBackground(new Color(0, 255, 0));//设置背景颜色frame.add(panel);frame.setVisible(true);//监听事件frame.addWindowListener(new WindowListener() {public void windowOpened(WindowEvent e) {System.out.println("打开");}public void windowClosing(WindowEvent e) {System.out.println("关闭中");System.exit(0);}public void windowClosed(WindowEvent e) {System.out.println("关闭");}public void windowIconified(WindowEvent e) {}public void windowDeiconified(WindowEvent e) {}public void windowActivated(WindowEvent e) {}public void windowDeactivated(WindowEvent e) {}});}
}

需求:用户登入之后才能进入主页 用户注销后就不能进入主页

  1. 用户登入的时候给用户一个session(session是存在服务器里的 每个用户都能获得自己的session )

    <form action="/servlet/login" method="post"><input type="text" name="username" /><input type="submit"/>
    </form>
    
    protected void doGet(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("/sys/success.jsp");}else {//登入失败resp.sendRedirect("error.jsp");}}
    
  2. 注销的时候要清除用户session

    <body>
    <h1>错误</h1>
    没有权限 用户名错误
    </body>
    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Object user_session = req.getSession().getAttribute("USER_SESSION");if (user_session!=null){req.getSession().removeAttribute("USER_SESSION");resp.sendRedirect("/login.jsp");}else {resp.sendRedirect("/login.jsp");}
    }
    
  3. 进入主页的时候 要判断用户是否登入 在过滤器中实现

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {//ServletRequest   HttpServletRequest  因为监听器的ServletRequest是没有重定向方法的 需要强转HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;if (request.getSession().getAttribute(Constant.USER_SESSION)==null){response.sendRedirect("/error.jsp");}chain.doFilter(request,response);
    }
    

    设置的常量USER_SESSION

    public class Constant {public final static String USER_SESSION="USER_SESSION";//因为这个session的ID经常被使用 我们可以把ID的key USER_SESSION 直接变成一个常量 这样每次调用直接写 constant.USER_SESSION//而在以后维护需要更改名字的时候 可以直接在这里改 如果是每次使用创建一个 那么修改起来会非常麻烦
    }
    

14 JDBC

什么是JDBC: Java 连接数据库

需要的jar包支持

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

实验环境搭建

public static void main(String[] args) throws ClassNotFoundException, SQLException {String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&character=utf-8";String username = "root";String password = "123456";//1.加载驱动Class.forName("com.mysql.jdbc.Driver");//2.连接数据库  connection代表数据库Connection connection = DriverManager.getConnection(url, username, password);//3.向数据库发送sql对象 statementStatement statement = connection.createStatement();//4.编写sqlString sql = "select * from users";//5.执行sql  返回一个结果集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();}

导入数据库依赖

<!--        mysql的驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.31</version></dependency></dependencies>

IDEA中连接数据库

JDBC固定步骤

  1. 加载驱动
  2. 连接数据库 代表数据库
  3. 向数据库发送sql的对象 statement
  4. 编写sql语句
  5. 执行sql
  6. 关闭连接

事务

要么都成功 要么都失败

ACID原则 保证数据的安全

开启事务
事物提交 commit()
事务回滚 rollback()
关闭事务转账 A 1000元B 1000元A(900)---100-->B(1100)

Junit单元测试

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version>
</dependency>

简单实用(如果要测试这个test方法 需要 新建一个main 但是用@Test注解就可以直接运行这个方法)

@Test
public void test(){System.out.println("你好");
}

代码演示转账

package com.lhc.test;import org.junit.Test;import java.sql.*;public class TestJDBC3 {@Testpublic void test() throws ClassNotFoundException, SQLException {Connection connection = null;try {//解决乱码问题 useUnicode=true&characterEncoding=utf8String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8";String username = "root";String password = "123456";//1.加载驱动Class.forName("com.mysql.jdbc.Driver");//2.连接数据库  connection代表数据库connection = DriverManager.getConnection(url, username, password);//3.通知数据库开启事务  关闭自动提交 相当于开启事务connection.setAutoCommit(false);//4.编写SQLString sql1 = "update account set money=money-100 where name='A'";connection.prepareStatement(sql1).executeUpdate();//制造错误int i = 1 / 0;String sql2 = "update account set money=money+100 where name='B'";connection.prepareStatement(sql2).executeUpdate();connection.commit();//以上两个SQL都执行成功了就提交时间System.out.println("");} catch (Exception e) {connection.rollback();e.printStackTrace();} finally {connection.close();}}
}

15 SMBMS(超市管理系统)

项目分析

数据库

准备项目搭建

项目如何搭建

考虑用不用Maven 依赖 Jar

Maven

  1. 搭建一个mavenweb项目

  1. 配置Tomcat

  2. 测试项目能否跑起来

  3. 导入项目中需要的jar包

        <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.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.31</version></dependency><!--JSTL表达式--><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><!--standard标签库--><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency></dependencies>
    
  4. 创建项目结构包

  5. 编写实体类

数据库编写

CREATE DATABASE `smbms`;USE `smbms`;DROP TABLE IF EXISTS `smbms_address`;CREATE TABLE `smbms_address` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',`contact` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系人姓名',`addressDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '收货地址明细',`postCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '邮编',`tel` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系人电话',`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者',`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '修改者',`modifyDate` DATETIME DEFAULT NULL COMMENT '修改时间',`userId` BIGINT(20) DEFAULT NULL COMMENT '用户ID',PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;INSERT  INTO `smbms_address`(`id`,`contact`,`addressDesc`,`postCode`,`tel`,`createdBy`,`creationDate`,`modifyBy`,`modifyDate`,`userId`) VALUES (1,'王丽','北京市东城区东交民巷44号','100010','13678789999',1,'2016-04-13 00:00:00',NULL,NULL,1),(2,'张红丽','北京市海淀区丹棱街3号','100000','18567672312',1,'2016-04-13 00:00:00',NULL,NULL,1),(3,'任志强','北京市东城区美术馆后街23号','100021','13387906742',1,'2016-04-13 00:00:00',NULL,NULL,1),(4,'曹颖','北京市朝阳区朝阳门南大街14号','100053','13568902323',1,'2016-04-13 00:00:00',NULL,NULL,2),(5,'李慧','北京市西城区三里河路南三巷3号','100032','18032356666',1,'2016-04-13 00:00:00',NULL,NULL,3),(6,'王国强','北京市顺义区高丽营镇金马工业区18号','100061','13787882222',1,'2016-04-13 00:00:00',NULL,NULL,3);DROP TABLE IF EXISTS `smbms_bill`;CREATE TABLE `smbms_bill` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',`billCode` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '账单编码',`productName` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品名称',`productDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品描述',`productUnit` VARCHAR(10) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品单位',`productCount` DECIMAL(20,2) DEFAULT NULL COMMENT '商品数量',`totalPrice` DECIMAL(20,2) DEFAULT NULL COMMENT '商品总额',`isPayment` INT(10) DEFAULT NULL COMMENT '是否支付(1:未支付 2:已支付)',`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)',`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)',`modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间',`providerId` BIGINT(20) DEFAULT NULL COMMENT '供应商ID',PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;INSERT  INTO `smbms_bill`(`id`,`billCode`,`productName`,`productDesc`,`productUnit`,`productCount`,`totalPrice`,`isPayment`,`createdBy`,`creationDate`,`modifyBy`,`modifyDate`,`providerId`) VALUES (2,'BILL2016_002','香皂、肥皂、药皂','日用品-皂类','块','1000.00','10000.00',2,1,'2016-03-23 04:20:40',NULL,NULL,13),(3,'BILL2016_003','大豆油','食品-食用油','斤','300.00','5890.00',2,1,'2014-12-14 13:02:03',NULL,NULL,6),(4,'BILL2016_004','橄榄油','食品-进口食用油','斤','200.00','9800.00',2,1,'2013-10-10 03:12:13',NULL,NULL,7),(5,'BILL2016_005','洗洁精','日用品-厨房清洁','瓶','500.00','7000.00',2,1,'2014-12-14 13:02:03',NULL,NULL,9),(6,'BILL2016_006','美国大杏仁','食品-坚果','袋','300.00','5000.00',2,1,'2016-04-14 06:08:09',NULL,NULL,4),(7,'BILL2016_007','沐浴液、精油','日用品-沐浴类','瓶','500.00','23000.00',1,1,'2016-07-22 10:10:22',NULL,NULL,14),(8,'BILL2016_008','不锈钢盘碗','日用品-厨房用具','个','600.00','6000.00',2,1,'2016-04-14 05:12:13',NULL,NULL,14),(9,'BILL2016_009','塑料杯','日用品-杯子','个','350.00','1750.00',2,1,'2016-02-04 11:40:20',NULL,NULL,14),(10,'BILL2016_010','豆瓣酱','食品-调料','瓶','200.00','2000.00',2,1,'2013-10-29 05:07:03',NULL,NULL,8),(11,'BILL2016_011','海之蓝','饮料-国酒','瓶','50.00','10000.00',1,1,'2016-04-14 16:16:00',NULL,NULL,1),(12,'BILL2016_012','芝华士','饮料-洋酒','瓶','20.00','6000.00',1,1,'2016-09-09 17:00:00',NULL,NULL,1),(13,'BILL2016_013','长城红葡萄酒','饮料-红酒','瓶','60.00','800.00',2,1,'2016-11-14 15:23:00',NULL,NULL,1),(14,'BILL2016_014','泰国香米','食品-大米','斤','400.00','5000.00',2,1,'2016-10-09 15:20:00',NULL,NULL,3),(15,'BILL2016_015','东北大米','食品-大米','斤','600.00','4000.00',2,1,'2016-11-14 14:00:00',NULL,NULL,3),(16,'BILL2016_016','可口可乐','饮料','瓶','2000.00','6000.00',2,1,'2012-03-27 13:03:01',NULL,NULL,2),(17,'BILL2016_017','脉动','饮料','瓶','1500.00','4500.00',2,1,'2016-05-10 12:00:00',NULL,NULL,2),(18,'BILL2016_018','哇哈哈','饮料','瓶','2000.00','4000.00',2,1,'2015-11-24 15:12:03',NULL,NULL,2);DROP TABLE IF EXISTS `smbms_provider`;CREATE TABLE `smbms_provider` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',`proCode` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商编码',`proName` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商名称',`proDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商详细描述',`proContact` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商联系人',`proPhone` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系电话',`proAddress` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '地址',`proFax` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '传真',`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)',`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',`modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间',`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)',PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;INSERT  INTO `smbms_provider`(`id`,`proCode`,`proName`,`proDesc`,`proContact`,`proPhone`,`proAddress`,`proFax`,`createdBy`,`creationDate`,`modifyDate`,`modifyBy`) VALUES (1,'BJ_GYS001','北京三木堂商贸有限公司','长期合作伙伴,主营产品:茅台、五粮液、郎酒、酒鬼酒、泸州老窖、赖茅酒、法国红酒等','张国强','13566667777','北京市丰台区育芳园北路','010-58858787',1,'2013-03-21 16:52:07',NULL,NULL),(2,'HB_GYS001','石家庄帅益食品贸易有限公司','长期合作伙伴,主营产品:饮料、水饮料、植物蛋白饮料、休闲食品、果汁饮料、功能饮料等','王军','13309094212','河北省石家庄新华区','0311-67738876',1,'2016-04-13 04:20:40',NULL,NULL),(3,'GZ_GYS001','深圳市泰香米业有限公司','初次合作伙伴,主营产品:良记金轮米,龙轮香米等','郑程瀚','13402013312','广东省深圳市福田区深南大道6006华丰大厦','0755-67776212',1,'2014-03-21 16:56:07',NULL,NULL),(4,'GZ_GYS002','深圳市喜来客商贸有限公司','长期合作伙伴,主营产品:坚果炒货.果脯蜜饯.天然花茶.营养豆豆.特色美食.进口食品.海味零食.肉脯肉','林妮','18599897645','广东省深圳市福龙工业区B2栋3楼西','0755-67772341',1,'2013-03-22 16:52:07',NULL,NULL),(5,'JS_GYS001','兴化佳美调味品厂','长期合作伙伴,主营产品:天然香辛料、鸡精、复合调味料','徐国洋','13754444221','江苏省兴化市林湖工业区','0523-21299098',1,'2015-11-22 16:52:07',NULL,NULL),(6,'BJ_GYS002','北京纳福尔食用油有限公司','长期合作伙伴,主营产品:山茶油、大豆油、花生油、橄榄油等','马莺','13422235678','北京市朝阳区珠江帝景1号楼','010-588634233',1,'2012-03-21 17:52:07',NULL,NULL),(7,'BJ_GYS003','北京国粮食用油有限公司','初次合作伙伴,主营产品:花生油、大豆油、小磨油等','王驰','13344441135','北京大兴青云店开发区','010-588134111',1,'2016-04-13 00:00:00',NULL,NULL),(8,'ZJ_GYS001','慈溪市广和绿色食品厂','长期合作伙伴,主营产品:豆瓣酱、黄豆酱、甜面酱,辣椒,大蒜等农产品','薛圣丹','18099953223','浙江省宁波市慈溪周巷小安村','0574-34449090',1,'2013-11-21 06:02:07',NULL,NULL),(9,'GX_GYS001','优百商贸有限公司','长期合作伙伴,主营产品:日化产品','李立国','13323566543','广西南宁市秀厢大道42-1号','0771-98861134',1,'2013-03-21 19:52:07',NULL,NULL),(10,'JS_GYS002','南京火头军信息技术有限公司','长期合作伙伴,主营产品:不锈钢厨具等','陈女士','13098992113','江苏省南京市浦口区浦口大道1号新城总部大厦A座903室','025-86223345',1,'2013-03-25 16:52:07',NULL,NULL),(11,'GZ_GYS003','广州市白云区美星五金制品厂','长期合作伙伴,主营产品:海绵床垫、坐垫、靠垫、海绵枕头、头枕等','梁天','13562276775','广州市白云区钟落潭镇福龙路20号','020-85542231',1,'2016-12-21 06:12:17',NULL,NULL),(12,'BJ_GYS004','北京隆盛日化科技','长期合作伙伴,主营产品:日化环保清洗剂,家居洗涤专卖、洗涤用品网、墙体除霉剂、墙面霉菌清除剂等','孙欣','13689865678','北京市大兴区旧宫','010-35576786',1,'2014-11-21 12:51:11',NULL,NULL),(13,'SD_GYS001','山东豪克华光联合发展有限公司','长期合作伙伴,主营产品:洗衣皂、洗衣粉、洗衣液、洗洁精、消杀类、香皂等','吴洪转','13245468787','山东济阳济北工业区仁和街21号','0531-53362445',1,'2015-01-28 10:52:07',NULL,NULL),(14,'JS_GYS003','无锡喜源坤商行','长期合作伙伴,主营产品:日化品批销','周一清','18567674532','江苏无锡盛岸西路','0510-32274422',1,'2016-04-23 11:11:11',NULL,NULL),(15,'ZJ_GYS002','乐摆日用品厂','长期合作伙伴,主营产品:各种中、高档塑料杯,塑料乐扣水杯(密封杯)、保鲜杯(保鲜盒)、广告杯、礼品杯','王世杰','13212331567','浙江省金华市义乌市义东路','0579-34452321',1,'2016-08-22 10:01:30',NULL,NULL);DROP TABLE IF EXISTS `smbms_role`;CREATE TABLE `smbms_role` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',`roleCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色编码',`roleName` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色名称',`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者',`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '修改者',`modifyDate` DATETIME DEFAULT NULL COMMENT '修改时间',PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;INSERT  INTO `smbms_role`(`id`,`roleCode`,`roleName`,`createdBy`,`creationDate`,`modifyBy`,`modifyDate`) VALUES (1,'SMBMS_ADMIN','系统管理员',1,'2016-04-13 00:00:00',NULL,NULL),(2,'SMBMS_MANAGER','经理',1,'2016-04-13 00:00:00',NULL,NULL),(3,'SMBMS_EMPLOYEE','普通员工',1,'2016-04-13 00:00:00',NULL,NULL);DROP TABLE IF EXISTS `smbms_user`;CREATE TABLE `smbms_user` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',`userCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户编码',`userName` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户名称',`userPassword` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户密码',`gender` INT(10) DEFAULT NULL COMMENT '性别(1:女、 2:男)',`birthday` DATE DEFAULT NULL COMMENT '出生日期',`phone` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '手机',`address` VARCHAR(30) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '地址',`userRole` BIGINT(20) DEFAULT NULL COMMENT '用户角色(取自角色表-角色id)',`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)',`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)',`modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;INSERT  INTO `smbms_user`(`id`,`userCode`,`userName`,`userPassword`,`gender`,`birthday`,`phone`,`address`,`userRole`,`createdBy`,`creationDate`,`modifyBy`,`modifyDate`) VALUES (1,'admin','系统管理员','1234567',1,'1983-10-10','13688889999','北京市海淀区成府路207号',1,1,'2013-03-21 16:52:07',NULL,NULL),(2,'liming','李明','0000000',2,'1983-12-10','13688884457','北京市东城区前门东大街9号',2,1,'2014-12-31 19:52:09',NULL,NULL),(5,'hanlubiao','韩路彪','0000000',2,'1984-06-05','18567542321','北京市朝阳区北辰中心12号',2,1,'2014-12-31 19:52:09',NULL,NULL),(6,'zhanghua','张华','0000000',1,'1983-06-15','13544561111','北京市海淀区学院路61号',3,1,'2013-02-11 10:51:17',NULL,NULL),(7,'wangyang','王洋','0000000',2,'1982-12-31','13444561124','北京市海淀区西二旗辉煌国际16层',3,1,'2014-06-11 19:09:07',NULL,NULL),(8,'zhaoyan','赵燕','0000000',1,'1986-03-07','18098764545','北京市海淀区回龙观小区10号楼',3,1,'2016-04-21 13:54:07',NULL,NULL),(10,'sunlei','孙磊','0000000',2,'1981-01-04','13387676765','北京市朝阳区管庄新月小区12楼',3,1,'2015-05-06 10:52:07',NULL,NULL),(11,'sunxing','孙兴','0000000',2,'1978-03-12','13367890900','北京市朝阳区建国门南大街10号',3,1,'2016-11-09 16:51:17',NULL,NULL),(12,'zhangchen','张晨','0000000',1,'1986-03-28','18098765434','朝阳区管庄路口北柏林爱乐三期13号楼',3,1,'2016-08-09 05:52:37',1,'2016-04-14 14:15:36'),(13,'dengchao','邓超','0000000',2,'1981-11-04','13689674534','北京市海淀区北航家属院10号楼',3,1,'2016-07-11 08:02:47',NULL,NULL),(14,'yangguo','杨过','0000000',2,'1980-01-01','13388886623','北京市朝阳区北苑家园茉莉园20号楼',3,1,'2015-02-01 03:52:07',NULL,NULL),(15,'zhaomin','赵敏','0000000',1,'1987-12-04','18099897657','北京市昌平区天通苑3区12号楼',2,1,'2015-09-12 12:02:12',NULL,NULL);

pojo(实体类编写)

ORM映射 表-类映射

User类

import java.util.Date;
public class User {private Integer id; //id private String userCode; //用户编码private String userName; //用户名称private String userPassword; //用户密码private Integer gender;  //性别private Date birthday;  //出生日期private String phone;   //电话private String address; //地址private Integer userRole;    //用户角色private Integer createdBy;   //创建者private Date creationDate; //创建时间private Integer modifyBy;     //更新者private Date modifyDate;   //更新时间private Integer age;//年龄private String userRoleName;    //用户角色名称public String getUserRoleName() {return userRoleName;}public void setUserRoleName(String userRoleName) {this.userRoleName = userRoleName;}public Integer getAge() {Date date = new Date();Integer age = date.getYear()-birthday.getYear();return age;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUserCode() {return userCode;}public void setUserCode(String userCode) {this.userCode = userCode;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getUserPassword() {return userPassword;}public void setUserPassword(String userPassword) {this.userPassword = userPassword;}public Integer getGender() {return gender;}public void setGender(Integer gender) {this.gender = gender;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public Integer getUserRole() {return userRole;}public void setUserRole(Integer userRole) {this.userRole = userRole;}public Integer getCreatedBy() {return createdBy;}public void setCreatedBy(Integer createdBy) {this.createdBy = createdBy;}public Date getCreationDate() {return creationDate;}public void setCreationDate(Date creationDate) {this.creationDate = creationDate;}public Integer getModifyBy() {return modifyBy;}public void setModifyBy(Integer modifyBy) {this.modifyBy = modifyBy;}public Date getModifyDate() {return modifyDate;}public void setModifyDate(Date modifyDate) {this.modifyDate = modifyDate;}}

Bill类

import java.math.BigDecimal;
import java.util.Date;
public class Bill {private Integer id;   //id private String billCode; //账单编码 private String productName; //商品名称 private String productDesc; //商品描述 private String productUnit; //商品单位private BigDecimal productCount; //商品数量 private BigDecimal totalPrice; //总金额private Integer isPayment; //是否支付 private Integer providerId; //供应商ID private Integer createdBy; //创建者private Date creationDate; //创建时间private Integer modifyBy; //更新者private Date modifyDate;//更新时间private String providerName;//供应商名称public String getProviderName() {return providerName;}public void setProviderName(String providerName) {this.providerName = providerName;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getBillCode() {return billCode;}public void setBillCode(String billCode) {this.billCode = billCode;}public String getProductName() {return productName;}public void setProductName(String productName) {this.productName = productName;}public String getProductDesc() {return productDesc;}public void setProductDesc(String productDesc) {this.productDesc = productDesc;}public String getProductUnit() {return productUnit;}public void setProductUnit(String productUnit) {this.productUnit = productUnit;}public BigDecimal getProductCount() {return productCount;}public void setProductCount(BigDecimal productCount) {this.productCount = productCount;}public BigDecimal getTotalPrice() {return totalPrice;}public void setTotalPrice(BigDecimal totalPrice) {this.totalPrice = totalPrice;}public Integer getIsPayment() {return isPayment;}public void setIsPayment(Integer isPayment) {this.isPayment = isPayment;}public Integer getProviderId() {return providerId;}public void setProviderId(Integer providerId) {this.providerId = providerId;}public Integer getCreatedBy() {return createdBy;}public void setCreatedBy(Integer createdBy) {this.createdBy = createdBy;}public Date getCreationDate() {return creationDate;}public void setCreationDate(Date creationDate) {this.creationDate = creationDate;}public Integer getModifyBy() {return modifyBy;}public void setModifyBy(Integer modifyBy) {this.modifyBy = modifyBy;}public Date getModifyDate() {return modifyDate;}public void setModifyDate(Date modifyDate) {this.modifyDate = modifyDate;}
}

Role类

import java.util.Date;
public class Role { private Integer id;   //idprivate String roleCode; //角色编码private String roleName; //角色名称private Integer createdBy; //创建者private Date creationDate; //创建时间private Integer modifyBy; //更新者private Date modifyDate;//更新时间public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getRoleCode() {return roleCode;}public void setRoleCode(String roleCode) {this.roleCode = roleCode;}public String getRoleName() {return roleName;}public void setRoleName(String roleName) {this.roleName = roleName;}public Integer getCreatedBy() {return createdBy;}public void setCreatedBy(Integer createdBy) {this.createdBy = createdBy;}public Date getCreationDate() {return creationDate;}public void setCreationDate(Date creationDate) {this.creationDate = creationDate;}public Integer getModifyBy() {return modifyBy;}public void setModifyBy(Integer modifyBy) {this.modifyBy = modifyBy;}public Date getModifyDate() {return modifyDate;}public void setModifyDate(Date modifyDate) {this.modifyDate = modifyDate;}
}

Provider类

import java.util.Date;
public class Provider {private Integer id;   //idprivate String proCode; //供应商编码private String proName; //供应商名称private String proDesc; //供应商描述private String proContact; //供应商联系人private String proPhone; //供应商电话private String proAddress; //供应商地址private String proFax; //供应商传真private Integer createdBy; //创建者private Date creationDate; //创建时间private Integer modifyBy; //更新者private Date modifyDate;//更新时间public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getProCode() {return proCode;}public void setProCode(String proCode) {this.proCode = proCode;}public String getProName() {return proName;}public void setProName(String proName) {this.proName = proName;}public String getProDesc() {return proDesc;}public void setProDesc(String proDesc) {this.proDesc = proDesc;}public String getProContact() {return proContact;}public void setProContact(String proContact) {this.proContact = proContact;}public String getProPhone() {return proPhone;}public void setProPhone(String proPhone) {this.proPhone = proPhone;}public String getProAddress() {return proAddress;}public void setProAddress(String proAddress) {this.proAddress = proAddress;}public String getProFax() {return proFax;}public void setProFax(String proFax) {this.proFax = proFax;}public Integer getCreatedBy() {return createdBy;}public void setCreatedBy(Integer createdBy) {this.createdBy = createdBy;}public Date getCreationDate() {return creationDate;}public void setCreationDate(Date creationDate) {this.creationDate = creationDate;}public Integer getModifyBy() {return modifyBy;}public void setModifyBy(Integer modifyBy) {this.modifyBy = modifyBy;}public Date getModifyDate() {return modifyDate;}public void setModifyDate(Date modifyDate) {this.modifyDate = modifyDate;}
}

编写基础公共类

数据库配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf-8
username=root
password=123456

编写数据库增删改查公共类

package com.lhc.dao;import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;public class BaseDao {private static String driver;private static String url;private static String username;private static String password;//静态代码块static {//通过类加载器 读取对应的资源InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");Properties properties = new 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);System.out.println("连接成功");} catch (Exception e) {System.out.println("连接失败");e.printStackTrace();}return connection;}//编写查询公共类public static ResultSet execute(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet, String sql, Object[] params) throws SQLException {//预编译的sql 在后面直接执行就可以了preparedStatement = connection.prepareStatement(sql);for (int i = 0; i < params.length; i++) {//因为 preparedStatement.setObject是从 1 开始的preparedStatement.setObject(i + 1, params[i]);}resultSet = preparedStatement.executeQuery();return resultSet;}//编写增删改公共类public static int execute(Connection connection, PreparedStatement preparedStatement, String sql, Object[] params) throws SQLException {preparedStatement = connection.prepareStatement(sql);for (int i = 0; i < params.length; i++) {//因为 preparedStatement.setObject是从 1 开始的preparedStatement.setObject(i + 1, params[i]);}int i = preparedStatement.executeUpdate();return i;}//释放资源public static boolean closeResource(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {boolean flag = true;if (resultSet != null) {try {resultSet.close();//GC回收resultSet = null;} catch (SQLException throwables) {throwables.printStackTrace();flag = false;}}if (preparedStatement != null) {try {preparedStatement.close();//GC回收preparedStatement = null;} catch (SQLException throwables) {throwables.printStackTrace();flag = false;}}if (connection != null) {try {connection.close();//GC回收resultSet = null;} catch (SQLException throwables) {throwables.printStackTrace();flag = false;}}return flag;}
}

编写字符编码过滤器

<?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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"><!--字符编码过滤器--><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>com.lhc.filter.CharacterEncodingFilter</filter-class></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>

导入静态资源

码云服务器里有

https://gitee.com/babobenNB/smbms?_from=gitee_search

登入功能实现

  1. 编写前端页面

  2. 设置首页

    web.xml

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

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

    package com.lhc.service;import com.lhc.pojo.User;public interface UserService {//用户登入public User login(String userCode,String password);
    }
    
  6. 业务层实现类

    package com.lhc.service;import com.lhc.dao.BaseDao;
    import com.lhc.dao.user.UserDao;
    import com.lhc.dao.user.UserDaoImpl;
    import com.lhc.pojo.User;
    import org.junit.Test;import java.sql.Connection;public class UserServiceImpl implements UserService {private UserDao userDao;public UserServiceImpl(){userDao= new UserDaoImpl();}public User login(String userCode, String password) {//业务层都会调用Dao层 所以我们要引入Dao层Connection connection=null;User user=null;try {connection= BaseDao.getConnection();System.out.println("连接成功");//通过业务层调用对应的具体的数据库操作user = userDao.getLoginUser(connection, userCode, password);} catch (Exception e) {e.printStackTrace();} finally {BaseDao.closeResource(connection,null,null);}return user;}}
  7. 编写servlet

    package com.lhc.servlet.user;import com.lhc.pojo.User;
    import com.lhc.service.UserService;
    import com.lhc.service.UserServiceImpl;
    import com.lhc.util.Constant;import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;public class LoginServlet extends HttpServlet {//servlet 控制层 调用业务层代码@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("进入LoginServlet---start...");//获取用户名和密码String userCode = req.getParameter("userCode");String userpassword = req.getParameter("userpassword");//和数据库中的密码进行对比 调用业务层UserServiceImpl userService = new UserServiceImpl();User user = userService.login(userCode, userpassword);//这里已经把登入的人给查出来了if (user!=null){//查有此人 可以登入//将用户的信息 放到Session中req.getSession().setAttribute(Constant.USER_SESSION,user);//跳转到主页resp.sendRedirect("jsp/frame.jsp");}else {//查无此人req.setAttribute("error","用户或者密码错误");req.getRequestDispatcher("login.jsp").forward(req,resp);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
    }
    
  8. 注册Servlet

    <servlet><servlet-name>LoginServlet</servlet-name><servlet-class>com.lhc.servlet.user.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping><servlet-name>LoginServlet</servlet-name><url-pattern>/login.do</url-pattern>
    </servlet-mapping>
    
  9. 测试访问 确保以上功能成功!

登入功能优化

注销功能

思路 移除session 返回登入页面

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//移除用户的Constant.USER_SESSIONreq.getSession().removeAttribute(Constant.USER_SESSION);resp.sendRedirect(req.getContextPath()+"/login.jsp");//返回登入页面  req.getContextPath()是到webapp路径下}

xml注册

<!--注销功能-->
<servlet><servlet-name>LogoutServlet</servlet-name><servlet-class>com.lhc.servlet.user.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>LogoutServlet</servlet-name><url-pattern>/jsp/logout.do</url-pattern>
</servlet-mapping>

登入拦截优化

查看session是否存在

过滤器

public void doFilter(ServletRequest req ,ServletResponse resp, FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;//过滤器 从session中获取用户User user = (User) request.getSession().getAttribute(Constant.USER_SESSION);if (user==null){//已经被移除或者注销了 或者未登入response.sendRedirect("smbms/error.jsp");}else {chain.doFilter(req,resp);}}

web.xml

<!--用户登入过滤器-->
<filter><filter-name>SysFilter</filter-name><filter-class>com.lhc.filter.SysFilter</filter-class>
</filter>
<filter-mapping><filter-name>SysFilter</filter-name><url-pattern>/jsp/*</url-pattern>
</filter-mapping>

登入 注销 拦截 完成

密码修改

  1. 导入前端页面

  2. 写项目 从底层向上写

  1. UserDao接口

    public int updatePwd(Connection connection,int id,String password) throws SQLException;
    
  2. UserDao接口实现类

    public int updatePwd(Connection connection, int id, String password) throws SQLException {PreparedStatement pstm = null;int execute = 0;if (connection != null) {String sql = "update smbms_user set userPassword=? where id=?";Object params[] = {password, id};execute = BaseDao.execute(connection, pstm, sql, params);BaseDao.closeResource(null, pstm, null);}return execute;
    }
    
  3. Userservice接口

    //根据user ID 修改密码
    public boolean updatePwd(int id, String password) throws SQLException;
    
  4. UserService实现类

    public boolean updatePwd(int id, String password) throws SQLException {Connection connection = null;boolean flag = false;connection = BaseDao.getConnection();try {//修改密码if (userDao.updatePwd(connection, id, password) > 0) {flag = true;}} catch (Exception e) {e.printStackTrace();BaseDao.closeResource(connection, null, null);}return flag;}
    
  5. Servlet层

     //修改密码public void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//从Session里拿IDObject o = req.getSession().getAttribute(Constant.USER_SESSION);boolean flag = false;String newpassword = req.getParameter("newpassword");if (o != null && !StringUtils.isEmptyOrWhitespaceOnly(newpassword)) {try {UserServiceImpl userService = new UserServiceImpl();flag = userService.updatePwd(((User) o).getId(), newpassword);} catch (SQLException throwables) {throwables.printStackTrace();}if (flag) {req.setAttribute("message", "修改密码成功,请退出 使用新密码登入");//密码修改成功 移除当前sessionreq.getSession().removeAttribute(Constant.USER_SESSION);} else {//密码修改失败req.setAttribute("message", "修改密码失败");}} else {//密码修改失败req.setAttribute("message", "修改密码有问题");}req.getRequestDispatcher("pwdmodify.jsp").forward(req, resp);}
    
  6. 记得实现服用 需要提取出方法

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getParameter("method");if (method.equals("savepwd")&&method!=null){this.update(req,resp);}
    }
    
  7. 测试成功

优化密码修改 使用Ajax

  1. 阿里巴巴的fastjson

    <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.61</version>
    </dependency>
    
  2. 后台代码

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getParameter("method");if (method.equals("savepwd") && method != null) {try {this.update(req, resp);} catch (SQLException throwables) {throwables.printStackTrace();}}else if (method.equals("pwdmodify")&&method != null){Object o = req.getSession().getAttribute(Constant.USER_SESSION);String oldpassword = req.getParameter("oldpassword");//万能的Map  结果集HashMap<String, String> resultMap = new HashMap<String,String>();if (o==null){//session失效了 或者过期resultMap.put("result","sessionerror");}else if (StringUtils.isEmptyOrWhitespaceOnly(oldpassword)){resultMap.put("result","error");}else {String userPassword = ((User) o).getUserPassword();//session中用户的密码if (oldpassword.equals(userPassword)){resultMap.put("result","true");}else {resultMap.put("result","false");}}//返回一个json文件resp.setContentType("application/json");;PrintWriter writer = resp.getWriter();//JSONArray 阿里巴巴的json工具类  转换格式/*resultMap.put("result","sessionerror")转换成json的格式{key:value}*/writer.write(JSONArray.toJSONString(resultMap));writer.flush();writer.close();}
    }
    

用户管理实现

思路

  1. 导入分页的工具类

  2. 用户列表页面导入

    userlist.jsp

1 获取用户数量

1.UserDao

public int getUserCount(String username,int userRole) throws SQLException;

2.UserDaoImpl

//根据用户名或者角色查询用户总数
public int getUserCount(String username, int userRole) throws SQLException {PreparedStatement pstm = null;ResultSet rs = null;Integer count = 0;Connection connection = BaseDao.getConnection();if (connection != null) {StringBuffer sql = new StringBuffer();sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole=r.id");ArrayList<Object> list = new ArrayList<Object>();//存放我们的数据if (!StringUtils.isNullOrEmpty(username)) {sql.append("and u.username like ?");list.add("%" + username + "%");//index:0}if (userRole > 0) {sql.append(" and u.userRole =?");list.add(userRole);//index:1}//怎么List转换为数组Object[] params = list.toArray();System.out.println("UserDaoImpl-->getUserCount:" + sql.toString());rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);if (rs.next()) {count = rs.getInt("count");//从结果集中获得数量}BaseDao.closeResource(connection, pstm, rs);}return count;}

3.UserService

//查询记录数
public int getUserCount(String username,int userRole);

4.UserServiceImpl

public int getUserCount(String username, int userRole) {int count=0;Connection connection = null;try {connection = BaseDao.getConnection();count = userDao.getUserCount(username, userRole);} catch (SQLException throwables) {throwables.printStackTrace();}return count;
}

5.Servlet

2 获取用户列表

1.UserDao

//获取用户列表
public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize)throws Exception;

2.UserDaoImpl

public List<User> getUserList(Connection connection,String userName, int userRole, int currentPageNo, int pageSize) throws Exception {// TODO Auto-generated method stubPreparedStatement pstm = null;ResultSet rs = null;List<User> userList = new ArrayList<User>();if(connection != null){StringBuffer sql = new StringBuffer();sql.append("select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole = r.id");List<Object> list = new ArrayList<Object>();if(!StringUtils.isNullOrEmpty(userName)){sql.append(" and u.userName like ?");list.add("%"+userName+"%");}if(userRole > 0){sql.append(" and u.userRole = ?");list.add(userRole);}//在数据库中 分页使用   limit startIndex,pageSize 总数//当前页 (当前页-1)*页面大小// 0,5   1  0    01234//6,5   2  6    56789//11,5  3  10sql.append(" order by creationDate DESC limit ?,?");currentPageNo = (currentPageNo-1)*pageSize;list.add(currentPageNo);list.add(pageSize);Object[] params = list.toArray();System.out.println("sql ----> " + sql.toString());rs = BaseDao.execute(connection,pstm, rs, sql.toString(), params);while(rs.next()){User _user = new User();_user.setId(rs.getInt("id"));_user.setUserCode(rs.getString("userCode"));_user.setUserName(rs.getString("userName"));_user.setGender(rs.getInt("gender"));_user.setBirthday(rs.getDate("birthday"));_user.setPhone(rs.getString("phone"));_user.setUserRole(rs.getInt("userRole"));_user.setUserRoleName(rs.getString("userRoleName"));userList.add(_user);}BaseDao.closeResource(null, pstm, rs);}return userList;
}

3.Userservice

//通过条件查询 -userList
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize);

4.UserserviceImpl

public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize) {// TODO Auto-generated method stubConnection connection = null;List<User> userList = null;System.out.println("queryUserName ---- > " + queryUserName);System.out.println("queryUserRole ---- > " + queryUserRole);System.out.println("currentPageNo ---- > " + currentPageNo);System.out.println("pageSize ---- > " + pageSize);try {connection = BaseDao.getConnection();userList = userDao.getUserList(connection, queryUserName,queryUserRole,currentPageNo,pageSize);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{BaseDao.closeResource(connection, null, null);}return userList;
}

3.获取角色操作

为了我们职责同一 可以把角色的操作单独放在一个包中 和POJO类对应

1.RoleDao

//获取角色列表
public List<Role> getRoleList(Connection connection)throws SQLException;

2.RoleDaoImpl

//获取角色列表
public List<Role> getRoleList(Connection connection) throws SQLException {PreparedStatement pstm=null;ResultSet rs=null;ArrayList<Role> roleList = new ArrayList<Role>();if (connection!=null){String sql="select * from smbms_role";Object[] params={};rs=BaseDao.execute(connection,pstm,rs,sql,params);while (rs.next()){Role role = new Role();role.setId(rs.getInt("id"));role.setRoleCode(rs.getString("rolename"));role.setRoleName(rs.getString("roleCode"));roleList.add(role);}BaseDao.closeResource(connection,pstm,rs);}return roleList;
}

3.RoleService

public List<Role> getRoleList();

4.RoleServiceImpl

//引入Dao
private RoleDao roleDao;
public RoleServiceImpl() {roleDao= new RoleDaoImpl();
}public List<Role> getRoleList() {Connection connection = null;List<Role> roleList=null;try {connection=BaseDao.getConnection();roleList= roleDao.getRoleList(connection);} catch (SQLException throwables) {throwables.printStackTrace();}finally {BaseDao.closeResource(connection,null,null);}return roleList;
}

4.用户显示的servlet

  1. 获取用户全的数据(查询)
  2. 判断请求是否需要执行 看参数的值判断
  3. 为了实现分页 需要计算出当前页面和总页面 页面大小
  4. 用户列表展示
  5. 返回前段
//query方法
public void query(HttpServletRequest req, HttpServletResponse resp){//查询用户列表//从前端获取数据;String queryUserName = req.getParameter("queryname");String temp = req.getParameter("queryUserRole");String pageIndex = req.getParameter("pageIndex");int queryUserRole = 0;//获取用户列表UserServiceImpl userService = new UserServiceImpl();List<User> userList = null;//第一次走这个请求,一定是第一页,页面大小固定的;int pageSize = 5; //可以把这个些到配置文件中,方便后期修改;int currentPageNo = 1;if (queryUserName ==null){queryUserName = "";}if (temp!=null && !temp.equals("")){queryUserRole = Integer.parseInt(temp);  //给查询赋值!0,1,2,3}if (pageIndex!=null){currentPageNo = Integer.parseInt(pageIndex);}//获取用户的总数 (分页:  上一页,下一页的情况)int totalCount = userService.getUserCount(queryUserName, queryUserRole);//总页数支持PageSupport pageSupport = new PageSupport();pageSupport.setCurrentPageNo(currentPageNo);pageSupport.setPageSize(pageSize);pageSupport.setTotalCount(totalCount);int totalPageCount = ((int)(totalCount/pageSize))+1;//控制首页和尾页//如果页面要小于1了,就显示第一页的东西if (currentPageNo<1){currentPageNo = 1;}else if (currentPageNo>totalPageCount){ //当前页面大于了最后一页;currentPageNo = totalPageCount;}//获取用户列表展示userList = userService.getUserList(queryUserName, queryUserRole, currentPageNo, pageSize);req.setAttribute("userList",userList);RoleServiceImpl roleService = new RoleServiceImpl();//用户名需要给下拉框里传值 因为前端用jstl表达式帮我们拆解这个List 所以我们传入List类型就行List<Role> roleList = roleService.getRoleList();req.setAttribute("roleList",roleList);req.setAttribute("totalCount",totalCount);req.setAttribute("currentPageNo",currentPageNo);req.setAttribute("totalPageCount",totalPageCount);req.setAttribute("queryUserName",queryUserName);req.setAttribute("queryUserRole",queryUserRole);//返回前端try {req.getRequestDispatcher("userlist.jsp").forward(req,resp);} catch (ServletException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}
}

4.Javaweb基础入门相关推荐

  1. JavaWeb基础入门到上手项目

    文章目录 1.基本概念 1.1.前言 1.2.web应用程序 1.3.静态web 1.4.动态web 2.web服务器 2.1.技术讲解 2.2.web服务器 3.Tomcat 3.1.安装Tomca ...

  2. Javaweb基础入门(IDEA版)值得学习的JavaWeb教程

    Java web Java web 1.基本概念 web开发: web,网页的意思,www.baidu.com 静态web html,css 提供给所有人看的数据始终不会发生变化! 动态web 淘宝, ...

  3. JavaWeb零基础入门之Cookie和Session

    学完之后学习JavaWeb零基础入门之Filter过滤器 视频链接:https://www.bilibili.com/video/BV1Y7411K7zz?p=1 参考手册:https://tool. ...

  4. java进阶 2018_Java Web基础入门2018版

    步骤1: Java Web基础入门 本步骤带领大家进入Java Web的世界,除了介绍JSP和Servlet以外,还会介绍开发工具IntelliJ IDEA的使用,以及什么是XML.最后会学习MVC模 ...

  5. index加载显示servlet数据_[WEB篇]-JavaWeb基础与应用-02-Servlet开发

    JavaWeb基础与应用 2.Servlet开发 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源 ...

  6. 【技术培训】招收Jeecg门徒 ---javaweb初级入门班

    招收Jeecg门徒[javaweb初级入门班] 最近准备带徒弟,带些人才出来,我带徒弟的理念是实践为王,在实践中掌握原理,积累经验. 我带徒弟的方向是JAVA WEB,掌握各种主流框架.(后期会开展j ...

  7. 黑马程序员最新版JavaWeb基础教程-学习笔记

    da@黑马程序员最新版JavaWeb基础教程-学习笔记 day06-HTML&CSS HTML HTML(HyperTest Markup Language):超文本标记语言 是一门语言,所有 ...

  8. 《黑马》——C++基础入门

    <黑马>--C++基础入门 Netfishless 2020-09-05 18:32:22 88654 收藏 3458 分类专栏: C++ 文章标签: c++ 原文链接:https://w ...

  9. Java基础入门:IDEA软件安装和软件初始化设置

    IDEA是一个专门针对Java的集成开发工具(IDE),由Java语言编写.所以,需要有JRE运行环境并配置好环境变量. 它可以极大地提升我们的开发效率.可以自动编译,检查错误.在公司中,使用的就是I ...

最新文章

  1. 【2016北京集训测试赛】river
  2. 怎样编译libdb_比特币编译(Ubuntu 16.04)
  3. sh(Spring+Spring mvc+hibernate)——IEmpDao.java
  4. Strust2初之体验
  5. java的程序编码_Java 程序编码规范(初学者要牢记)
  6. ffplay for mfc 代码备忘
  7. Linux学习之在线安装mysql
  8. 接口与interface关键字
  9. dubbo monitor mysql_dubbo-monitor监控台的部署
  10. Flexsim 视觉类 平面 plane仿真对象模块化
  11. 细说API – 认证、授权和凭证
  12. 波动速读入门训练(含黄卡、曼陀螺使用方法)提供卡片
  13. Python软件包的安装(3种方法)
  14. 【python】chardet函数用法
  15. 代码设置margintop_如何通过代码设置TextView的Margin参数?
  16. 阿里云ECS服务器修复漏洞
  17. Python安装pip时, 报错:zipimport.ZipImportError: can‘t decompress data; zlib not available 解决办法:
  18. Docker 容器退出状态码existed
  19. nodejs __dirname 与 process.cwd(); 的区别
  20. 如何让DIV标签居中显示?

热门文章

  1. 快播死了:各大门户视频网站能否得意的笑
  2. HOG+SVM行人检测python实现
  3. android解析语句,句读(tech.caicheng.judourili) - 4.3.4 - 应用 - 酷安
  4. 关于java.lang.OutOfMemoryError:java heap space错误解决方案
  5. python--使用cnmaps绘制省界地图(快速上手,简单有效)
  6. Android系统学习(37)---Android知识点及资料汇总
  7. BlackBerry 网络连接编程
  8. 视频|如何通过 LeanCloud 快速开发实时对战小游戏
  9. SEO的5大关键指标:排名+流量+会话+停留时长+跳出率
  10. SEO效果评估(7大综合指标)