问题思考:
当你的浏览器中的地址栏输入地址并回车的一瞬间 页面能够展现出来,经历了什么
重定向和转发的区别
相同点:页面都会跳转
不同点:转发url不会变化 重定向url会变化
//重定向 状态码302
resp.sendRedirect("/response_test_war/image");
//转发
req.getRequestDispatcher("/success.jsp").forward(req,resp); (后端)
pageContext.forward("/success.jsp") (前端)
resp.setContentType("html/text;charset=utf-8");
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
在xml中设置错误跳转
<error-page>
<error-code>404error-code>
<location>/error/404.jsplocation>
error-page>
<error-page>
<error-code>500error-code>
<location>/error/500.jsplocation>
error-page>
发布一个web网站 (结构)
--webapps:tomcat服务器的web目录
-ROOT
-jieStudy:网站的目录名
-WEB-INF
--classes:java程序
-lib:依赖的jar包
-web.xml 配置文件
-index.html 默认的首页
-static
-css
-js
HTTP(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上
http:80 https:443(安全的)
http请求 :客户端–发起请求(request)–服务器
淘宝
Request URL: https://www.taobao.com/ 请求地址
Request Method: GET get方法/post方法
get:能够携带的参数较少,大小有限,会在浏览器的url行显 示,不安全,但是高效
host:能够携带的参数无限制,大小无限,不会在浏览器的url 行显示,安全,但是不高效
Status Code: 200 状态码
Remote Address: 218.98.8.102:443 淘宝的地址加端口
Referrer Policy: unsafe-url
Accept: text/html 告诉浏览器,它支持的数据类型
Accept-Encoding: gzip, deflate, br 支持哪种编码格式
Accept-Language: zh-CN,zh;q=0.9 告诉语言环境
Cache-Control: no-cache 缓存控制
Connection: keep-alive 告诉浏览器 断开还 是保持连接
HOST:主机
http响应:服务器–响应–客户端
百度
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
响应状态码
动态web工程
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
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>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.46version>
dependency>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cNdDX0ju-1603807787400)(img\image-20200916203854664.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g4GSjNGn-1603807787407)(img\image-20200917210028069.png)]
package com.jie.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 helloSevlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
PrintWriter writer = resp.getWriter();//响应流
writer.print("helloword");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
编写servlet的映射:在web中注册编写的servlet 并且给予访问路径
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>com.jie.servlet.helloSevletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
<servlet>
<servlet-name>errorservlet-name>
<servlet-class>com.jie.servlet.errorServeltservlet-class>
servlet>
<servlet-mapping>
<servlet-name>errorservlet-name>
<url-pattern>/hello/*url-pattern>
servlet-mapping>
mapping为路径映射
单个servlet可以指定多个映射
指定error映射
<servlet>
<servlet-name>errorservlet-name>
<servlet-class>com.jie.servlet.errorServeltservlet-class>
servlet>
<servlet-mapping>
<servlet-name>errorservlet-name>
<url-pattern>/hello/*url-pattern>
servlet-mapping>
可以使用通配符*
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello1url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello/*url-pattern>
servlet-mapping>
名字相同 class指向java文件 pattern申明目录
1.数据共享
servletcontext可以实现数据共享 并且全局只有一个ServletContext对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fYv73Fqa-1603807787409)(img\image-20200919161200967.png)]
this.getInitParameter(); 初始化参数
this.getServletConfig(); Servlet配置
this.getServletContext(); Servlet上下午
在一个servlet中添加数据
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("hello");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
// this.getInitParameter(); 初始化参数
// this.getServletConfig(); Servlet配置
// this.getServletContext(); Servlet上下午
ServletContext servletContext = this.getServletContext(); //并且全局为同一个
String username="杰哥哥"; //数据
servletContext.setAttribute("username",username); //将数据保存在了ServletContest中可以允许其他Servlet调用
PrintWriter writer = resp.getWriter();
writer.print("去取值吧");
另一个读取
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username"); //取出
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
if (username==null){
writer.print("还没取值呢哥哥");
}
else
{
writer.print("获取名字:"+username);
}
2.获取初始化参数
设置
<context-param>
<param-name>urlparam-name>
<param-value>jdbc:mysql://localhost:3306/5555param-value>
context-param>
获取
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig config = this.getServletConfig();
String url = config.getInitParameter("url");
PrintWriter writer = resp.getWriter();
writer.print(url);
}
3.请求转发
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入了Demo02");
// RequestDispatcher dispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径
// dispatcher.forward(req,resp); //调用forward实现转发
context.getRequestDispatcher("/gp").forward(req,resp);
}
4.读取文件
打包给classes目录下
用文件流读取
public class propertiesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream inputStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(inputStream);
String username = prop.getProperty("username");
String password = prop.getProperty("password");
resp.getWriter().print(username+" "+password);
}
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
public void sendRedirect(String location) throws IOException;
//重定向 状态码302
resp.sendRedirect("/response_test_war/image");
//转发
req.getRequestDispatcher("/success.jsp").forward(req,resp);
${pageContext.request.contextPath}表示项目路径
获取参数
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
//处理请求
// req.getParameter()
String user_name = req.getParameter("user_name");
String password = req.getParameter("password");
if (user_name.equals("319991012") && password.equals("123456")){
resp.sendRedirect("/response_test_war/success.jsp");
}else{
resp.getWriter().print(user_name);
resp.getWriter().print(password);
resp.getWriter().print("账号密码错误");
}
}
用户打开浏览器 点击多个链接 访问资源,关闭浏览器 被称之为会话
保存会话的两种技术
cookie:客户端技术(响应,请求)
session:服务端技术,可以保存用户的对话,可以把信息或者数据放在Session中!
Session和cookie的区别
cookie[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KPzFehNt-1603807787413)(img\image-20200924173742976.png)]
session
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rGCBp6Hf-1603807787416)(img\image-20200924174020307.png)]
// 获得cookie信息
Cookie[] cookies = req.getCookies();
//判断是否为空
if (cookies!=null){
for (Cookie cookie:cookies){
if(cookie.getName().equals("name")){
out.write("name为"+cookie.getValue()+"
");
}else if (cookie.getName().equals("lastTime")){
long lastTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastTime);
out.write("上次访问的时间是"+date.toLocaleString()+"
");
}else if(cookie.getName().equals("last_time")){
out.write("上次访问的时间 "+cookie.getValue());
}
}
}else{
out.write("第一次访问");
}
//创建cookie
Cookie cookie = new Cookie("name", "jie");
Cookie cookie1 = new Cookie("lastTime", System.currentTimeMillis() + ""); //时间戳
Cookie cookie2 = new Cookie("last_time", new Date().toLocaleString()); //字符串
resp.addCookie(cookie);
resp.addCookie(cookie1);
resp.addCookie(cookie2);
}
从请求中拿到Cookie信息
服务器响应给客户端
Cookie[] cookies = req.getCookies();
获取值
cookie.getName()
cookie.getValue()
添加
Cookie cookie = new Cookie("name", "jie");
resp.addCookie(cookie);
//传入中文时需要加码
Cookie cookie = new Cookie("name", URLEncoder.encode("周成杰","utf-8"));
//输出解码
out.write("name为"+ URLDecoder.decode(cookie.getValue(),"UTF-8") +"
");
//保证名字相同
Cookie cookie = new Cookie("name", "cheng");
cookie.setMaxAge(0);
resp.addCookie(cookie);
添加
HttpSession session = req.getSession();
session.setAttribute("name","周成杰");
session.setAttribute("person",new person("周成杰",20));
String id = session.getId();
if (session.isNew()){
writer.print("Session创建成功"+id);
}else{
writer.print("Session已经在服务器中存在了"+id);
}
获取
//获取
HttpSession session = req.getSession();
String name = (String) session.getAttribute("name");
writer.print(name+"
");
person person = (person) session.getAttribute("person");
writer.print(person);
删除
HttpSession session = req.getSession();
session.removeAttribute("name");
session.invalidate();
或者在xml中配置时间
<session-config>
<session-timeout>30session-timeout>
session-config>
xml配置
15分钟后失效
<session-config>
<session-timeout>15session-timeout>
session-config>
Java Server Pages:Java服务端页面
jsp页面中可以嵌入Java代码,为用户提供动态数据
原理
服务器内部工作
C:\Users\lenovo\bin\IdeaConfig\system\tomcat
jsp本质上就是servlet
初始化
public void _jspInit() {
}
销毁
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
内置对象
final javax.servlet.jsp.PageContext pageContext; 页面上下文
javax.servlet.http.HttpSession session = null; session
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
输出前添加的代码
response.setContentType("text/html"); //用于转换 被识别
pageContext = _jspxFactory.getPageContext(this, request, response, //生成内置 对象
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WFBr9fix-1603807787417)(img\image-20200925144856915.png)]
<%= new java.util.Date()+"
"%>
<%
int num=0;
for (int i=1;i<=100;i++){
num+=i;
%>
<%
}
out.print(num);
%>
2.JSP声明 会被放在生成的类中
<%!
static {
System.out.println("静态代码块");
}
private int password=123456;
public void study(){
System.out.println("定义了方法");
}
%>
设置头和尾
<%@include file="common/Header.jsp"%>
<%@include file="common/footer.jsp"%>
<%@ page errorPage="error/500.jsp" %>
存入数据
//从底层到高层 page->request->session->application
pageContext.setAttribute("name1","周"); //当前页面有效
pageContext.setAttribute("name11","周",PageContext.SESSION_SCOPE); //手动设置 有效范围
request.setAttribute("name2","成"); // 只在一次页面中有效 页面跳转会携带数据
session.setAttribute("name3","杰"); // 个人单独的数据 一次会话有效
application.setAttribute("name4","啊"); //在保存在服务器 从打开服务器到关闭服务器
取值
<%
String name1 = (String)pageContext.findAttribute("name1");
String name11 = (String)pageContext.findAttribute("name11");
String name2 = (String)pageContext.findAttribute("name2");
String name3 = (String)pageContext.findAttribute("name3");
String name4 = (String)pageContext.findAttribute("name4");
String name5 = (String)pageContext.findAttribute("name5");
%>
<h1>
取值
</h1>
<h3>${name1}</h3>
<h3>${name11}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>
转发 携带数据
id:
gender:
class:
sname:
JSTL标签库是为了弥补HTML标签的不足,他自定义了许多标签供使用,功能与java代码相同
核心标签
核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7mNL5XFn-1603807787419)(img\image-20200926171304599.png)]
使用JSTL需要在Tomcat的lib中加入 JTSL和standard的包 否则会报错
if
满分
及格
不及格
for each
<%
List p= new ArrayList();
p.add(0,"周");
p.add(1,"成");
p.add(2,"杰");
request.setAttribute("list",p);
%>
begin表示开始 end结束 step为步速
过滤器 过滤网站的数据
配置Filter代码
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("启动");
}
@Override
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("过滤前");
chain.doFilter(request,response);//让过滤器进行通行 固定代码
System.out.println("过滤后");
}
@Override
public void destroy() {
System.out.println("销毁");
}
}
在xml中配置
<filter>
<filter-name>Encodingfilter-name>
<filter-class>com.jie.Filter.EncodingFilterfilter-class>
filter>
<filter-mapping>
<filter-name>Encodingfilter-name>
<url-pattern>/servlet/*url-pattern>
filter-mapping>
注册监听器 只要session创建便会执行
public class onlineCountListener implements HttpSessionListener {
@Override
//创建session监听
//一旦创建seesion便会执行事件
public void sessionCreated(HttpSessionEvent se) {
System.out.println(se.getSession().getId());
ServletContext ctx = se.getSession().getServletContext();
Integer online = (Integer)ctx.getAttribute("online");
if (online==null){
online=new Integer(1);
}else{
int count=online.intValue();
online=new Integer(count+1);
}
ctx.setAttribute("online",online);
}
@Override
//销毁
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer online = (Integer)ctx.getAttribute("online");
if (online==null){
online=new Integer(0);
}else{
online=new Integer(online-1);
}
ctx.setAttribute("online",online);
}
在xml中配置
<listener>
<listener-class>com.jie.listener.onlineCountListenerlistener-class>
listener>
java连接数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b3f35Ru2-1603807787421)(img\image-20200929102502488.png)]
解决中文乱码问题 同时设置参数
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8";
String username="root";
String password="123456";
1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
2.连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
3.向数据库发送sql的对象 statement:CRUD
Statement statement=connection.createStatement();
4.编写sql
String sql="select * from jdbc.users";
5.执行 查询
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
System.out.println("id="+resultSet.getObject("id"));
System.out.println("na="+resultSet.getObject("sname"));
System.out.println("passwords="+resultSet.getObject("password"));
System.out.println("email="+resultSet.getObject("email"));
System.out.println("birthday="+resultSet.getObject("birthday"));
}
6.关闭连接、释放资源 先开后关 与io相同
resultSet.close();
statement.close();
connection.close();
设置中vm选项导入 -Dfile.encoding=GB2312 否则会出乱码 (个人问题)
//预编译
String sql="insert into jdbc.users(id, sname, password, email, birthday) VALUES (?,?,?,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,4);
preparedStatement.setString(2,"周成杰");
preparedStatement.setString(3,"123456");
preparedStatement.setString(4,"[email protected]");
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));
// 执行sql
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入成功@");
}
preparedStatement.close();
connection.close();
Connection connection = DriverManager.getConnection(url,username,password);
String sql="select * from smbms.test";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
System.out.println(resultSet.getObject("id"));
System.out.println(resultSet.getObject("password"));
}
resultSet.close();
preparedStatement.close();
connection.close();
ACID原则:保证数据的安全
junit单元测试
//依赖
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
dependency>
//通知数据库开启事务
connection.setAutoCommit(false);
无错误 提交 有错误回滚
String sql="update jdbc.account set money=money-100 where name='z'";
connection.prepareStatement(sql).executeUpdate();
int i=1/0;
String sql2="update jdbc.account set money=money+100 where name='c'";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();
System.out.println("提交成功");
@Test
public void Test() {
String url="jdbc:mysql://localhost:3306/jdbc?usrUnicode=true&characterEncoding=utf-8";
String username= "root";
String password="123456";
Connection connection=null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url, username, password);
//通知数据库开启事务
connection.setAutoCommit(false);
String sql="update jdbc.account set money=money-100 where name='z'";
connection.prepareStatement(sql).executeUpdate();
int i=1/0;
String sql2="update jdbc.account set money=money+100 where name='c'";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();
System.out.println("提交成功");
} catch (Exception e) {
try {
System.out.println("事务回滚");
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
什么是MVC: Model view Controll 模型 视图 控制器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KflPCPl3-1603807787422)(img\image-20200927144213632.png)]
Model 模型
Controller(Servlet) 控制层
View 视图层
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WBEV0qEf-1603807787424)(img\image-20201002212727081.png)]
视图View
负责页面的显示;与用户的交互。包含各种表单。 实现视图用到的技术有html/css/jsp/js等前端技术。
用户交互:用户鼠标点击页面;填写页面中各种表单…等等
模型Model
模型负责各个功能的实现(如登录、增加、删除功能)。模型用JavaBean实现。
**JavaBeans *①是Java中一种特殊的类(换言之:JavaBean就是一个Java类).一个Java类 ,满足以下要求,则可称为一个JavaBean a. public修饰的类,提供public 无参构造方法 b. 所有属性 都是private c. 提供getter和setter方法 ②从使用层面来看,JavaBean分为2大类: *a. 封装业务逻辑的JavaBean* (eg:LoginDao.java 封装了登录逻辑) *b. 封装数据的JavaBean* (实体类:eg:Student.java Vedio.java 。往往对应于数据库中的一张表,即数据库中有个Student表,项目中就有个Student.java类) ③JavaBean 是一个可以重复使用的组件,通过编写一个组件来实现某种通用功能,“一次编写、任何地方执行、任何 地方重用”。
控制器Controller
控制器负责将视图与模型一一对应起来。相当于一个模型分发器。所谓分发就是:①接收请求,并将该请求跳转(转发,重定向)到模型进行处理。②模型处理完毕后,再通过控制器,返回给视图中的请求处。建议使用Servlet实现控制器。
三层架构分为:表现层(UI)(web层)、**业务逻辑层(BLL)(service层)、数据访问层(DAL)*(dao层)** **,*再加上实体类库(Model)*
1.实体类库(Model),在Java中,往往将其称为Entity实体类。数据库中用于存放数据,而我们通常选择会用一个专门的类来抽象出数据表的结构,类的属性就一对一的对应这表的属性。
·一般来说,Model实体类库层需要被DAL层,BIL层和UI层引用。
2.数据访问层(DAL),主要是存放对数据类的访问,即对数据库的添加、删除、修改、更新等基本操作
·DAL就是根据业务需求,构造SQL语句,构造参数,调用帮助类,获取结果,DAL层被BIL层调用
3.业务逻辑层(BLL)
·BLL层好比是桥梁,将UI表示层与DAL数据访问层之间联系起来。所要负责的,就是处理涉及业务逻辑相关的问题,比如在调用访问数据库之前,先处理数据、判断数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B3vXkmv5-1603807787425)(img\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmasdMzQxMA==,size_16,color_FFFFFF,t_70.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h4B0jzxh-1603807787425)(img\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZGbmV0L3dlaXhpbl80MjE1MzQxMA==,size_16,color_FFFFFF,t_70.png)]
获取下载文件的路径
获取下载文件名
设置想办法让浏览器支持下载我们需要的的东西
创建缓冲区
获取下载文件的输入流
获取output stream对象
将FileOutputStream流写入buffer缓冲区
使用output stream将缓存区中的数据输出到客户端
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// - 获取下载文件的路径
// String path=this.getServletContext().getRealPath("/kuang.png");
String path="C:\\Users\\lenovo\\Desktop\\JAVAEE\\maven_servlet\\response_test\\src\\main\\resources\\kuang.PNG";
System.out.println("下载路径为:"+path);
// - 获取下载文件名
String filename = path.substring(path.lastIndexOf("\\") + 1);
// - 设置想办法让浏览器支持下载我们需要的的东西
resp.setHeader("Content-Disposition","attachment;filename="+filename+ URLEncoder.encode(filename,"UTF-8"));
// - 获取下载文件的输入流
FileInputStream in = new FileInputStream(path);
// 创建缓冲区
int len=0;
byte[] buffer = new byte[1024];
// - 获取output stream对象
ServletOutputStream out = resp.getOutputStream();
// - 将FileOutputStream流写入buffer缓冲区 使用output stream将缓存区中的数据输出到客户端
while((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
in.close();
out.close();
}
commons-io
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.6version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.4version>
dependency>
在表单中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ab7vHuON-1603807787426)(img\image-20201005184220478.png)]
jsp表单
xml
<servlet>
<servlet-name>FileServletservlet-name>
<servlet-class>com.jie.servlet.FileServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>FileServletservlet-name>
<url-pattern>/upload.dourl-pattern>
servlet-mapping>
servlet
package com.jie.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
public class FileServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//判断上传的文件是普通的表单还是带文件的表单
if (!ServletFileUpload.isMultipartContent(request)) {
return;//如果是普通文件,我们可以直接返回
} //如果通过了这个if,说明我们的表单是带文件上传的;
//创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件;
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {//如果目录不存在,创建这样一个目录;
uploadFile.mkdir();
}
//临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File file = new File(tmpPath);
if (!file.exists()) {//如果目录不存在,创建这样一个目录;
file.mkdir();
}
//处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
//但是我们都建议使用 Apache的文件上传组件来实现,common-fileupload,它需要依赖于 commons-io组件;
//1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的;
DiskFileItemFactory factory = getDiskFileItemFactory(file);
//2.获取ServletFileUpload
ServletFileUpload upload = getServletFileUpload(factory);
//3.处理上传的文件
String msg = uploadParseRequest(upload, request, uploadPath);
//servlet请求转发消息
request.setAttribute("msg",msg);
request.getRequestDispatcher("info.jsp").forward(request,response);
} catch (FileUploadException e) {
e.printStackTrace();
}
}
public static DiskFileItemFactory getDiskFileItemFactory(File file) {
DiskFileItemFactory factory = new DiskFileItemFactory();
//通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
factory.setSizeThreshold(1024 * 1024); //缓存区大小为1M
factory.setRepository(file);//临时目录的保存目录,需要一个File
return factory;
}
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度;
upload.setProgressListener(new ProgressListener() {
@Override
//pBytesRead:已经读取到的文件大小
//pContentLength : 文件大小
public void update(long pBytesRead, long pContentLength, int pItems) {
Long p1=new Long(pBytesRead);
Long p2=new Long(pContentLength);
BigDecimal decimal = new BigDecimal(p1).divide(new BigDecimal(p2),2,BigDecimal.ROUND_HALF_UP);
System.out.println("总大小:"+pContentLength+"已上传:"+pBytesRead+"进度:"+decimal);
}
});
//处理乱码问题
upload.setHeaderEncoding("UTF-8");
//设置单个文件的最大值
upload.setFileSizeMax(1024 * 1024 * 10);
//设置总共能够上传文件的大小
//1024 = 1kb * 1024 = 1M * 10 = 10M
upload.setSizeMax(1024 * 1024 * 10);
return upload;
}
public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadPath)
throws FileUploadException, IOException {
String msg = "";
//3.把前端请求解析,封装成一个FileItem对象
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()){ //判断上传的文件是普通的表单还是带文件的表单
//getFieldName指的是前端表单控件的name;
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8"); //处理乱码
System.out.println(name+":"+value);
}else { //判断它是上传的文件
//=======================处理文件===============================//
//拿到文件名字
String uploadFileName = fileItem.getName();
System.out.println("上传的文件名:"+uploadFileName);
if (uploadFileName.trim().equals("")||uploadFileName==null){
continue;
}
//获得上传的文件名 /images/girl/paojie.png
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
//获得文件的后缀名
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
/*
如果文件后缀名 fileExtName 不是我们所需要的
就直接return,不处理,告诉用户文件类型不对。
*/
System.out.println("文件信息 [件名:"+fileName+"---文件类型"+fileExtName+"]");
//可以使用UUID(唯一识别的通用码),保证文件名唯一;
//UUID.randomUUID(),随机生一个唯一识别的通用码;
String uuidPath = UUID.randomUUID().toString();
//=======================处理文件完毕===============================//
//存到哪? uploadPath
//文件真实存在的路径 realPath
String realPath = uploadPath+"/"+uuidPath;
//给每个文件创建一个对应的文件夹
File realPathFile = new File(realPath);
if (!realPathFile.exists()){
realPathFile.mkdir();
}
//=======================存放地址完毕===============================//
//获得文件上传的流
InputStream inputStream = fileItem.getInputStream();
//创建一个文件输出流
//realPath = 真实的文件夹;
//差了一个文件; 加上输出文件的名字+"/"+uuidFileName
FileOutputStream fos = new FileOutputStream(realPath+"/"+fileName);
//创建一个缓冲区
byte[] buffer = new byte[1024*1024];
//判断是否读取完毕
int len = 0;
//如果大于0说明还存在数据;
while ((len=inputStream.read(buffer))>0){
fos.write(buffer,0,len);
}
//关闭流
fos.close();
inputStream.close();
msg = "文件上传成功!";
fileItem.delete(); //上传成功,清除临时文件
//=======================文件传输完毕===============================//
}
}
return msg;
}
}
<dependency>
<groupId>javax.mailgroupId>
<artifactId>mailartifactId>
<version>1.4.7version>
dependency>
<dependency>
<groupId>javax.activationgroupId>
<artifactId>activationartifactId>
<version>1.1.1version>
dependency>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F4Cd1fbW-1603807787427)(img\image-20201006152646775.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tlsVaSz3-1603807787428)(img\image-20201006152559396.png)]
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.setProperty("mail.host", "smtp.qq.com");
prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码
// 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
//使用JavaMail发送邮件的5个步骤
//创建定义整个应用程序所需的环境信息的 Session 对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("[email protected]", "bksskeflcidmbgdd");
}
});
//开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com", "[email protected]", "bksskeflcidmbgdd");
//4、创建邮件
//创建邮件对象
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("[email protected]"));
//指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
//邮件的标题
message.setSubject("只包含文本的简单邮件");
//邮件的文本内容
message.setContent("你好啊!", "text/html;charset=UTF-8");
//5、发送邮件
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}
实体类
javaBean特定的写法:
一般用来和数据库的字段做映射 ORM (对象映射关系)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GMfgERmj-1603807787429)(\img\image-20201001150922355.png)]
导入数据库
编写数据库公共类
package com.jie.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();
}
System.out.println(driver);
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 update = preparedStatement.executeUpdate();
return update;
}
//释放资源
public static boolean closeResourse(Connection connection,PreparedStatement preparedStatement,ResultSet resultSet){
boolean flag=true;
if (resultSet!=null){
try {
resultSet.close();
resultSet=null;
} catch (SQLException throwables) {
throwables.printStackTrace();
flag=false;
}
}
if (preparedStatement!=null){
try {
preparedStatement.close();
preparedStatement=null;
} catch (SQLException throwables) {
throwables.printStackTrace();
flag=false;
}
}
if (connection!=null){
try {
connection.close();
connection=null;
} catch (SQLException throwables) {
throwables.printStackTrace();
flag=false;
}
}
return flag;
}
}
过滤器
request.setCharacterEncoding("utf-8");
response.setContentType("utf-8");
chain.doFilter(request,response);
配置资源文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf-8
username=root
password=123456
导入静态资源
流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KYNVgB0i-1603807787430)(img\image-20201001160418971.png)]
数据访问层 Dao
编写DAO登录用户的接口
public interface UserDao {
//得到要登录的用户
public User getLoginUser(Connection connection,String userCode) throws SQLException;
}
实现类
public class UserDaoImpl implements UserDao {
@Override
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.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.getTimestamp("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getTimestamp("modifyDate"));
}
BaseDao.closeResourse(null,pstm,rs);
}
return user;
}
}
业务逻辑层 Service
业务层接口
public interface UserService {
//用户登录
public User login(String useCode, String password);
}
实现
public class UserServicelmpl implements UserService {
//引入dao层
private UserDao userDao;
private UserServicelmpl(){
userDao=new UserDaoImpl();
}
//通过业务层调用dao层
@Override
public User login(String useCode, String password) {
Connection connection=null;
User user=null;
try {
connection= BaseDao.getConnection();
user=userDao.getLoginUser(connection,useCode);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
BaseDao.closeResourse(connection,null,null);
}
return user;
}
public static void main(String[] args) {
UserServicelmpl userServicelmpl = new UserServicelmpl();
User admin = userServicelmpl.login("admin","123456");
System.out.println(admin.getBirthday());
}
}
查询数据是否配对
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userCode = req.getParameter("userCode");
String password = req.getParameter("userPassword");
UserService userService=new UserServicelmpl();
User user = userService.login(userCode, password);
if(user!=null){ //查有此人
req.getSession().setAttribute(Constants.USER_SESSION,user);
//转到
resp.sendRedirect("jsp/frame.jsp");
}else{ //无法登录
req.setAttribute("error","用户名或者密码不正确");
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
退出登录
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.removeAttribute(Constants.USER_SESSION);
resp.sendRedirect(req.getContextPath()+"/login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
退出session优化
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest) req;
HttpServletResponse response=(HttpServletResponse) resp;
if (request.getSession().getAttribute(Constants.USER_SESSION)!=null){
chain.doFilter(req,resp);
}else{
response.sendRedirect(request.getContextPath()+"/error.jsp");
}
}
jsp静态资源导入
接口
public int updatePwd(Connection connection,int id,int password) throws SQLException;
实现类
//修改用户密码
@Override
public int updatePwd(Connection connection, int id, int password) throws SQLException {
PreparedStatement pstm=null;
int execute=0;
if (connection!=null){
String sql="update smbms.smbms_user set userPassword=? where ?";
Object []params={password,id};
execute = BaseDao.execute(connection, pstm, sql, params);
BaseDao.closeResourse(null,pstm,null);
}
return execute;
}
//修改用户密码
@Override
public boolean updatePwd(int id, String pwd) {
Connection connection = null;
boolean flag=false;
try {
connection=BaseDao.getConnection();
if (userDao.updatePwd(connection, id, pwd)>0){
flag=true;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
BaseDao.closeResourse(connection,null,null);
}
return flag;
}
public void update(HttpServletRequest req, HttpServletResponse resp){
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String newpassword=req.getParameter("newpassword");
String olodpassword=req.getParameter("oldpassword");
boolean flag=false;
if (o!=null && !StringUtils.isNullOrEmpty(newpassword) && ((User)o).getUserPassword().equals(olodpassword)){
UserService userService=new UserServicelmpl();
flag = userService.updatePwd(((User) o).getId(), newpassword);
if (flag){
req.setAttribute(Constants.USER_MESSAGE,"修改密码成功,请退出重新登录");
req.getSession().removeAttribute(Constants.USER_SESSION);
}else{
req.setAttribute(Constants.USER_MESSAGE,"修改密码失败");
}
}else{
req.setAttribute(Constants.USER_MESSAGE,"修改密码失败");
}
try {
resp.sendRedirect(req.getContextPath()+"/jsp/pwdmodify.jsp");
} catch (IOException e) {
e.printStackTrace();
}
}
<context-param>
<param-name>userparam-name>
<param-value>adminparam-value>
context-param>
<context-param>
<param-name>passwordparam-name>
<param-value>123param-value>
context-param>
<servlet>
<servlet-name>configservlet-name>
<servlet-class>com.jie.servlet.servlet1servlet-class>
<init-param>
<param-name>namespaceparam-name>
<param-value>123param-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>configservlet-name>
<url-pattern>/1url-pattern>
servlet-mapping>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = getServletConfig();
resp.getWriter().println(getServletContext().getInitParameter("user"));
resp.getWriter().println(getServletContext().getInitParameter("password"));
resp.getWriter().println(getServletConfig().getInitParameter("namespace"));
}