JavaWeb 开发模式:C/S、B/S
服务器类别(软件和硬件):文件服务器、网页服务器、域名服务器、数据库服务器、FTP服务器。
客户端和服务器的访问过程
请求:客户端 -> 服务器
响应:服务器 -> 客户端
网页服务器tomcat
作用:发布项目,共享网页资源
项目访问地址 http://目标主机的ip地址:服务器端口号/项目名/被访问的资源路径或页面(如果是自己的电脑作为服务器,则主机ip可以写成ip地址或127.0.0.1或localhost),80是默认的端口号。
(面试)
tomcat目录下的文件夹:
bin 存放一些指令(启动、停止服务器...)
conf 存放配置文件
lib 存放jar包
logs 存放日志
temp 存放临时文件
webapps 存放共享的项目资源
work 存放jsp编译后的代码
tomcat的常用操作:conf/server.xml(修改端口号)
<Connector part="80" ... />
管理服务器中的项目
tomcat的主界面(http://localhost:8080/) -> ManagerApp(Applications登录后查看)只要将项目放到webapp下面,无论用户访问的是哪一个项目,tomcat都会默认启动所有的项目。
创建一个用户,允许登录tomcat,conf/tomcat-user.xml
<role rolename="manager-gui" />
<user username="tomcat" password="123456" roles="manager-gui" />
IDEA中部署tomcat(找百度)
Deployment(部署项目指的是将项目放到tomcat服务器)
URL项目的访问路径 HTTP port:修改端口号
Application context:这里设置的是项目名(为了方便通常设置为 / )
JSP本质上就是一个页面,与html的区别在于:jsp即支持html的代码,也支持在页面中编写java代码。(动态页面)
小脚本:
<% java代码 %> <%!定义方法 %> <% =变量名 %> 输出变量值
例:<% int a=10;String name="text";%>
username=<% =name %>,age=<% =a %>
JSP三大指令(使用@开头):
<%@ page 属性名="属性值" %> 设置当前jsp页面的一些属性
<%@ include file="页面地址" %> 实现页面的共享
<%@ taglib prefix="前缀" uri="地址" %> jstl标签库时使用
jsp页面一定要在第一行添加page指令
<%@ page import="bean.Users" %>
<%@ page contextType="text/html;charset=UTF-8" language="java" %>
jsp的内置对象(九个):page、pageContext、out、config、exception、request、response、session、application。
page相当于当前jsp自己的对象,等价于this
pageContext当前页面范围内的一个对象
//pageContext存值
pageContext.setAttribute(String key,Object value);
//pageContext取值
pageContext.getAttribute(String key);
out用来做输出的 out.print("输出内容");
config获得一些配置信息
//ServletContext是jsp内置对象application的类型
ServletContext servletContext = config.getServletContext();
//得到初始化参数
String initParameter = config.getInitParameter(" ");
//得到Servlet name
String servletName = config.getServletName();
//config可以实现服务器地址的获取
String realPath = config.getServletContext().getRealPath("/文件夹");
exception异常
如果jsp页面中想要使用exception内置对象,需要在page指令的位置添加属性:
<%@page contextType="text/html;charset=UTF-8" isErrorPage="true" language="java"%>
request转发
//request取值(单次请求)
request.getAttribute(String key);
//request存值
request.setAttribute(String key,Object value);
//得到请求中的单个参数
String 变量名 = request.getParameter("元素name值");
//得到请求中同名的一组参数(复选框)
String[] 变量名 = request.getParameterValues(String name);
//设置请求的参数
request.setCharacterEncoding("utf-8");
//跳转页面
request.getRequestDispatcher("页面路径").forward(request,response);
get请求和post请求的区别:
1.post请求的数据不会在地址栏显示,数据更安全;而get请求会将请求的参数拼接到地址栏,数据不安全
2.get请求在拼接参数时,第一个参数使用?间隔,之后的参数使用&拼接
3.由于get请求在地址栏中拼接参数,所以对长度是有限定的;而post请求则不限定,所以在提交文件时都选用post请求
response重定向
//跳转页面
response.sendRedirect("目标页面");
//获得打印流(输出流)
PrintWriter writer = response.getWriter();
//添加cookie
Response.addCookie(cookie);
//设置响应的结果类型
Response.setContentType("text/html;charset=UTF-8")
对比两种跳转页面的方式:
1、概念
2、请求和响应的次数不同
转发:一次请求一次响应(将结果页面的内容直接响应给客户端)
login.jsp -> tologin.jsp -> 地址栏:tologin.jsp(request中有数据)
重定向:两次请求两次响应(第一次响应结果页面的地址,第二次响应结果页面的内容)
login.jsp -> tologin.jsp -> /success.jsp(request中的值为null)
3、重定向时会丢失request中的数据,转发则不会
session单次会话
//session存值
session.setAttribute(String key,Object value);
//session取值
session.getAttribute(String key);
//session失效
session.invalidate();
//从session中删除某个key
session.removeAttribute(String key);
//设置session的有效期
session.setMaxInactiveInterval();
//获取session的有效期-默认是半小时
session.getMaxInactiveInterval();
//session会话的id
session.getId();
重定向时也不会丢失session中的数据
session存的数据是在服务器端,所以要选择合适的数据存放
application表示整个服务器运行期间可以跨越多个会话
//application存值
application.setAttribute(String key,Object value);
//application取值
application.getAttribute(String key);
总结:
可以存值的内置对象:pageContext、request、session、application
pageContext的有效范围是当前页面
request的有效范围是单次请求
session的有效范围是单次会话(包含多次请求)
application的有效范围是服务器运行期间
(面试)
作用域:pageContext < request < session < application
Servlet本质上就是一个java代码,用来顶替jsp中编写java业务逻辑代码的部分,步骤如下:
1、先创建java类,继承HttpServlet
2、重写方法
@Override //用来编写处理业务的代码
protected void service(HttpServletRequest req, HttpServletResponse resp) throws Exception {
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String userpass = req.getParameter("userpass");
if ("zhangsan".equals(username) && "123456".equals(userpass)){
//session
HttpSession session = req.getSession();
session.setAttribute("uname",username);
resp.sendRedirect("success.jsp");
}else{
resp.sendRedirect("lose.jsp");
}
}
@Override //销毁Servlet对象时的方法
public void destroy() {
System.out.println("destroy");
}
@Override //初始化Servlet对象时的方法
public void init(ServletConfig config) throws ServletException {
System.out.println("init");
}
3、在web.xml文件中建立请求地址和处理类之间的关系(当需要建立多个请求地址时,应使用注解的形式进行编写)
<web-app ...>
<servlet>
<servlet-name>aa</servlet-name>3
<servlet-class>通过处理类去调取service方法</servlet-class>4
</servlet>
<servlet-mapping>
<servlet-name>aa</servlet-name>2
<url-pattern>对应表单action属性中的请求名</url-pattern>1
</servlet-mapping>
</web-app>
(面试)
servlet的生命周期:当客户端发送第一次请求时,根据web.xml的文件配置找到对应的处理类,先判断该处理类的对象是否已经创建,如果没有,则先创建对象,如果有,则调取init方法进行初始化,再调取service方法处理业务,然后根据客户端的请求方式,判断调取doGet方法还是doPost方法;当客户端再次发送请求后,调取service方法再次进行判断;当服务器关闭时,调取destroy方法销毁对象。(servlet是单例的)
HttpServlet的service方法中已经对请求方式做了区分。
补充:在后续使用servlet时,如果不需要区分get和post的逻辑操作,可以直接重写service方法,如果需要区分,则重写doGet()和doPost(),上述两者二选一即可。
jsp和servlet的关系:jsp最终会被编译成一个java文件(存放在tomcat的work文件夹下),而这个java文件就是servlet;jsp编译的java类,继承HttpJspBase(tomcat -> lib -> jasper.jar),HttpJspBase继承HttpServlet。
Servlet3.0注解形式
@WebServlet(属性名=属性值)
name="指定servlet类的对象名" initParams="初始化参数"
urlPatterns/value="请求地址"
urlPatterns可以使用通配符来进行地址的匹配( /* )
初始化参数的操作
作用:可以将一些场景下的常量值定义到web.xml的初始化标签中,让servlet去读取,方便后续的修改
<web-app ...>
<context-param>
<param-name>coding</param-name>
<param-value>utf-8</param-value>
</context-param>
</web-app>
使用(全局):在init方法中获取初始化参数
config.getServletContext().getInitParameter("coding");
补充:使用context-param定义的初始化参数是多个servlet都可以共享访问的
使用(局部):给指定的servlet配置自己独有的初始化参数
@WebServlet(urlPatterns="/test1",
initParams={ @WebInitParam(name="user1",value="这是test1的user") } )
读取:config.getInitParameter("user1");
服务器默认配置是启动后先访问index.jsp页面,如果想要修改可以在web.xml中进行配置。
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
项目开发
开发流程:立项(项目经理) -> 确定好需求 -> 分析(需求分析/数据库分析) -> UI(做效果图) -> 前端开发(页面-html) -> 后端(将html的静态功能编成动态功能) -> 测试工程师(测试代码和需求的匹配度) -> 上线 -> 运维
由于传统的项目开发效率低,为了提高效率,现阶段的前后端都是同步进行的。
后端
目前所学:html(css、javascript、jquery) + servlet + mysql(jdbc)
如何编写代码:
1、创项目(创建包结构)
com.xxx.bean
放的是和数据库对应的java实体类
将数据库中的数据,封装到java的对象中(实体类)
命名规范:类名=表名 属性名=列名,例Users
com.xxx.dao
定义操作数据库方法的接口
补充:在使用驱动包时,需要将驱动包复制到tomcat的lib文件夹下
命名规范:实体类名+Dao,例UsersDao
com.xxx.dao.impl
dao包下的实现类所存放的包路径
命名规范:接口名+Impl,例UsersDaoImpl
com.xxx.service
定义各个功能的业务逻辑方法的接口
命名规范:实体类名+service,例UsersService
com.xxx.service.impl
service包下的实现类所存放的包路径
命名规范:接口名+Impl,例UsersServiceImpl
com.xxx.web
定义servlet,用来接收用户请求,调取处理业务逻辑的方法,并根据结果跳转页面
命名规范:请求名+Servlet,例ToLoginServlet
servlet主要做三件事:1.接收参数 2.调取业务逻辑 3.跳转页面
com.xxx.util 工具类
注意:在上述的包结构中,有固定的调取关系:servlet调取service,service调取dao。
2、实现用户的登录和登出
3、实现用户列表的展示和分页
limit 开始下标,显示条数;
pageindex页码值 pagesize每页显示条数
分页查询:limit (pageindex-1) * pagesize,pagesize;
totalPages 总页数 count(*) 总条数
totalPages=总条数%pagesize>0?总条数/pagesize+1:总条数/pagesize
4、模糊查询
5、增加/删除/修改
真删除 delete from 表名 where 限定条件
假删除 在数据表中添加一列,表示用户的状态,设置状态的值,如0表示正常使用,1表示已注销
update 表名 set status=1 where 限定条件
6、合并Servlet
7、过滤器
功能:对数据进行限定
特点:定义的过滤器代码,在请求和响应时都会被执行
实现:1.创建类,实现javax.servlet.Filter接口
2.配置web.xml文件(与servlet的配置格式一致)
说明:当服务器启动时,就会调取init方法,且只会调取一次;当用户请求进来时,会重复调取doFilter方法;当服务器关闭时,会调取destroy方法。
注解:@WebFilter(urlPatterns = "/请求名")
过滤器链:将多个过滤器添加到项目中,web.xml文件中配置的先后顺序会影响到过滤器最后执行的先后顺序。
使用场景:添加过滤器,设置编码方式
添加过滤器,实现权限判断
8、监听器
作用:实时监测项目运行中对象和程序的变化
监听的分类
ServletContext域 | HttpSession域 | ServletRequest域 | |
域对象的创建与销毁 | ServletContext Listener | HttpSession Listener | ServletRequest Listener |
域对象内的属性变化 | ServletContext AttributeListener | HttpSession AttributeListener | ServletRequest AttributeListener |
实现:使用监听器实现在线人数统计
9、EL表达式(用来代替jsp页面中原来小脚本的作用)
作用:显示数据、执行运算、获取指定作用域中的数据、调取java方法
优点:实现基础的类型自转换(比如:可以把"123"自动转换成123)
支持三目运算符和关系运算符
获得指定作用域的值
语法:${key/变量名}
注意:EL表达式获取的值一定是从作用域中获取的,所以需要先存值
补充:当不同作用域存储了相同的key值时,默认取值的顺序是pageContext、request、session、application。
如果想要获取指定作用域的值? ${作用域.key}
作用域:pageScope、requestScope、sessionScope、applicationScope
10、JSTL标签库
标签库提供了循环和判断的标签,方便在jsp页面中使用,并结合EL表达式一起操作
使用:1.项目中引入标签库(需要同时将jar包放置在tomcat的lib文件夹下)
2.在页面中使用jsp的指令,引入标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
prefix表示前缀,自定义的值,通常使用c
标签:<% pageContext.setAttribute("age",16) %>
单分支if
<c:if test="${age<18}"> 未成年 </c:if>
多分支if
<c:choose> <c:when test="${age<18}"> 未成年 </c:when>
<c:when test="${age<30}"> 青年 </c:when>
<c:otherwise> 青年以上 </c:otherwise> </c:choose>
数值类型的循环
<c:forEach begin="1" end="10" var="n">
n=${n},
</c:forEach>
集合的循环
<%
List list = new ArrayList();
list.add("abc");
list.add("bcd");
list.add(12345);
pageContext.setAttribute("ulist",list);
%>
<c:forEach items="${ulist}" var="str" varStatus="sta">
${sta.count}--${sta.index}--str=${str},
</c:forEach>
items定义被遍历的集合,var定义变量名,varStatus定义编号属性(count行号、index下标)
11、MVC设计模式
M-model模型层(bean,dao,service) V-view视图层(html,jsp) C-controller控制层(web-servlet)
目的:实现代码解耦,各司其职
耦合度指的是代码之间的关联性,通常是越低越好
12、cookie
创建:Cookie c = new Cookie(key,value);
作用:在客户端存值,对于服务器来说,没有压力,所以安全性低
场景:在浏览器中提示保存当前的账号和密码,一些程序的本地浏览记录也可以使用
常用方法:getName(); getValue(); setValue(); 获得有效期getMaxAge(); 设置有效期setMaxAge(0不记录/-1会话级,关闭浏览器失效/60*60过期时间为1小时);
cookie和session的对比(存储位置/安全性/存储大小)
关联性:本身http请求是无状态的(不记忆),但session可以在多次请求中保持同一次会话的原因是,服务器分配一个sessionid后,会将这个sessionid返回到客户端,并存储在cookie中,在之后的请求和响应中始终传递该值,这样的话服务器端判断是否是同一次会话,只需要拿到cookie中sessionid的值做匹配,能匹配上,则说明是同一次会话。
(面试)
问:如果是浏览器里面禁用cookie的话,session还能不能用?
答:不能。
13、AJAX(阿贾克斯)
实现异步请求的一种方式,js、jquery都可以实现
实现代码:
$.ajax({ //基于jquery
url:"请求地址",
data:"请求的参数",
type:"请求方法",
dataType:"服务器返回的数据格式",
success:function(rs){
//回调函数(当服务器处理完结果后,返回success指定的函数中)
//function中的参数rs,是用来接收返回的信息
$("span标签的id").html(rs);
};
})
使用场景:验证用户名是否可用、数据的自动填充
补充:ajax请求发送后,服务器处理,处理完毕后,默认回到原页面
$.get(url,data,function(){ });
$.getJSON(url,data,function(){ });
$.post(url,data,function(){ });
常用的请求方式有哪些?
地址栏直接编写:get 表单:method="get/post"
超链接:<a href="请求地址?key=value&key2=value2&key3=value3"></a>
js跳转请求:location.href="请求地址?key=value&key2=value2"
ajax:$.ajax({..type="get"..}); $.get(); $.getJSON();
ajax:$.ajax({..type="post"..}); $.post();
14、文件的上传和下载
当文件上传时,需要设置表单的属性,与此同时,数据参数不能直接使用HttpServletRequest获取,需要使用SmartUpload对象的Request方法。
<form action="/users?Method=add" method="post"
enctype="multipart/form-data"></form>
//1.创建上传文件的工具类
SmartUpload smartUpload = new SmartUpload();
//2.得到PageContext对象
JspFactory df = JspFactory.getDefaultFactory();
PageContext pc = df.getPageContext(this,req,resp,null,false,1024,true);
//3.初始化上传的工具类对象
smartUpload.Initialize(pc);
//4.设置编码方式
smartUpload.setCharset("utf-8");
//5.上传
smartUpload.upload();
//6.需要有一个文件保存的操作
File file = smartUpload.getFiles().getFile(0);
//7.得到文件的相关属性
String fileName = file.getFileName();//文件名
String contentType = file.getContentType();//文件类型
System.out.println("filename="+fileName+",contenttype="+contentType);
String url = "/uploadimg/"+fileName;
//8.保存操作
file.saveAs(url,SmartUoload.SAVE_VIRTUAL);
//9.获取非文件的内容
Request request = smartUpload.getRequest();
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
String uage = request.getParameter("uage");
String usex = request.getParameter("usex");
//10.调取业务逻辑,跳转页面
//1.获取要下载的图片路径
String imgurl = request.getParameter("imgurl");
//2.1将响应的内容设置成二进制流的形式
resp.setContentType("application/octet-stream");
//2..2告知浏览器现在需要一个弹窗
//uploadimg/asdzxc.jpg
int end = imgurl.lastIndexOf("/");//得到最后一个/的下标
String filename = imgurl.substring(end+1);
//如果文件名是中文,需要处理编码
filename = URLEncoder.encode(filename,"utf-8");
//展示给用户下载的文件名称是什么
resp.addHeader("Content-Disposition","attachment;filename="+filename);
req.getRequestDispatcher(imgurl).forward(req,resp);
resp.flushBuffer();//刷新缓存
二维码生成(创建index.html)
1.引入jquery.js文件
2.引入支持中文编码的js文件(utf.js)
3.引入jquery.qrcode.js文件
4.在页面中编写一个div,用于显示二维码
<div id="qrcode"></div>
5.准备二维码的规格对象(JSON)
var config = {
width:200,
height:200,
text:"内容",
correctLevel: 0,//二维码的纠错级别
background:"rrggbb",//二维码的后景颜色,默认白色
foreground:"rrggbb",//二维码的前景颜色,默认黑色
render:"绘制模式"//取值table(默认)/canvas
};
6.通过选择器,查找到上述的div,得到jquery对象,通过jquery对象的qrcode函数生成二维码。
$("#qrcode").qrcode(config);