【狂神说Java】JavaWeb入门到实战 https://www.bilibili.com/video/BV12J411M7Sj
可以配置端口号
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
可以配置主机名称
<Host name="www.syk.com" appBase="webapps"
unpackWARs="true" autoDeploy="true">
高难度面试题:
请你谈一谈网站是如何进行访问的?
--webapps:Tomcat服务器的web目录
-Root
-WEB-INF
-classes:java文件
-lib:web应用所依赖的jar包
-web.xml:网站配置文件
-index.jsp/index.html 默认访问的首页
-statics
-css
-style.css
-js
-img
-...
HTTP协议:面试
Maven:构建工具
Servlet 入门
常见面试题
当你的浏览器地址栏中输入地址并回车的一瞬间到页面能够展示回来,经历了什么?
我们的目的就是用来方便导入jar包的
Maven的核心思想:约定大于配置
Maven会规定好你该如何去编写我们的java代码,必须按照这个规范来
https://maven.apache.org/download.cgi
在我们的系统环境变量中
配置如下的配置:
mvn -version
测试Maven是否安装成功,保证必须配置成功
镜像:mirrors
国内建议使用阿里云的镜像
<mirror>
<id>nexus-aliyunid>
<name>nexus aliyunname>
<url>http://maven.aliyun.com/nexus/content/groups/public/url>
<mirrorOf>*,!jeecg,!jeecg-snapshotsmirrorOf>
mirror>
注:直接按照狂神java中的配置手动敲写的
建立一个本地仓库,远程仓库;
建立一个本地仓库 localRepository
<localRepository>D:\JAVA\apache-maven-3.6.3\maven-repolocalRepository>
直接下一步,选择不使用模板
这个只有在web应用下才有:
项目结构配置
选择并找到Tomcat
解决警告问题
必须要的配置为什么会有这个问题:我们潍坊潍一个网站,需要指定一个文件夹名字;
pom.xml是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.0modelVersion>
<groupId>com.sykgroupId>
<artifactId>javaweb-01-mavenartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.7maven.compiler.source>
<maven.compiler.target>1.7maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
dependencies>
<build>
<finalName>javaweb-01-mavenfinalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-pluginartifactId>
<version>3.1.0version>
plugin>
<plugin>
<artifactId>maven-resources-pluginartifactId>
<version>3.0.2version>
plugin>
<plugin>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.0version>
plugin>
<plugin>
<artifactId>maven-surefire-pluginartifactId>
<version>2.22.1version>
plugin>
<plugin>
<artifactId>maven-war-pluginartifactId>
<version>3.2.2version>
plugin>
<plugin>
<artifactId>maven-install-pluginartifactId>
<version>2.5.2version>
plugin>
<plugin>
<artifactId>maven-deploy-pluginartifactId>
<version>2.8.2version>
plugin>
plugins>
pluginManagement>
build>
project>
maven由于他的约定大于配置,我们之后可能遇到我们写的配置文件,无法导出或者生效的问题,
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
Maven 3.6.2
Tomcat闪退
IDEA中每次都要发重复配置Maven
在IDEA中的全局默认配置中去配置
Maven项目中Tomcat无法配置
maven默认web项目中的web.xml版本问题
替换为webapp4.0版本和tomcat一致
<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>
maven仓库的使用
地址:https://mvnrepository.com/
配置
<servlet>
<servlet-name>helloServletservlet-name>
<servlet-class>com.syk.servlet.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloServletservlet-name>
<url-pattern>/sykurl-pattern>
servlet-mapping>
把实现了Servlet类的Java程序叫做,Servlet
Servlet接口Sun公司有两个默认的实现类:HttpServlet、GenericServlet
构建一个Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立Moudle,这个空的工程就是Maven的主工程;
关于Maven父子工程的理解:
父项目中会有
<modules>
<module>servlet-01module>
modules>
子项目会有
<parent>
<artifactId>javaweb-02-maven01artifactId>
<groupId>com.sykgroupId>
<version>1.0-SNAPSHOTversion>
parent>
父项目中的Java子项目可以直接使用
类似于 子类继承父类
Maven环境优化
编写一个Servlet程序
编写一个普通类
实现Servlet接口,这里直接继承HttpServlet类
package com.syk.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 {
PrintWriter writer = resp.getWriter();
writer.print("Hello Servlet");// 响应流
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
编写Servlet的映射
为什么需要映射;我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器。所以我们需要在服务器中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径;
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>com.syk.servlet.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
配置Tomcat
注意:配置项目的发布路径就可以了
启动测试
遇到的问题
解决方法:
原因:
因为maven依赖中配置的jar包只存在在项目中,并不存在在tomcat中,所以运行时在tomcat中找不到相应的jar包,故报错。
所以需要将jar包引用到tomcat中
扩展 intellij idea module设置 dependencies的export
export 会改变当前module的依赖架包的共享范围:
例如有module A 配置依赖了jdbc.jar ,module B 又依赖 module A,但是如果你不在module A里的dependencies 里面把 JDBC。jar
前面的 export 勾上,module B是无法用到 JDBC的内容的,编译无法通过。
前面所说的都是通过IDE配置的 依赖,但是 如果整个module之间的依赖都是通过maven 管理的,那就没有这么多事情,默认就是scope 全局共享,
现在用maven gradle的越来越多,可能这些ide 配置会再以后的版本中删除都有可能
原为链接: https://blog.csdn.net/langzi7758521/java/article/details/51804086
Servlet是由Web服务器调用,Web服务器在收到浏览器请求址后,会:
一个Servlet可以指定一个映射路径
一个Servlet可以指定多个映射路径
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello2url-pattern>
servlet-mapping>
一个Servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
指定一些后缀或者前缀等等。
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
优先级问题
制定了固有的映射路径优先级最高,如果找不到才会走默认的处理请求(即通配符处理)
web容器在启动的时候,它会为每个web程序都创建一个相应的ServletContext对象,它代表了当前的web应用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TVBlfkXB-1589261528401)(JavaWeb.assets/image-20200505100002467.png)]
我在这个Servlet中保存的数据,可以在另外一个Servlet中拿到
package com.syk.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 ServletSet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String value="2020-05-05测试Servlet";
context.setAttribute("key",value);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.syk.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 ServletGet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String value = (String) context.getAttribute("key");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.getWriter().print("key的值为:"+value);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>testsetservlet-name>
<servlet-class>com.syk.servlet.ServletSetservlet-class>
servlet>
<servlet-mapping>
<servlet-name>testsetservlet-name>
<url-pattern>/setkeyurl-pattern>
servlet-mapping>
<servlet>
<servlet-name>testgetservlet-name>
<servlet-class>com.syk.servlet.ServletGetservlet-class>
servlet>
<servlet-mapping>
<servlet-name>testgetservlet-name>
<url-pattern>/getvalurl-pattern>
servlet-mapping>
在 “http://localhost:8080/s2/getval” 中可以取到 在 "http://localhost:8080/s2/setkey"中的值。
但是有个问题,就是切换了不同的浏览器之后,依然可以取到在其他浏览器中输入的值。?这个是Tomcat服务器为每一个请求IP配置了同一个ServletContext,还是Tomcat为一个网站全局只配置了一个ServletContext??
以下测试 session
package com.syk.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionSet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
String value="2020-05-05测试Session";
session.setAttribute("key",value);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
package com.syk.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 javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionGet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
String value = (String) session.getAttribute("key");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.getWriter().print("key的值为:"+value);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
<servlet>
<servlet-name>sessionsetservlet-name>
<servlet-class>com.syk.servlet.SessionSetservlet-class>
servlet>
<servlet-mapping>
<servlet-name>sessionsetservlet-name>
<url-pattern>/setskurl-pattern>
servlet-mapping>
<servlet>
<servlet-name>sessiongetservlet-name>
<servlet-class>com.syk.servlet.SessionGetservlet-class>
servlet>
<servlet-mapping>
<servlet-name>sessiongetservlet-name>
<url-pattern>/getsvurl-pattern>
servlet-mapping>
session结果:
tomcat服务器会为每一个浏览器请求配置同一个 session,会为不同的浏览器请求配置不同的session,因此可以将每个登陆网站的用户的数据添加到session会话中,以此来保证数据响应的正确。也可以将所有的所有的统计信息,比如当前在线用户数 等信息存入 ServletContext中。ServletContext类似于类中的类变量。
<context-param>
<param-name>urlparam-name>
<param-value>jdbc:mysql//localhost:3306/mybatisparam-value>
context-param>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String initParameter = context.getInitParameter("url");
resp.getWriter().print(initParameter);
}
ServletContext context = this.getServletContext();
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/sd05");// “/”代表当前web项目下
System.out.println("进入ServletDemo06-doGet");
requestDispatcher.forward(req,resp);
重定向与请求转发的区别
Properties 【属性】[import java.util.Properties;]
发现:都被打包到了同一个路径下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H3xKg9d1-1589261528403)(JavaWeb.assets/image-20200505145203903.png)]
都在WEB-INF下的classes路径下,我们俗称这个路径为classpath;
思路:需要一个文件流去读取新建的properties文件
[db.properties]
username=root
password=123456789
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(is);
String name = properties.getProperty("username");
String pwd = properties.getProperty("password");
resp.getWriter().print(name+":"+pwd);
}
测试结果:
root:123456789
总结:这个Properties类好像就是专门为了从流中读取这种键值对形式的值写的类下面是该类的详细使用说明
https://www.iteye.com/blog/gimgen1026-152023
向浏览器输出消息
下载文件
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 下载文件
/*
1、找到文件路径
2、创建文件流FileInputStream
3、将流存入ResponseOutputStream中输出到前端
*/
ServletContext context = this.getServletContext();
String path = context.getRealPath("WEB-INF/classes/测试.png");
FileInputStream inputStream = new FileInputStream(path);
String filename=path.substring(path.lastIndexOf('\\')+1);
//resp.setHeader("Content-Disposition","attachment;filename="+filename);
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8"));
ServletOutputStream outputStream = resp.getOutputStream();
int len=0;
byte[] buffer=new byte[1024];
while ((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
使用BufferedImage 类、ImageIO去实现一个图片验证码
疑问:StringBuffer与StringBuilder
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
BufferedImage bImg = new BufferedImage(100, 40, BufferedImage.TYPE_INT_RGB);
// Graphics2D graphics = bImg.getGraphics();
Graphics2D g = (Graphics2D) bImg.getGraphics();
// 画背景
g.setColor(Color.blue);
g.fillRect(0,0,100,40);
// 画数字
g.setColor(Color.white);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(createNum(),0,20);
// 画两条线.用于干扰
g.setColor(Color.white);
g.drawLine(getRandomInt(0,10),getRandomInt(5,35),getRandomInt(90,200),getRandomInt(5,35));
g.setColor(Color.yellow);
g.drawLine(getRandomInt(0,10),getRandomInt(5,35),getRandomInt(90,200),getRandomInt(5,35));
resp.setHeader("refresh","3"); // 自动刷新
resp.setHeader("content-type","image/jpeg");// 配置内容
resp.setHeader("Expires","-1");// 不缓存
resp.setHeader("Pragma","no-cache");// 不缓存
resp.setHeader("Cache-Control","no-cache");// 不缓存
ImageIO.write(bImg,"jpg",resp.getOutputStream());
}
/**
* 获取7位数字的验证码
* @return
*/
private String createNum() {
Random random = new Random();
String num = random.nextInt(9999999)+"";
StringBuffer buffer = new StringBuffer();
for(int i=0;i<7-num.length();i++){
buffer.append("0");
}
return buffer.toString()+num;
}
private int getRandomInt(int bound1,int bound2){
Random random = new Random();
return random.nextInt(bound2-bound1)+bound1;
}
支持和StringBuilder所有相同的操作,不同的是StringBuffer是线程安全的,在声明的方法中使用synchronized关键字进行修饰,因此单线程中一般要比StringBuilder效率低
resp.sendRedirect("/s2/img01");// 需要加上项目路径
// resp.setStatus(302);
// resp.setHeader("Location","/s2/img01");
两者完全等价
面试题:请你聊聊重定向和转发的区别?
相同点
不同点
<%--${pageContext.request.contextPath}代表当前的项目--%>
<%--${pageContext.servletContext.contextPath} 实测,路径等价--%>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String pwd = req.getParameter("password");
System.out.println(username+":"+pwd);
resp.sendRedirect("/s2/Success.jsp");
}
if (session.isNew()) {
resp.getWriter().write("新创建的会话,Session:" + id);
} else {
resp.getWriter().write("已经存在的会话,Session:" + id);
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding(“utf-8”);
resp.setContentType(“text/html”);
HttpSession session = req.getSession();
String id1 = session.getId();
Person p1=(Person)session.getAttribute("user");
resp.getWriter().write("旧的Session,Session:" + id1);
resp.getWriter().write("person:" + p1.toString());
session.invalidate();
// 第二次
HttpSession session2 = req.getSession();
String id2 = session2.getId();
Person p2=(Person)session2.getAttribute("user");
resp.getWriter().write("注销后的Session,Session:" + id2);
resp.getWriter().write("注销后的person:" + p2.toString());
}
**会话自动过期:web.xml配置**
~~~xml
15
Cookie原理
Session原理
ServletContext和applicationContext都是获取作用域,此处可以存储一些共有的信息
Java Server Pages
本机jsp编译后的地址
C:\Users\Sun\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_javaweb-02-maven01\work\Catalina\localhost\jstl\org\apache\jsp
任何语言都有自己的语法。JSP作为java技术的一种应用,它拥有自己扩充的语法(了解、知道即可!),Java所有语法都支持
JSP表达式
作用:用来将程序的输出、输出到客户端
<%= 变量或者表达式 %>
<%= new java.util.Date() %>
JSP脚本片段
<%
String username = request.getParameter("name");
String userpwd = request.getParameter("pwd");
if (username!=null&&userpwd!=null){
if ("admin".equals(username)&&"123456".equals(userpwd)){
out.print("管理员登陆成功");
out.print("当前输入 ->"+username+":"+userpwd);
}else {
out.print("账号或者密码不对");
out.print("当前输入2 ->"+username+":"+userpwd);
}
}
%>
JSP声明
<%! public void kuang(){System.out.println("123");} %>
jsp声明:会被编译到 JSP 生成 java 的类中!其它的,就会被生成到 _jspService 方法中!
JSP的注释不会在客户端显示,html的注释则会在客户端显示
<%@ page args...%>
<%@ include file="footer.jsp"%> // 会将两个网页正真的从源码程度上 “和二为一”
jsp标签
<jsp:include page="/footer.jsp"> // 拼接页面,本质还是两个页面
final javax.servlet.http.HttpServletRequest request,
final javax.servlet.http.HttpServletResponse response
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
四大作用域
pageContext.setAttribute("name1", "1号"); // 保存的数据只在一个页面中有效
request.setAttribute("name2", "2号"); // 保存的数据只在一次请求中有效,使用转发会携带该数据
session.setAttribute("name3", "3号");// 保存的数据只在一次会话中有效
application.setAttribute("name4", "4号");// 保存的数据在服务器中有效,从打开服务器到关闭服务器
<dependencies>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstl-apiartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
dependencies>
EL表达式: ${}
实体类
JavaBean有特定的写法:
必须有一个无参构造
属性必须私有化
必须有对应的get/set方法;
一般用来和数据库的字段做映射 ORM;
ORM:对象关系映射
people表
id | name | age | address |
---|---|---|---|
1 | 张三1号 | 3 | 西安国际大酒店 |
2 | 张三2号 | 18 | 西安国际大酒店 |
3 | 张三3号 | 100 | 西安国际大酒店 |
class People{
private int id;
private String name;
private String age;
private String address
}
class A{
new People(1,"张三1号",3,"西安");
new People(1,"张三1号",3,"西安");
new People(1,"张三1号",3,"西安");
}
建议存放实体类的包名: pojo,entity,dto,vo
新建数据库
jsp标签中使用 标签
什么是MVC: Model view Controller 模型、视图、控制器
用户直接访问控制层,控制层就可以直接操作数据库:
servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的
程序员调用
|
JDBC
|
MySql Oracle SqlServer ....
Model
View
Controller
接收用户的请求:(req、请求参数、Session…)
交给业务层处理对应的代码
控制视图的跳转
登陆-->接收用户的登陆请求--->处理用户的请求(获取用户登陆的参数,username,password)--->交给业务层处理登陆业务(判断用户名、密码是否正确 事务)---->Dao层查询用户名和密码是否正确---->查数据库
统一过滤乱码等问题
package com.syk.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharaterFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化过滤器CharaterFilter");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("进入CharaterFilter doFilter");
// 过滤乱码等情况
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=UTF-8");
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() {
System.out.println("销毁过滤器CharaterFilter");
}
}
<filter>
<filter-name>CharaterFilterfilter-name>
<filter-class>com.syk.filter.CharaterFilterfilter-class>
filter>
<filter-mapping>
<filter-name>CharaterFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
jdbc驱动
需要jar包支持:
视眼环境搭配
导入数据库依赖
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
dependencies>
IDEA中连接数据库
JDBC固定步骤
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 、PreparedStatement :CRUD Statement:普通的sql;PreparedStatement:预编译,安全的sql
Statement statement = connection.createStatement();
// PreparedStatement
// 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("birthday:"+rs.getObject("birthday"));
System.out.println("email:"+rs.getObject("email"));
}
// 6、关闭连接,释放资源(一定要做) 先开后关
rs.close();
statement.close();
connection.close();
}
预编译SQL
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 使用安全的预编译的sql
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password="123456";
Connection connection = DriverManager.getConnection(url, username, password);
String sql=" insert into users(id, name, password, birthday, email) VALUE (?,?,?,?,?) ";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,5);
preparedStatement.setString(2,"狂神说Java");
preparedStatement.setString(3,"12345678");
preparedStatement.setDate(4,new Date(new java.util.Date().getTime()));
preparedStatement.setString(5,"[email protected]");
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("数据插入成功");
}
preparedStatement.close();
connection.close();
}
事物
要么都成功,要么都失败!
ACID原则:保证数据的安全
开启事物
事物提交 commit()
事物回滚 rollback()
关闭事物
转账:
A:1000
B:1000
A(900) --100--> B(1100)
Junit 单元测试
依赖
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
简单使用
@Test 注解只在方法上有效,只要加了这个注解的方法,就可以直接运行
@Test
public void ss(){
System.out.println("123");
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywK1jjr1-1589261528420)(JavaWeb.assets/image-20200509200130044.png)]
失败的时候是红色:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N87b0IoH-1589261528420)(JavaWeb.assets/image-20200509200156734.png)]
搭建一个环境:
事物
start transaction ;
commit ;
rollback ;
// 通知数据库开启事物,false开启
connection.setAutoCommit(false);
// 提交事务
connection.commit();
// 事物回滚
connection.rollback();
说明: 超市订单管理系统,,使用jsp+servlet项目,新手学习的例子,简单好用
(Supermarket order management system, the use of jsp+servlet project, novice learning examples, simple and easy to use)
架构
数据库
项目如何搭建?
考虑使用bushiyongmaven?依赖,jar包
搭建一个maven web项目
配置Tomcat
测试项目是否能够运行起来
导入项目中会遇到的jar包
jsp,servlet,mysql驱动,jstl,stand
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>jsp-apiartifactId>
<version>2.2version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstl-apiartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
dependencies>
创建项目包结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y6vyoDbM-1589261528423)(JavaWeb.assets/image-20200509214752272.png)]
编写实体类
ORM映射:表-实体类
编写基础公共类
数据库配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf-8
username=root
pawword=123456
编写数据库的公共类
package com.syk.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 {
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 {
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject((i+1),params[i]);
}
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++) {
preparedStatement.setObject((i+1),params[i]);
}
int updateRows = preparedStatement.executeUpdate();
return updateRows;
}
// 释放资源
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();
connection=null;
// gc回收
} catch (SQLException throwables) {
throwables.printStackTrace();
flag=false;
}
}
return flag;
}
}
编写字符编码过滤器
导入静态资源
编写前端页面
设置欢迎页
<welcome-file-list>
<welcome-file>login.jspwelcome-file>
welcome-file-list>
编写dao层登陆的接口
public interface UserDao {
public User getLoginUser(Connection connection, String userCode) throws SQLException;
}
编写dao的实现类
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};
rs = BaseDao.execute(connection, pstm, rs, sql, params);
if (rs.next()) {
user = new User();
user.setId(rs.getInt("id"));
user.setUserCode(rs.getString("userCode"));
user.setUserName(rs.getString("userName"));
user.setUserPassword(rs.getString("userPassword"));
user.setGender(rs.getInt("gender"));
user.setBirthday(rs.getDate("birthday"));
user.setPhone(rs.getString("phone"));
user.setAddress(rs.getString("address"));
user.setUserRole(rs.getInt("userRole"));
user.setCreatedBy(rs.getInt("createdBy"));
user.setCreationDate(rs.getDate("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getDate("modifyDate"));
}
BaseDao.closeResource(null,pstm,rs);
}
return user;
}
}
业务层接口
public interface UserService {
//用户登陆
public User login(String userCode,String password);
}
业务层实现类
// 业务层都会调用dao层,所以我们要引用Dao层
private UserDao userDao;
public UserServiceImpl(){
userDao=new UserDaoImpl();
}
public User login(String userCode, String password) {
Connection connection=null;
User user=null;
try {
connection= BaseDao.getConnection();
user=userDao.getLoginUser(connection,userCode);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.closeResource(connection,null,null);
}
return user;
}
编写servlet
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入LoginServlet");
// 调用service层
String userCode = req.getParameter("userCode");
String userPassword = req.getParameter("userPassword");
UserService service=new UserServiceImpl();
User user = service.login(userCode, userPassword);
if (user!=null){
// 登陆成功
req.getSession().setAttribute(Constants.USER_SESSION,user);
resp.sendRedirect("jsp/frame.jsp");
}else {
req.setAttribute("error","登陆失败了,小可爱 O,O");
req.getRequestDispatcher("login.jsp").forward(req,resp);// 转发
}
}
注册Servlet
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.syk.servlet.user.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
测试能够访问
注销功能:
思路:移除Session,返回登陆页
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 移除session
req.getSession().removeAttribute(Constants.USER_SESSION);
resp.sendRedirect(this.getServletContext().getContextPath()+"/login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
注册xml
<servlet>
<servlet-name>LogoutServletservlet-name>
<servlet-class>com.syk.servlet.user.LogoutServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>LogoutServletservlet-name>
<url-pattern>/jsp/logout.dourl-pattern>
servlet-mapping>
登陆拦截优化
编写过滤器,并注册
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) servletRequest;
HttpServletResponse response= (HttpServletResponse) servletResponse;
User user = (User)request.getSession().getAttribute(Constants.USER_SESSION);
if (user==null){
response.sendRedirect(request.getServletContext().getContextPath()+"/error.jsp");
}else{
filterChain.doFilter(servletRequest,servletResponse);
}
}
public void destroy() {
}
}
**尚未收录**
实现代码:
**尚未收录**