Servlet和jsp
b/s:浏览器请求,服务器响应
c/s:客户端请求,服务器响应
资源:
动态资源(jsp,servlet):不同用户访问同一动态资源的时候得到的结果可能会不一样
静态资源(jpg,png,css,js,html):不同用户访问同一静态资源时得到的结果一样
Servlet
即server applet,运行在服务器上的小程序,定义了一套浏览器如何访问服务器的规则,本质上是一个接口Servlet
生命周期
创建Servlet对象后---------->初始化(调用 init () 方法)--------->处理/响应客户端的请求(调用 service() 方法)--------->销毁(调用 destroy() 方法,最后由 JVM 的垃圾回收器进行垃圾回收)
一
-
首先定义类并实现Servlet接口,重写其中的方法方法 作用 initservlet的初始化方法,当第一次访问该servlet的时候执行该初始化方法(生命周期可以更改,可以通过修改初始化方法,令服务器一启动就执行初始化方法(如下))serviceservlet的服务方法每一次访问该servlet的时候都会执行该服务方法destroyservlet的销毁方法,当服务器正常关闭时,执行该销毁方法 -
web.xml的配置文件,如下

二
-
与一相同,继承Servlet接口 -
无需在web.xml中进行配置,而是通过@WebServlet注解,可以代替web.xml中所有关于该servlet的配置,将url填写在该注解后的括号中

三
-
直接继承GenericServlet类,GenericServlet是一个抽象类,对init和destroy方法进行了空实现,只需实现service方法 -
同样使用注解

四(请求)
-
继承HttpServlet,重写doGet和doPost方法,默认请求方式为get,所以默认调用doGet方法,当请请求方式为post时调用doPost方法(可采用嵌套方式,即在doGet方法内调用doPost方法,这样,无论使用什么请求都会调用doPost方法) -
新建jsp页面

get请求和post请求的区别
get请求:在地址栏中拼接参数,参数不能存放太大,大概2k左右,相对来说不安全;查询效率高于post请求;get请求没有请求体,只有query string
post请求:请求参数放在请求体中,相对来说更安全,查询效率没有get高
五(注解写法)
使用@WebServlet注解时,可使用多种方法
-
第一种:@WebServlet("/servletDemo5") -
第二种(多路径写法):@WebServlet({"/xxx","/yyy"}) -
第三种(只要后缀为.can的路径都可以访问):@WebServlet("*.can") -
第四种(只要前缀为/user/的路径都可以访问):@WebServlet("/user/*") -
第五种(可以绑定所有,但优先级低于已经绑定的url,并且可以访问.jsp后缀的文件(当地址栏输入xxx.jsp时会跳转到jsp页面),而不会跳转到servletDemo5):@WebServlet("/") -
第六种(可以绑定所有,但优先级低于已经绑定的url,匹配不到.jsp后缀的文件(当地址栏输入xxx.jsp时会匹配为servletDemo5),并且会把.jsp后缀的文件匹配到servletDemo5):@WebServlet("/*")
Request
参数中的request是客户端传入的,即doGet和doPost方法的形参
中文乱码问题
request.setCharacterEncoding("utf-8");
获取参数(表单中name属性的值)
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+":"+password);
路径
System.out.println(request.getRequestURL());// 完整路径 System.out.println(request.getRequestURI());// 部分路径
获取地址栏拼接参数(只有get请求有)(略)
System.out.println(request.getQueryString());
获取请求头中的值(略)
System.out.println(request.getHeader("Host"));
域对象
四大域对象(page(jsp有效),request(一次请求),session(一次会话),servletContext(application--jsp中的名字)(当前web应用))

// 域对象:能够在一定的范围内共享数据
// request的作用域在一次请求和一次响应之间
// xxx.setAttribute即为设置域对象
request.setAttribute("username","张三");// 参数为“名值对”
//由于request作用范围是一次请求一次响应,浏览器访问requestDemo1视为一次请求,若要获取username的值,就需要在本次响应中返回,而不能再次调用requestDemo2进行返回,但可以使用请求转发,如下
System.out.println(request.getAttribute("username"));
请求转发
// 当访问requestDemo1时,地址栏仍为requestDemo1,但由requestDemo2返回值,不能跳转到外部资源
// 由于请求转发是一次请求,所以使用请求转发,仍可以调用到requestDemo2,可以获取username的值,而不需要在地址栏输入进行二次请求
// 获取请求转发器
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/requestDemo2");
// 请求转发
requestDispatcher.forward(request,response);
实例
登录功能
@WebServlet("/requestLoginTest")
public class RequestLoginTest extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取表单中的账号密码
String username = request.getParameter("username");
String password = request.getParameter("password");
// 获取到登录页面和登陆成功页面的请求转发器
RequestDispatcher requestDispatcher1 = request.getRequestDispatcher("/login.jsp");
RequestDispatcher requestDispatcher2 = request.getRequestDispatcher("/successful.jsp");
// 账号密码判断
if (username.equals("zhangsan")) {
if (password.equals("123456")) {
// 登录成功,通过请求转发跳转到登陆成功页面
requestDispatcher2.forward(request,response);
} else {
// 设置域对象,用于在登录页面通过${requestScope.end}展示值
request.setAttribute("end","密码错误");
requestDispatcher1.forward(request,response);
}
} else {
request.setAttribute("end","账号错误");
requestDispatcher1.forward(request,response);
}
}
}
Response
常见响应状态码:
-
200:成功响应,正常的状态码 -
302:重定向,正常的状态码 -
404:请求资源找不到(查看访问的路径是否正确,查看访问的资源福否被编译进out目录) -
405:请求的方法不允许(后端无法接收前端的请求方式) -
403:请求被拒绝(在爬虫中加上请求头user-agent) -
500:服务器内部出错(在idea控制台中查看报错信息)
乱码问题
response.setContentType("text/html;charset=utf-8");
写入数据
// 将数据写给前端,在没有处理的情况下会直接显示在前端网页上
response.getWriter().write("张三");
重定向
response.sendRedirect("/login.jsp");
请求转发和重定向
| 请求转发 | 重定向 |
|---|---|
一次请求 | 两次请求 |
在服务器内部进行资源跳转,不能访问外部资源 | 服务器会告诉浏览器访问什么资源,可以访问外部资源 |
地址栏没有发生变化 | 地址栏发生了变化 |
浏览器不知道服务器内部做了什么 | 浏览器接收到重定向的消息后再进行访问 |
Cookie
会话(多次请求,多次响应)技术,运行在客户端上
解决多次请求和多次响应之间共享数据的问题
创建cookie
// value可以存储中文,但在存储空格时需要进行编码和解码
String value = "月 亮";
String encode = URLEncoder.encode(value, "utf-8");
Cookie cookie = new Cookie("name",encode);
添加cookie
// cookie的存储时间默认在浏览器关闭后就消失 // 设置getMaxAge();可让关闭后还能存在 // 当参数为正整数时,是多少就是多少秒 // 当参数为0时,删除该cookie // 当参数为-1时,就是默认情况 cookie.getMaxAge(); // 把cookie添加到响应中,让浏览器能存储它 response.addCookie(cookie);
拿到请求中的cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
String name = cookie.getName();
// 解码
if ("name".equals(name)) {
String value = cookie.getValue();
String decode = URLDecoder.decode(value,"utf-8");
System.out.println(name+":"+decode);
}
}
实例
登录注册
@WebServlet("/cookieLoginTest")
public class CookieLoginTest extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 解决乱码问题
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/login.jsp");
// 标志位,判断是否是第一次登录
boolean flag = true;
if (username.equals("zhangsan")) {
if (password.equals("123456")) {
// 登陆成功时,记录登录时间
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String format1 = format.format(date);
// 遍历cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
String name = cookie.getName();
// 第一次访问时,没有名为name的cookie,所以不进入该if
if (name.equals("name")) {
String value = cookie.getValue();
String decode = URLDecoder.decode(value, "utf-8");
response.getWriter().write( "欢迎,您上次登录的时间为" + decode);
flag = false;
}
}
if (flag) {
//request.setAttribute("welcome", "欢迎,这是您第一次登录");
//requestDispatcher.forward(request, response);
// 将数据写给前端(使用cookie时,尽量不使用请求转发)?
response.getWriter().write("欢迎,这是您第一次登录!");
}
// 将时间添加到cookie中
String encode = URLEncoder.encode(format1, "utf-8");
Cookie cookie1 = new Cookie("name", encode);
response.addCookie(cookie1);
} else {
request.setAttribute("end", "密码错误");
// 使用请求转发,如果使用了request域,使用重定向后,request就失效了,因为超出了作用域范围
requestDispatcher.forward(request, response);
}
} else {
request.setAttribute("end", "账号不存在");
requestDispatcher.forward(request, response);
}
}
}
Session
会话技术,存储在服务器上(相对于cookie更加安全)
session依赖cookie而存活,当浏览器第一次访问服务器时,会生成一把“钥匙”,即Set-Cookie:JSESSIONID=xxx,在后续的访问中,浏览器都会携带该同一钥匙,若钥匙相同,则可以访问到服务器获取值;在关闭浏览器后,cookie销毁,重启浏览器,会重新生成一把“钥匙”,由于重新生成的钥匙和原钥匙不匹配,所以无法得到相应的值,要解决该问题就需要增大cookie的生命周期
拿到session对象
HttpSession session = request.getSession();
设置域对象
session.setAttribute("name","zhangsan");
设置生命周期添加
// 让浏览器关闭后再启动依旧能访问到服务器中的session数据(增大cookie的生命周期)
// 拿到当前session的钥匙,JSESSIONID的值,并设置存活时间
String id = session.getId();
Cookie cookie = new Cookie("JSESSIONID",id);
cookie.setMaxAge(500);
response.addCookie(cookie);
ServletContext
作用域为全局
得到对象添加值
javax.servlet.ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("config","xxxxx");
Filter过滤器
1.通过@WebFilter()对指定文件进行过滤,括号中为需要过滤的文件
2.在doFilter方法中对过滤的文件进行操作
3.放行
filterChain.doFilter(servletRequest,servletResponse);
实例
对所有文件进行拦截,只放行login.jsp页面和requestLoginTest,若登录成功后,可以访问所有文件
// requestLoginTest
@WebServlet("/requestLoginTest")
public class RequestLoginTest extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
HttpSession session = request.getSession();
if (username.equals("zhangsan")) {
if (password.equals("123456")) {
// 新建session域对象,标志位判断是否登陆成功
session.setAttribute("flag", true);
// 若之前输入账号密码出现错误,会出现提示,在登录成功后删除提示
session.removeAttribute("name");
session.removeAttribute("pass");
// 登陆成功,重定向到登陆成功页面
response.sendRedirect("/successful.jsp");
} else {
// 标志位判断没有登录成功过,在过滤器中就不会放行
session.setAttribute("flag", false);
// 域对象,用于显示在login.jsp界面提示用户
session.setAttribute("pass","密码错误");
// 当密码错误时,会删除账号不存在的提示,而出现密码错误的提示
session.removeAttribute("name");
response.sendRedirect("/login.jsp");
}
} else {
session.setAttribute("flag", false);
session.setAttribute("name","账号不存在");
session.removeAttribute("pass");
response.sendRedirect("/login.jsp");
}
}
}
// 过滤器
@WebFilter("/*")// 可以对所有文件进行过滤
public class FilterTest implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
// 放行与登录相关的页面
if (httpServletRequest.getRequestURI().equals("/login.jsp") || httpServletRequest.getRequestURI().equals("/requestLoginTest")) {
filterChain.doFilter(httpServletRequest,httpServletResponse);
} else {
// 与登录不相关时,进行判断,是否成功登陆过
Object flag = httpServletRequest.getSession().getAttribute("flag");
if (flag == null) {
httpServletResponse.sendRedirect("/login.jsp");
} else {
// 不为空时,判断标志位
Boolean Tflag = (Boolean) flag;
// 如果标志位为true,说明成功登陆过,放行
if (Tflag) {
filterChain.doFilter(httpServletRequest,httpServletResponse);
} else {
httpServletResponse.sendRedirect("/login.jsp");
}
}
}
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
JSP
java server pages
jsp脚本
用于嵌入java代码使用的脚本
1.该脚本放置在该jsp被编译后的servlet类中的service方法中
<%
System.out.println("hello");
int a = 5;
%>
2.该脚本用于输出到页面上
<%=
a
%>
3.该脚本作为全局变量来使用,放在类体里面
<%!
int b = 5;
%>
jsp指令
用于配置技术jsp页面使用的
指令格式:<%@ %>
1.page指令
其中errorPage和isErrorPage(发生错误的页面通过errorPage绑定跳转路径,被调用的错误页面通过isErrorPage绑定为true,实现两者的跳转)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
2.include指令
用于导入页面资源,让别的页面能显示到该页面,可在body中引入
<%@ include file="/successful.jsp"%>
3.taglib指令
用于导入资源,相当于java导包
<%@ taglib prefix="c" uri="" %>
jsp内置对象
pageContext
session
request
application(servletContext)
<--不需要创建,直接调用-->
pageContext.setAttribute("username","zhangsan");
MVC
model:模型层
view:视图层
controller:控制层

El表达式
格式:${表达式}
<%
pageContext.setAttribute("username","zhangsan");
request.setAttribute("username","lisi");
session.setAttribute("username","wangwu");
application.setAttribute("username","zhaoliu");
%>
${pageScope.username}
${requestScope.username}
${sessionScope.username}
${applicationScope.username}
<--当没有域名时,默认从作用域最小的域开始查找数据-->
${username}
<--算术运算符,逻辑运算符-->
${1>1}
JSTL
1.首先在web包下创建lib包,导入jstl的jar包
创建lib包,导入jar包,点击Add as library,打开Project Structure中的Problems,解决后可以使用

2.在jsp页面中引入
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
3.常用标签
<body>
<%
request.setAttribute("ifMarried", true);
Calendar instance = Calendar.getInstance();
int i = instance.get(Calendar.DAY_OF_WEEK);
request.setAttribute("weekDay",i-1);
ArrayList<String> strings = new ArrayList<>();
strings.add("zhangsan");
strings.add("lisi");
request.setAttribute("items",strings);
%>
<%--c:if 里面的test属性必有,值为boolean值,true为显示里面内容,false不显示,一般配合el表达式使用--%>
<c:if test="${ifMarried}">
xxx结婚了
</c:if>
<c:if test="${!ifMarried}">
xxx没有结婚了
</c:if>
<%--c:choose 相当于java中的switch语句,一般配合c:when来使用--%>
<c:choose>
<c:when test="${weekDay==1}">星期一</c:when>
<c:when test="${weekDay==2}">星期二</c:when>
<c:when test="${weekDay==3}">星期三</c:when>
<c:when test="${weekDay==4}">星期四</c:when>
<c:when test="${weekDay==5}">星期五</c:when>
</c:choose>
<%--c:forEach 相当与 for(int a = 1;a<10;a+=2){System.out.println(a);}--%>
<c:forEach var="a" begin="1" end="10" step="2">
${a}
</c:forEach>
<%--items内可以放置集合等可以遍历的容器,varStatus表示循环变量的状态--%>
<c:forEach items="${items}" var="a" varStatus="b">
${a}---------${b.index}
</c:forEach>
</body>
JSON
java script object notation js对象的表示法,用来做网络中传输的一种格式,简洁,明了,不冗余,本质就是一串字符串
<script>
// JSON对象
// 值为可以为字符串,数字,布尔值,null,js对象,js数组
let user = {
"name":"zhangsan",
"age":18
}
// 转换成JSON字符串
let s = JSON.stringify(user);
alert(s);
// 取值 对象.键名
console.log(user.name);
//遍历
let school = ["清华","北大","西南石油"];
for (let i = 0; i < school.length; i++) {//fori
console.log(school[i]);
}
for (let x of school) {//forof
console.log(x);
}
for (const x in school) {//forin
console.log(school[x]);
}
</script>

java对象-->js对象
// 转换出来为一个js对象的json表达式
User user = new User();
user.setAge(15);
user.setName("moon");
System.out.println(user);
// 将java对象转换成js对象的方法
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(user1));

//list转换为一个js数组
ArrayList<String> strings = new ArrayList<>();
strings.add("aaa");
strings.add("bbb");
strings.add("ccc");
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(strings));
![]()
//转换出来为一个对象数组 User user1 = new User(); ArrayList<User> users = new ArrayList<>(); users.add(user); users.add(user1); ObjectMapper objectMapper = new ObjectMapper(); System.out.println(objectMapper.writeValueAsString(users));
![]()
//map转换出来为一个js对象
Map<String,String> map = new HashMap();
map.put("name","zhangsan");
map.put("age","zhangsan");
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(map));
![]()
Ajax
优点:异步,局部刷新
同步:浏览器对服务器发送请求,在等待服务器响应的过程中,什么都不能做
异步:浏览器不需要等待服务器响应,在等待服务器响应的过程中,可以做任何事
ajax使用
1.创建jsp页面,并引入jquery(在web目录下新建static目录,并将jquery放在该目录下)
2.页面中添加事件,在事件函数中使用ajax
<body>
<span>用户名:</span><input id="username" type="text" οnblur="userNameJudge()"><span id="usernameJudge"></span><br>
<span>密码:</span><input id="password" type="password"><br>
<button type="button" οnclick="login()">登录</button>
<script>
// 用于登录对账号密码的判断
function login() {
var username = $("#username").val();
var password = $("#password").val();
$.ajax({
// 请求的url(旅行的目的地)
url:"/ajaxServlet",
// 请的方式(出行方式)
type:"post",
// 请求携带的参数(同行人)
data:{
"username":username,
"password":password
},
// 返回时参数的格式
dataType:"json",
// 成功回调后执行的函数
// rs接收后端传送的数据,即response.getWriter().write(string);
success:function (rs) {
if (rs.code == 200) {
alert(rs.msg)
// 账号密码正确,跳转页面
location.href="/successful.jsp"
} else {
alert(rs.msg)
}
}
})
}
// 用于对用户名是否可用判断
function userNameJudge() {
var username = $("#username").val();
$.ajax({
url:"/usernameJudge",
type:"post",
data:{
"username":username,
},
dataType:"json",
success:function (rs) {
if (rs.code == 200) {
// 新增样式
$("#usernameJudge").css({'color':'green'});
// 新增内容
$("#usernameJudge").html(rs.msg);
} else {
$("#usernameJudge").css({'color':'red'});
$("#usernameJudge").html(rs.msg);
}
}
})
}
</script>
</body>
// 账号密码判断的servlet
@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
ResultInfo resultInfo;
if ("zhangsan".equals(username)) {
if ("123456".equals(password)) {
// 密码正确,封装信息
resultInfo = new ResultInfo(200,"登录成功",null);
} else {
resultInfo = new ResultInfo(500,"密码错误",null);
}
} else {
resultInfo = new ResultInfo(500,"账号不存在",null);
}
// 将封装好的信息通过json格式传递给前端
ObjectMapper objectMapper = new ObjectMapper();
String string = objectMapper.writeValueAsString(resultInfo);
response.getWriter().write(string);
}
}
// 新建一个结果类ResultInfo
public class ResultInfo {
// 自己定义的状态码
private Integer code;
// 响应信息
private String msg;
// 响应的数据
private Object data;
(有参无参构造方法)
(get和set方法)
(toString方法)
}
Maven
概念
Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。
核心功能
Maven的核心功能是合理叙述项目间的依赖关系,通俗点就是通过pom.xml文件的配置获取jar包不用手动的去添加jar包
Maven坐标
-
groupId:Maven项目隶属的实际项目 -
artifactld:当前项目的模块名称 -
version:当前模块的版本
仓库
当maven项目需要jar包时,第一时间寻找本地仓库中的jar包,当本地仓库没有需要的jar包时,就会在中央仓库寻找,但当配置了私服时,会优先前往私服寻找,私服中没有,才会去中央仓库中寻找
maven项目结构

lifeCycle插件
1.clean
用于清除之前构建生成的所有文件
其中具体为清除Target目录中的所有文件,包括该目录
删除了install生成的所有文件
2.compile
编译项目的源代码,主要是java文件
一般是编译scr/main/java或是scr/test/java里面的文件
3.deploy
复制最终的包至远程仓库
共享给其它开发人员和项目
该博客围绕Servlet和JSP展开,介绍了Servlet的生命周期、Request和Response的乱码问题及操作、Cookie和Session的使用、ServletContext和Filter过滤器等。还涉及JSP的脚本、指令和内置对象,以及MVC、El表达式、JSTL、JSON、Ajax和Maven等相关知识。

3万+

被折叠的 条评论
为什么被折叠?



