一、javaweb服务器
1.1、服务器
就是一段应用程序,类似于是一个装代码的容器。我们可以将可执行的代码放到这存放到容器中,当用户向服务器发送请求时,服务器就会自动去根据请求调用对应的代码来执行。
1.2、服务器的种类
apatch nginx iis **tomcat**。tomcat:使用java语言开发的服务器。
1.3、tomcat安装
步骤:
1、将压缩包解压到无中文无空格的目录下即可。
2、配置环境变量
3、将mysql的驱动包放在lib目录中
tomcat目录
bin: 可执行的脚本
conf : tomcat配置文件所在的目录
lib: tomcat运行过程中需要使用到的第三方依赖所在的目录
logs: tomcat运行时产生的日志文件所在的目录
temp: tomcat运行时产生的临时文件存储目录
webapps: web项目的部署目录
work: 项目的工作目录
二、WEB项目的常见架构
2.1、CS
c:client(客户端)
s:server(服务端)
特点是:如果客户需要使用系列的话,需要先下载客户端才可以使用。
优点:客户端和服务器都是同一家公司开发的,客户端与服务端的数据交互时可以直接使用自己定义的格式,
缺点:客户端比较庞大时,下载时非常耗费资源,网络不好时,无法完成下载。。。。。。
2.2、BS
b:browser
s:server
特点时:无需下载专用的客户端,直接使用浏览器来代替客户端。
优点:不耗费资源
缺点:浏览器与服务端进行数据交互时,服务端无法直接处理浏览器发送过来的数据。
三、协议
用于规范浏览器和服务端数据交互的格式。
3.1、HTTP协议:
超文本传输协议 hyper text transfer protocal,是一个简单的请求-响应协议。
HTTP请求格式

请求行 :
请求头:以键值对的形式出现
空行
请求正文:
GET:没有请求正文,原因是用户提交的参数会拼接在URL上,再传递到后台服务器。
POST:就会存在请求正文。
HTTP响应格式

响应状态码

常见错误响应状态码
400-499 客户端错误响应
- 400 Bad Request: 请求语法有问题,服务器无法识别:没有host请求头字段,或者设置了超过一个的host请求头字段。
- 401 UnAuthorized: 客户端未授权该请求。缺乏有效的身份认证凭证,一般可能是未登陆。登陆后一般都解决问题。
- 403 Forbidden: 服务器拒绝响应。权限不足。
- 404 Not Found: URL无效或者URL有效但是没有资源。
- 405 Method Not Allowed: 请求方式Method不允许。
- 406 Not Acceptable: 资源类型不符合服务器要求。
- 407 Proxy Authorization Required: 需要代理授权。
- 408 Request Timeout:服务器将不再使用的连接关闭。响应头会有Connection: close。
426 Upgrade Required: 告诉客户端需要升级通信协议。
500-599 服务器错误响应
500 Internal Server Error: 服务器内部错误,未捕获。
- 502 Bad Gateway: 服务器作为网关使用时,收到上游服务器返回的无效响应。
- 503 Service Unavailable: 无法服务。一般发生在因维护而停机或者服务过载。一般还会伴随着返回一个响应头Retry-After: 说明恢复服务的估计时间。
- 504 Gateway Timeout: 网关超时。服务器作为网关或者代理,不能及时从上游服务器获取响应返回给客户端。
- 505 Http Version Not Supported: 发出的请求http版本服务器不支持。如果请求通过http2发送,服务器不支持http2.0,就会返回该状态码。
3.2、URI和URL
URI:统一资源标识符
作用:用于标识互联网上的某一份资源的名称
ftp://资源名称
public://资源名称
public://a.png
URL:统一资源定位符
URL是URI的子集,比URI更为强大。不光可以标识资源名称,还指定了访问对应资源的路径。
标准的URL: http://192.168.120.136:8098/a.png
ip+port是可以定位一台设备上某个应用程序。
ip:用于唯一标识互联网上的物理设备
port:用于确定设备上的应用程序
四、入门案例
如何在idea中创建web项目?


4.1、servlet
web项目的三大组件之一
三大组件:servlet(重点) filter listener
作用:接收请求,作出响应。
Servlet是一个接口,该接口有一个实现类GenericServlet,GenericServlet有一个子类HttpServlet(重点)
创建servlet的步骤:
1、创建一个类,继承HttpServlet
2、重写service()
public class LoginServlet extends HttpServlet {// @Override// protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// System.out.println("do something .......");// }// @Override// protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//// doGet(req,resp);// System.out.println("do something .......");// }/*** 重写service(),可以处理任何类型的请求方式* @param req* @param resp* @throws ServletException* @throws IOException*/@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// super.service(req, resp);System.out.println("do something .......");}}
3、在web.xml中配置servlet
<!--servlet的配置--><servlet><servlet-name>loginServlet</servlet-name><servlet-class>com.woniuxy.servlet.LoginServlet</servlet-class></servlet><servlet-mapping><servlet-name>loginServlet</servlet-name><!-- http://localhost:8080/login --><url-pattern>/login</url-pattern></servlet-mapping>
servlet的三种创建方式
1、继承HttpServlet
2、实现servlet接口

package com.woniuxy.servlet;import javax.servlet.*;import java.io.IOException;public class ServletInterface implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("实现了servlet接口创建的servlet在处理请求");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}}
3、继承GenericServlet
public class ServletExtendsGenericServlet extends GenericServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("ServletExtendsGenericServlet do something ....");}}
url-pattern的配置
<!--url-pattern用于匹配url中除去协议+ip+端口之后的内容url-pattern的值编写时,可以使用*通配符如果使用通配符,请注意*只能出现在最前或最后,不能出现在中间url-pattern的值编写方式有三种:精确匹配、前缀匹配、后缀匹配精确匹配:/user前缀匹配:/user/*后缀匹配:*.do匹配所有:/* 这种写法在servlet中是不会这么用的。url-pattern可以配置多个--><url-pattern>*.do</url-pattern>
生命周期
servlet的生命周期:
init():在servlet初始化时执行
destroy():在servlet销毁的时候执行
service():在servlet接收到请求时执行的
servlet的生命周期基于load-on-startup的配置与否,决定servlet初始化时机。
如果不配置,则servlet在第一次接收用户请求时,完成初始化
如果配置了,则在tomcat启动时,servlet就完成了初始化
load-on-startup的配置位置:在
<servlet><servlet-name>loginServlet</servlet-name><servlet-class>com.woniuxy.servlet.LoginServlet</servlet-class><!--<load-on-startup>的取值是非零整数,值越小,越先初始化--><load-on-startup>1</load-on-startup></servlet>
servletConfig
getServletConfig()用于获取当前servlet的配置信息对象ServletConfig,每个ServletConfig对象都代表当前servlet在web.xml文件中的配置信息,调用该对象的相应方法可以不必进行XML解析而直接获取对应配置信息。
ServletConfig
ServletConfig是一个接口,有4个方法:
- getServletName():获取
中的内容; - getServletContext():获取servlet上下文;
- getInitParameter(String name):获取servlet初始化参数,与
对应; - getInitParameterNames():获取所有初始化参数名称,返回的是一个集合(迭代器)。
<servlet><servlet-name>loginServlet</servlet-name><servlet-class>com.woniuxy.servlet.LoginServlet</servlet-class><!--<load-on-startup>的取值是非零整数,值越小,越先初始化--><init-param><param-name>a</param-name><param-value>1</param-value></init-param><init-param><param-name>b</param-name><param-value>2</param-value></init-param><load-on-startup>1</load-on-startup></servlet>
public class LoginServlet extends HttpServlet {@Overridepublic void init() throws ServletException {System.out.println("LoginServlet被初始化了");}@Overridepublic void destroy() {System.out.println("LoginServlet被销毁了");}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// super.service(req,resp);// System.out.println("do something......");//获取servletConfig对象ServletConfig config = getServletConfig();//获取servlet名称System.out.println(config.getServletName());//根据param-name的值去获取param-valueSystem.out.println(config.getInitParameter("a"));//获取所有param-name的值Enumeration<String> initParameterNames = config.getInitParameterNames();while (initParameterNames.hasMoreElements()) {String paramName = initParameterNames.nextElement();System.out.println(config.getInitParameter(paramName));}}}
解决控制台乱码:
4.2、HttpServletRequest
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>$Title$</title></head><body><form action="/login" method="post"><table><tr><td>用户名</td><td><input type="text" name="username"></td></tr><tr><td>密码</td><td><input type="password" name="password"></td></tr><tr><td colspan="2"><input type="submit" value="立即登录"></td></tr></table></form></body></html>
从请求行中获取数据
//获取请求行中的内容//返回的是请求的提交方式String method = req.getMethod();System.out.println(method);//获取协议String scheme = req.getScheme();System.out.println(scheme);//获取请求URIString requestURI = req.getRequestURI();System.out.println(requestURI);//获取请求的URLStringBuffer requestURL = req.getRequestURL();System.out.println(requestURL.toString());
从请求头中获取数据
//根据头的key去获取值String s = req.getHeader("Host");System.out.println(s);//获取所有请求头中的keyEnumeration<String> headerNames = req.getHeaderNames();while (headerNames.hasMoreElements()) {String headerName = headerNames.nextElement();System.out.println(req.getHeader(headerName));}
获取用户传递的参数(重点掌握)
//根据表单控件的name属性值或者url中?传参的参数名去获取对应的值String username = req.getParameter("username");String password = req.getParameter("password");System.out.println(username+":"+password);
4.3、HttpServletResponse
对响应对象进行相应的设置
package com.woniuxy.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 TestResponseServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//HttpServletResponse响应对象//设置响应状态码// resp.setStatus(400);//响应错误码//resp.sendError(400);// resp.sendError(400,"类型转换错误");//设置响应内容的类型resp.setContentType("text/html;charset=utf-8");//获取输出流PrintWriter writer = resp.getWriter();//通过输出流向浏览器写出内容writer.write("<h1>今天的天气真的不错,又不热又不冷。</h1>");//设置响应头信息,使用setHeader()对同一个key进行添加时,会覆盖resp.setHeader("a","1");resp.setHeader("a","2");resp.setHeader("a","3");resp.setHeader("a","4");//添加响应头信息,使用addHeader()对同一个key进行添加时,不会覆盖resp.addHeader("a","5");resp.addHeader("a","6");resp.addHeader("a","7");resp.addHeader("a","8");resp.setHeader("a","9");}}
4.4、BaseServlet
/*** 1、从请求参数中获取method的值* 2、根据method的值通过反射API生成Method对象* 3、调用invoke执行对应的方法,并对方法的返回值进行不同的处理。(指定不同的跳转方式)*/public class BaseServlet extends HttpServlet {/*** 假设请求的发送方式是:http://localhost:8080/user?mehtod=register* @param req* @param resp* @throws ServletException* @throws IOException*/@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String methodName = req.getParameter("method");//null ""System.out.println(methodName);if (null==methodName||"".equals(methodName)) {//用户未传递method参数或method参数未给值throw new RuntimeException("请求中未传递method参数,后台无法调用具体的方法来处理您的业务!");}try {//this:请求访问的是哪个servelt,这个this就是该servlet的对象Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);Object returnValue = method.invoke(this, req, resp);//对于返回值来说,如果为null,表示方法没有返回值(ajax)if (null==returnValue) {//对ajax请求的处理return ;}String methodReturnValue = (String) returnValue;if (methodReturnValue.contains(":")) {//如果返回值中有:存在,表示指定了跳转方式String[] values = methodReturnValue.split(":");String operation=values[0];//跳转方式String path=values[1];//跳转路径if (operation.equals("r")) {resp.sendRedirect(path);} else if (operation.equals("f")) {req.getRequestDispatcher(path).forward(req,resp);}else{throw new RuntimeException("您指定的跳转方式本系统尚不支持!!!");}}else{//如果没有,使用默认的跳转方式resp.sendRedirect(methodReturnValue);}} catch (Exception e) {e.printStackTrace();}}}
使用BaseServlet的要点:

4.5、JSP
java servlet pages,java服务端页面。本质上来说,JSP就是一个servlet。
jsp的执行原理:

JSP页面中可以出现的哪些内容:
html css js image java(小脚本、声明、注释、表达式…..)
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title><style>div{width: 200px;/*height: 200px;*/}</style></head><body><!--html注释在jsp页面中要编写java语句,应该使用以下的几种形式:--><%--jsp注释: 在jspServlet解析相应的jsp文件时,jsp注释是不会被解析的。--%><script>// var msg="abc";</script><%--小脚本 : _jspService(){} --%><%int i=0;System.out.println(i);%><%-- 表达式: 语法:<%= %> --%><%=i%><%-- 声明:语法:<%! %> 写在声明中的内容会以类的成员的形式出现--%><%!int x=1;public String getString(){return "今天星期一";}%><%=getString()%></body></html>
jsp指令
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ page import="com.woniuxy.domain.User" %><%@ include file="jspStudy.jsp"%><%-- 引入JSTL --%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><html><head><title>Title</title></head><body><%-- jsp页面中可以出现三种指令:page include taglib --%><%--page指令作用:用于对当前页面进行对应的一些设置。语法:<%@ page 参数列表 %>contentType:设置jsp页面的内容类型language:表示支持的语言pageEncoding:设置页面的字符编码集import:导包isELIgnored:用于指定当前JSP页面是否忽略EL表达式,一般情况下不会设置它,当页面中的EL表达不生效时,需要手动来指定--%><%User user = new User();%><%--include指令作用:用于引入外部资源语法:<%@ include 参数列表 %>--%><%--taglib指令作用:用于引入标签库,一般会使用该指令引入jtsl语法:<%@ taglib 参数列表 %>--%><c:out value="今天星期一,明天星期二"/></body></html>
4.6、EL表达式:
expression language:表达式语言。语法:${},**作用:用于从作用域对象中获取值。**
四大作用域
作用域对象:jsp有四大作用域对象
| 域对象 | 内置对象 |
|---|---|
| pageScope | pageContext |
| requestScope | request |
| sessionScope | session |
| applicationScope | application |
jsp的九大内置对象:
JSP九大内置对象
内置对象就是由JSP页面转译成的servlet的_jspService()方法中存在的几个对象。
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;final javax.servlet.ServletContext application;final javax.servlet.ServletConfig config;javax.servlet.jsp.JspWriter out = null;final java.lang.Object page = this;......
9大内置对象包括_jspService()的两个参数request和response,以及_jspService()方法中的pageContext、session、application、config、out、page和异常对象Exception。**pageContext**pageContext是页面上下文对象,封存了其他内置对象,封存了当前JSP的运行信息。每个JSP文件单独拥有一个pageContext对象,只在当前页面有效。
//通过pageContext对象调用对应的get***()方法可以获取其他内置对象。pageContext.getServletContext();
**session**session对象用来存储用户的不同请求的共享数据的。该对象可以通过page指令控制是否获取。**application**application就是ServletContext对象,一个项目只有一个。存储用户共享数据的对象,并完成其他操作。**config**config就是ServletConfig,主要是用来获取web.xml中的配置数据,完成一些初始化数据的读取。**out**out是响应对象,Jsp内部使用。带有缓冲区的响应对象,效率高于response对象。**page**page代表当前JSP的对象。**request**request存放了当前请求数据的对象。由tomcat服务器创建。一次请求**response**response是响应对象,用来响应请求处理结果给浏览器的对象。设置响应头,重定向。**exception**exception是异常对象,存储了当前运行的异常信息。

<%@ page import="com.woniuxy.domain.User" %><%@ page import="java.util.Arrays" %><%@ page import="java.util.HashMap" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title></head><body><%--el表达式:是用于从作用域对象中取值如果不指定作用域对象去获取,此时会从最小的域逐级向上查找,直到找到为止,如果到最后都没有找到,返回空字符串""作用域范围由小及大:页面域(pageScope)<请求域(requestScope)<会话域(sessionScope)<应用域(applicationScope)如果指定作用域获取,那么只在当前域中查找,没找到时直接返回"",不会向更大的域中去查找了。--%><%//向请求对象中保存了一个用户对象// request.setAttribute("user",new User("tom","111"));session.setAttribute("user",new User("jack","222"));request.setAttribute("nums", Arrays.asList(1,2,3,4));HashMap<String, String> map = new HashMap<>();map.put("a","1");map.put("b","2");map.put("c","3");session.setAttribute("map",map);%>${requestScope.user.username}<%--el表达式的运算符: . []“.”:如果域中存储的是某个类的对象,此时可以使用.运算符直接获取该类型的成员变量中存储的值“[]”:一般对应于集合元素的访问--%><hr>${nums[2]>10}<hr>${map["a"]}</body></html>
4.7、JSTL
JSTL(Java server pages standarded tag library,即JSP标准标签库)使用条件:
1、导入相应的jar包:jstl.jar, standard.jar
2、在jsp页面中,需要通过taglib指令引入jstl
<%@ taglib prifex="c" uri="http://java.sun.com/jsp/jstl/core"%>
作用:使用JSTL可以解决jsp页面中出现大量java代码导致可读性差的问题,使用了JSLT之后,jsp页面中就不会出现java代码,全部以标签的形式进行展示。
JSTL常用的标签:
<%@ page import="com.woniuxy.domain.User" %><%@ page import="java.util.Arrays" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><html><head><title>Title</title></head><body><%--jstl常用标签:--%><%--c:set:作用:用于修改域对象中存储的对象的属性值--%><%request.setAttribute("user",new User("tom","111"));request.setAttribute("nums", Arrays.asList(1,2,3,4,5,6));%><c:set target="${user}" property="username" value="jack"/><c:out value="${user.username}"/><hr><%--c:if:类似于java中的if--%><c:if test="${user.username.equals('tom')}"><c:out value="${user.username}"/></c:if><%--c:choose(switch)\c:when(case)\c:otherwise(default):类似于java中的switch--%><hr><c:choose><c:when test="${user.username.equals('tom')}"><c:out value="${user.username}"/></c:when><c:when test="${user.username.equals('jack')}"><c:out value="${user.username}"/></c:when><c:otherwise><c:out value="cici"/></c:otherwise></c:choose><%--c:foreach:遍历items:要被遍历的集合var:每次遍历从集合中获取的对象begin:从集合的哪个位置开始end:遍历到集合的哪个位置结束for(int i=0;i<nums.size();i++){nums.get(i)}--%><hr><c:forEach items="${nums}" var="num" begin="0" end="${nums.size()}"><c:out value="${num}"/></c:forEach><hr><%--c:remove:移除域对象中key--%><c:remove var="user"></c:remove><c:out value="${user.username}"/><hr><%--c:redirect:重定向--%><%-- <c:redirect url="login.jsp"></c:redirect>--%><hr><c:url value="/page/a.jsp"></c:url></body></html>
4.8、过滤器
web项目三大组件之一,执行在servlet之前。
应用场景:登录验证,统一字符编码设置,敏感字符过滤,权限验证等。
过滤器生命周期与tomcat保持一致,tomcat启动时会调用filter的init方法,关闭时调用destroy方法。
创建过滤器需要实现javax.servlet.Filter接口
/*** 实现了Filter接口的类,就会成为一个过滤器*/public class FirstFilter implements Filter {/*** 过滤器初始化时执行的方法* @param filterConfig* @throws ServletException*/@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("过滤器被初始化了");}/*** 过滤器执行过滤的方法* @param servletRequest* @param servletResponse* @param filterChain* @throws IOException* @throws ServletException*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//做一些逻辑处理,基于处理的结果决定请求要不要放行,如果放行,请求就会进入servlet中去//filterChain.doFilter(servletRequest,servletResponse);//放行}/*** 过滤器销毁时执行的方法*/@Overridepublic void destroy() {System.out.println("过滤器被销毁了");}}
配置过滤器
<!--配置过滤器--><filter><filter-name>firstFilter</filter-name><filter-class>com.woniuxy.filter.FirstFilter</filter-class></filter><filter-mapping><filter-name>firstFilter</filter-name><url-pattern>/user</url-pattern></filter-mapping>
也可以使用@WebFilter注解完成过滤器配置
@WebFilter("/user")
登录验证
登录验证分为两种场景:
1、未登录时,不允许访问系统中的任何资源
2、未登录时,不允许访问系统中的特定资源
两种不同场景下,登录验证的实现是不同的。
登录验证的实现:
1、登录成功时,通过session保存登录状态
2、在过滤器中通过session获取登录状态,如果值为空,表示未登录,应重定向到登录页面,不为空,放行请求即可。
验证特定资源需要登录:
/*** 登录验证的过滤器* url-pattern应该如何配置?* 对于静态资源是不必进行登录验证的,登录验证的是动态资源。*** 验证的是特定资源需要登录***/@WebFilter({"/cart.do","/order.do"})public class LoginFilter2 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;Object isLogin = request.getSession().getAttribute("isLogin");if (null == isLogin) {//为空,表示未登录response.sendRedirect("/login.jsp");} else {filterChain.doFilter(request, response);//如果有登录状态,则直接放行}}@Overridepublic void destroy() {}}
验证所有资源需要登录:
/*** 登录验证的过滤器* url-pattern应该如何配置?* 对于静态资源是不必进行登录验证的,登录验证的是动态资源。*** 验证所有资源都需要登录***///@WebFilter({"*.jsp","*.do"})public class LoginFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;//进行登录验证//有一些特定的资源是应该直接放行的:login.jsp user.doString requestURI = request.getRequestURI();//user.doif ("/login.jsp".equals(requestURI)||"/register.jsp".equals(requestURI)) {//如果访问的是login.jsp,则直接放行filterChain.doFilter(request,response);} else if ("/user.do".equals(requestURI)) {String method = request.getParameter("method");if (method.equals("login") || method.equals("register")) {filterChain.doFilter(request,response);}else{checkLoginStatus(request,response,filterChain);}}else {checkLoginStatus(request,response,filterChain);}}public void checkLoginStatus(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws IOException, ServletException {//其余的资源就应该进行登录验证:// 从session中去获取登录状态,如果登录状态存在,则放行,如果不存在,则重定向到登录页面。Object isLogin = request.getSession().getAttribute("isLogin");if (null == isLogin) {//为空,表示未登录response.sendRedirect("/login.jsp");} else {filterChain.doFilter(request, response);//如果有登录状态,则直接放行}}@Overridepublic void destroy() {}}
统一字符编码的设置
web.xml
<filter><filter-name>charsetFilter</filter-name><filter-class>com.woniuxy.filter.CharsetFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>charsetFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
过滤器charsetFilter
public class CharsetFilter implements Filter {private String encoding;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {String encoding = filterConfig.getInitParameter("encoding");if (null==encoding||"".equals(encoding)) {encoding="utf-8";}this.encoding=encoding;}/*** 字符编码设置* @param servletRequest* @param servletResponse* @param filterChain* @throws IOException* @throws ServletException*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;//进行字符编码设置request.setCharacterEncoding(encoding);response.setCharacterEncoding(encoding);//不是固定的东西,基于请求的方式进行不同的设置,今后如果发送的是ajax请求,这里的代码需要进行对应的修改。response.setContentType("text/html;charset="+encoding);filterChain.doFilter(request,response);}@Overridepublic void destroy() {}}
filter链的执行顺序
在开发过程中,建议:每个过滤器处理自己的逻辑即可,不要让过滤器存在依赖关系。
如果需要指定过滤器的执行顺序,根据过滤器的配置方式,有不同的设置。
1、web.xml
过滤器链的执行顺序由filter-mapping的配置顺序决定
2、注解配置
过滤器链的执行顺序由filtername的字母顺序来决定
敏感字符过滤
1、设定一些敏感词汇
2、请求中所有的用户提交的参数都应该进行敏感词汇的过滤
过滤器
@WebFilter("/word")public class WordFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//过滤请求参数的数据//1、设定敏感词汇List<String> words = Arrays.asList("sb","操","妈");//2、从请求中获取所有用户提交的参数HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;Enumeration<String> parameterNames = request.getParameterNames();//创建一个集合,用于保存进行了过滤之后的干净的字符串ArrayList<String> newStrs = new ArrayList<>();while (parameterNames.hasMoreElements()) {String parameterName = parameterNames.nextElement();String parameter = request.getParameter(parameterName);// 操场 妈妈叫你回家吃饭 好好学习for (String word : words) {if (parameter.contains(word)) {parameter = parameter.replace(word, "***");}}newStrs.add(parameter);}request.setAttribute("newStrs",newStrs);filterChain.doFilter(request,response);}@Overridepublic void destroy() {}}
servlet
@WebServlet("/word")public class WordServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { List<String> newStrs = (List<String>) req.getAttribute("newStrs"); System.out.println(newStrs); }}
4.9、listener(不是重点内容)
web三大组件之一,又称之为监听器。
作用:用于监听域对象(除pageContext以外)的创建和销毁,以及域对象当中的属性变化。
监听器分类:
第一类:监听域对象(除pageContext以外)的创建和销毁
第二类:监听域对象当中的属性变化 :setAttribute() removeAttribute()
req.setAttribute(“name”,”tom”) 对一个key的第一次赋值,对属性中进行新增操作
req.setAttribute(“name”,”jack”) 对同一个key的第二次或更多次赋值时,对属性进行修改操作
req.removeAttribute(“name”) 删除一个key,删除的属性
第三类:监听session域中的javaBean的属性变化。 仅作了解。
创建监听器
1、创建类,实现对应的监听器接口。
2、复写方法
3、配置监听器
第一类监听器
package com.woniuxy.listener;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.ServletRequestEvent;import javax.servlet.ServletRequestListener;import javax.servlet.annotation.WebListener;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;/*** 监听域对象的创建和销毁的*/@WebListenerpublic class MyListener implements HttpSessionListener, ServletRequestListener, ServletContextListener {/*** session对象创建时,执行sessionCreated* @param httpSessionEvent*/@Overridepublic void sessionCreated(HttpSessionEvent httpSessionEvent) {System.out.println("session被创建了");}@Overridepublic void sessionDestroyed(HttpSessionEvent httpSessionEvent) {System.out.println("session被销毁了");}@Overridepublic void contextInitialized(ServletContextEvent servletContextEvent) {}@Overridepublic void contextDestroyed(ServletContextEvent servletContextEvent) {}@Overridepublic void requestDestroyed(ServletRequestEvent servletRequestEvent) {}@Overridepublic void requestInitialized(ServletRequestEvent servletRequestEvent) {}}
第二类监听器
package com.woniuxy.listener;import javax.servlet.ServletContextAttributeEvent;import javax.servlet.ServletContextAttributeListener;import javax.servlet.ServletRequestAttributeEvent;import javax.servlet.ServletRequestAttributeListener;import javax.servlet.annotation.WebListener;import javax.servlet.http.HttpSessionAttributeListener;import javax.servlet.http.HttpSessionBindingEvent;/*** 监听域对象属性的变更*/@WebListenerpublic class AttributeListener implements HttpSessionAttributeListener, ServletRequestAttributeListener, ServletContextAttributeListener {/*** session对象第一次调用setAttribute()对某个key进行赋值操作时,监听器调用attributeAdded* @param httpSessionBindingEvent*/@Overridepublic void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {System.out.println("attributeAdded");}/*** session对象调用removeAttribute()对某个key进行移除操作时,监听器调用attributeRemoved* @param httpSessionBindingEvent*/@Overridepublic void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {System.out.println("attributeRemoved");}/*** session对象第二次或更多次调用setAttribute()对某个key进行赋值操作时,监听器调用attributeReplaced* @param httpSessionBindingEvent*/@Overridepublic void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {System.out.println("attributeReplaced");}@Overridepublic void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {}@Overridepublic void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {}@Overridepublic void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {}@Overridepublic void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {}@Overridepublic void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {}@Overridepublic void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {}}
监听器应用:
统计在线人数
创建监听器,实现httpsessionlistenter(统计在线人数增长)、servletcontextlistener(创建一个保存在线人数的变量)
统计在线登录人数
@WebListenerpublic class CountOnlineUser implements HttpSessionListener, ServletContextListener, HttpSessionAttributeListener {@Overridepublic void contextInitialized(ServletContextEvent servletContextEvent) {//servletcontext对象初始化时,向servletContext对象中保存一个存放在线人数的变量。ServletContext context = servletContextEvent.getServletContext();context.setAttribute("onlineUserNum",0);//在线人数context.setAttribute("onlineLoginUserNum",0);//在线登录人数}@Overridepublic void contextDestroyed(ServletContextEvent servletContextEvent) {}@Overridepublic void sessionCreated(HttpSessionEvent httpSessionEvent) {//从servletcontext对象获取在线人数的变量,并对其进行自增操作,然后重新设置回去ServletContext context = httpSessionEvent.getSession().getServletContext();Integer onlineUserNum = (Integer) context.getAttribute("onlineUserNum");context.setAttribute("onlineUserNum",++onlineUserNum);}@Overridepublic void sessionDestroyed(HttpSessionEvent httpSessionEvent) {}/**** @param httpSessionBindingEvent*/@Overridepublic void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {String name = httpSessionBindingEvent.getName();if (name.equals("isLogin")) {//在线登录人数就应该加一ServletContext context = httpSessionBindingEvent.getSession().getServletContext();Integer onlineLoginUserNum = (Integer) context.getAttribute("onlineLoginUserNum");context.setAttribute("onlineLoginUserNum",++onlineLoginUserNum);}}@Overridepublic void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {String name = httpSessionBindingEvent.getName();if (name.equals("isLogin")) {System.out.println("session中移除了isLogin");//在线登录人数就应该减一ServletContext context = httpSessionBindingEvent.getSession().getServletContext();Integer onlineLoginUserNum = (Integer) context.getAttribute("onlineLoginUserNum");context.setAttribute("onlineLoginUserNum",--onlineLoginUserNum);}}@Overridepublic void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {}}
4.10、ajax
Ajax:Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),本质上是一种浏览器端的技术。Ajax不是新的编程语言,而是一种使用现有标准(HTML / XHTML、CSS、JavaScript / DOM)的新方法。
作用:通过javascript域()向服务端发送请求,根据请求返回的结果,使用DOM来局部刷新部分网页。
优点:可以更方便和快速的对用户进行响应,用户体验会更好。
缺点:无法回退。
核心对象:XmlHttpRequest,请求由该对象向外发起,响应由该对象进行接收。
XmlHttpRequest的属性

XmlHttpRequest的方法

原生ajax的实现:
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title></head><body><div id="div" style="width: 400px;height: 400px;border: 1px solid black;"></div><input type="button" value="测试ajax请求" id="btn"><script>document.getElementById("btn").onclick=function () {var div = document.getElementById("div");//1、创建xmlhttprequestvar xmlHttpRequest = new XMLHttpRequest();//2、设置请求内容xmlHttpRequest.open("GET","/ajax.do?username=tom&password=111")//3、发送请求xmlHttpRequest.send(null)//4、处理响应,通过DOM操作局部刷新网页xmlHttpRequest.onreadystatechange=function () {if (xmlHttpRequest.readyState == 4) {//代表请求完成if (xmlHttpRequest.status == 200) {//根据不同的响应状态码进行不同页面刷新div.innerText=xmlHttpRequest.responseText}else if (xmlHttpRequest.status == 404) {div.innerText="404"}}}}</script></body></html>
ajaxservlet
@WebServlet("/ajax.do")public class AjaxServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(req.getParameter("username"));resp.getWriter().write("58期");}}
jquery的ajax操作
$.ajax()
%E6%96%B9%E6%B3%95%E9%80%9A%E8%BF%87%20HTTP%20%E8%AF%B7%E6%B1%82%E5%8A%A0%E8%BD%BD%E8%BF%9C%E7%A8%8B%E6%95%B0%E6%8D%AE%E3%80%82%E8%AF%A5%E6%96%B9%E6%B3%95%E6%98%AF%20jQuery%20%E5%BA%95%E5%B1%82%20AJAX%20%E5%AE%9E%E7%8E%B0%E3%80%82#card=math&code=.ajax%28%29%E6%96%B9%E6%B3%95%E9%80%9A%E8%BF%87%20HTTP%20%E8%AF%B7%E6%B1%82%E5%8A%A0%E8%BD%BD%E8%BF%9C%E7%A8%8B%E6%95%B0%E6%8D%AE%E3%80%82%E8%AF%A5%E6%96%B9%E6%B3%95%E6%98%AF%20jQuery%20%E5%BA%95%E5%B1%82%20AJAX%20%E5%AE%9E%E7%8E%B0%E3%80%82&id=Sn2cR).ajax() 返回其创建的 XMLHttpRequest 对象。ajax() 方法用于执行 AJAX(异步 HTTP)请求。所有的 jQuery AJAX 方法都使用 ajax() 方法。该方法通常用于其他方法不能完成的请求。
$.ajax(options)
参数options为一个javascript对象,该对象的属性包含了$.ajax()方法所需要的请求设置及回调函数等信息,以键值对形式存在,所有属性都是可选的。
下面的表格中列出了可能的属性(加粗部分为常用,必须掌握):
| 名称 | 值/描述 |
|---|---|
| async | 布尔值,表示请求是否异步处理。默认是 true。 |
| beforeSend(xhr) | 发送请求前运行的函数。 |
| cache | 布尔值,表示浏览器是否缓存被请求页面。默认是 true。 |
| complete(xhr,status) | 请求完成时运行的函数(在请求成功或失败之后均调用,即在 success 和 error 函数之后)。 |
| contentType | 发送数据到服务器时所使用的内容类型。默认是:”application/x-www-form-urlencoded”。 |
| context | 为所有 AJAX 相关的回调函数规定 “this” 值。 |
| data | 规定要发送到服务器的数据。 |
| dataFilter(data,type) | 用于处理 XMLHttpRequest 原始响应数据的函数。 |
| dataType | 预期的服务器响应的数据类型。 |
| error(xhr,status,error) | 如果请求失败要运行的函数。 |
| global | 布尔值,规定是否为请求触发全局 AJAX 事件处理程序。默认是 true。 |
| ifModified | 布尔值,规定是否仅在最后一次请求以来响应发生改变时才请求成功。默认是 false。 |
| jsonp | 在一个 jsonp 中重写回调函数的字符串。 |
| jsonpCallback | 在一个 jsonp 中规定回调函数的名称。 |
| password | 规定在 HTTP 访问认证请求中使用的密码。 |
| processData | 布尔值,规定通过请求发送的数据是否转换为查询字符串。默认是 true。 |
| scriptCharset | 规定请求的字符集。 |
| success(result,status,xhr) | 当请求成功时运行的函数。 |
| timeout | 设置本地的请求超时时间(以毫秒计)。 |
| traditional | 布尔值,规定是否使用参数序列化的传统样式。 |
| type | 规定请求的类型(GET 或 POST)。 |
| url | 规定发送请求的 URL。默认是当前页面。 |
| username | 规定在 HTTP 访问认证请求中使用的用户名。 |
| xhr | 用于创建 XMLHttpRequest 对象的函数。 |
$.ajax.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title><script type="text/javascript" src="/js/jquery-3.3.1.js"></script></head><body><form><table border="1" cellpadding="0" cellspacing="0"><tr><td>用户名</td><td><input type="text" name="username" id="username"></td><td></td></tr><tr><td>密码</td><td><input type="text" name="password" id="password"></td><td></td></tr><tr><td colspan="3"><input type="button" value="立即注册" id="btn"></td></tr></table></form><script>//需求:当用户名被输入完成后,失去光标时,则向后台发一次请求,验证当前用户名是否在数据库中存在//如果存在,在用户名的表单控件后的td中,给用户作出提示//onchange:表单控件内容发生了改变,并且失去了光标 onblur$(function () {$("#username").change(function () {//向后台发请求,并把当前控件的value值带过去。$.ajax({url:"/user.do",//url:请求提交的位置type:"GET", //type:请求提交的方式data:{username:$("#username").val()}, // data: 提交请求时附带的数据dataType:"text", //dataType:预期从服务器端返回的数据类型success:function (resp) {//resp就是封装了服务器响应回来的数据console.log(resp)$("#username").parent("td").next().html(resp)}})})})</script></body></html>
%E3%80%81#card=math&code=.get%28%29%E3%80%81&id=IaLvg).post()
%20%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8%20HTTP%20GET%20%E8%AF%B7%E6%B1%82%E4%BB%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%EF%BC%8C#card=math&code=.get%28%29%20%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8%20HTTP%20GET%20%E8%AF%B7%E6%B1%82%E4%BB%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE%EF%BC%8C&id=iwyN1).post() 方法使用 HTTP POST请求从服务器加载数据,这两个方法是在$.ajax()方法上做的封装,相当于直接固定了TYPE属性的值。
$.get(URL,data,function(data,status,xhr),dataType)
| 参数 | 描述 |
|---|---|
| URL | 必需。规定您需要请求的 URL。 |
| data | 可选。规定连同请求发送到服务器的数据。 |
| function(data,status,xhr) | 可选。规定当请求成功时运行的函数。 额外的参数: data - 包含来自请求的结果数据status - 包含请求的状态(”success”、”notmodified”、”error”、”timeout”、”parsererror”)xhr - 包含 XMLHttpRequest 对象 |
| dataType | 可选。规定预期的服务器响应的数据类型。 默认地,jQuery 会智能判断。 可能的类型:”xml” - 一个 XML 文档”html” - HTML 作为纯文本”text” - 纯文本字符串”script” - 以 JavaScript 运行响应,并以纯文本返回”json” - 以 JSON 运行响应,并以 JavaScript 对象返回”jsonp” - 使用 JSONP 加载一个 JSON 块,将添加一个 “?callback=?” 到 URL 来规定回调 |
$.post("/user.do",{username:$(this).val(),method:"register"},function (resp) { console.log(resp) },"json")
$.getJson()
$.getJson() 方法使用 HTTP GET请求从服务器加载数据,要求返回的值为JSON。
$.getJson(URL,data,function(data,status,xhr))
| 参数 | 描述 |
|---|---|
| URL | 必需。规定将请求发送到哪个 URL。 |
| data | 可选。规定连同请求发送到服务器的数据。 |
| function(data,status,xhr) | 可选。规定当请求成功时运行的函数。 额外的参数: data - 包含来自请求的结果数据status - 包含请求的状态(”success”、”notmodified”、”error”、”timeout”、”parsererror”)xhr - 包含 XMLHttpRequest 对象 |
$.getJSON("/user.do",{username:$(this).val(),method:"register"},function (resp) { console.log(resp) })
服务端响应JSON
1、导入fastJSON包
2、在程序中通过JSONObject对象的toJSONString()将对应的对象转换为json字符串。
User user = new User("jack", "222");resp.getWriter().write(new JSONObject().toJSONString(user));
MD5加密
特点1:
对同一个值进行md5加密时,得到的结果永远是相同的。
111 ==> gajoajalemhlakeyraemk
特点2:
加密结果不可逆。
package com.woniuxy.utils;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Base64;public class CommonsUtil { public static String md5(String password) throws UnsupportedEncodingException, NoSuchAlgorithmException { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] digest = md5.digest(password.getBytes("utf-8")); return Base64.getEncoder().encodeToString(digest); }}
五、项目相关功能
5.1、文件上传
开发人员可以使用Apache文件上传组件commons-fileupload来接收浏览器上传的文件,该组件由多个类共同组成,但是,对于使用该组件来编写文件上传功能的Java Web开发人员来说,只需要了解和使用以下三个类:
- ServletFileUpload:Apache文件上传组件的核心类,应用程序开发人员通过这个类来与Apache文件上传组件进行交互。
- FileItem:用来封装单个表单字段元素的数据,一个表单字段元素对应一个FileItem对象,通过调用FileItem对象的方法可以获得相关表单字段元素的数据。
FileUploadException:上传中产生的异常。
文件上传流程:
- 编写上传页面,form表单的enctype属性必须为”multipart/form-data”,提交方式必须为post;
- servlet中使用ServletFileUpload的isMultipartContent()判断请求消息中的内容是否是“multipart/form-data”类型,是则返回true,否则返回false。
- 返回结果为true,则基于DiskFileItemFactory工厂对象创建ServletFileUpload对象,并使用ServletFileUpload的parseRequest()解析请求,获取所有表单字段的数据集合List。
- 遍历数据集合,通过FileItem的isFormField()判断是否是普通表单字段,是则返回true,否则返回false(文件字段)。
如果FileItem是文件字段,使用FileItem的write()将文件写至指定存放地点即可。
在上传流程中,也可以使用ServletFileUpload的**setSizeMax**()设置上传文件大小,在上传操作完成后,一般会调用FileItem的**delete**()手动删除由于上传文件过大而产生的临时文件。
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title></head><body><form action="/upload.do" method="post" enctype="multipart/form-data">用户名:<input type="text" name="username" ><br>密码:<input type="text" name="password" ><br>头像:<input type="file" name="file" ><br><input type="submit" value="立即注册"></form></body></html>
serlvet
@WebServlet("/upload.do")public class UploadServlet extends HttpServlet {/*** 处理表单提交的数据* 如果有文件域,就应该做文件上传的相应处理。* @param req* @param resp* @throws ServletException* @throws IOException*/@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException{//先判断当前请求中是否存在文件上传boolean isMulti = ServletFileUpload.isMultipartContent(req);if (isMulti) {//做文件上传相应的处理try {//创建ServletFileUpload对象ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());//设置最大尺寸upload.setSizeMax(200*1024*1024);//解析请求,为第一个表单控件生成对应的fileItem对象List<FileItem> fileItems = upload.parseRequest(req);//fileItem的类型for (FileItem fileItem : fileItems) {if (fileItem.isFormField()) {String value = fileItem.getString("utf-8");System.out.println(value);}else{//执行上传操作//1、指定文件存储位置 文件服务器 文件系统下 web应用File target = new File("D:\\files");//2、处理文件的存储名称,解决同名文件被覆盖的问题String originName = fileItem.getName();String suffix = originName.substring(originName.lastIndexOf("."));String uploadFileName=UUID.randomUUID().toString().replace("-","")+System.currentTimeMillis()+ suffix;//生成要被上传的文件File uploadFile = new File(target, uploadFileName);fileItem.write(uploadFile);//上传}}} catch (Exception e) {e.printStackTrace();}}else{//如果不是,就进行普通的表单处理}}/*** 1、将前端设置好* form的method指定为post enctype指定为multipart/form-data* 在表单中提供文件域 <input type="file" name="file"/>* 2、在servlet中要去做的事情* 2.1 先判断是否是文件上传的请求 ServletFileUpload.isMultipartContent(req)* 2.2 返回值如果为true,表示是文件上传的请求,就需要解析请求:* 2.2.1 创建SevletFileUpload对象,使用带参构造创建,参数为DiskFileItemFactory对象* 2.2.2 设置上传请求的尺寸 upload.setSizeMax()* 2.2.3 解析请求 upload.parseRequest(req)* 2.2.4 遍历解析请求后返回的FileItem集合,使用isFormField()判断是否是文件字段(false)* 2.2.5 如果是文件字段,进行文件上传的处理 指定文件的存储路径 处理上传文件的存储名称 fileItem.write(file)完成上传。*/}
5.2、javaMail
协议:SMTP(可发可收) POP3(发送) IMAP(接收)
javaMail,sun公司为了方便程序员进行邮件开发写的一套API

程序开发中关心的是发送邮件的API,接收部分由邮件服务提供商进行处理。
要实现邮件发送,在程序中需要使用到三个javaMail的API类:Message(邮件),Session(定义环境),Transport(发送邮件)
javaMail开发实现
1、开发前的准备:
1.1注册邮箱帐号并登录
1.2点击设置,开启SMTP/POP3服务并保存授权密码
2、编写代码发送邮件
public class CommonsUtil {public static void sendMail(String sender,String password,String reciver,String subject,Object mailMsg) throws MessagingException {//通过3个对象将邮件发送出去//session message transport//设置邮件发送的相关环境Properties props = new Properties();props.setProperty("mail.transport.protocol","SMTP");props.setProperty("mail.host","smtp.163.com");props.setProperty("mail.smtp.auth","true");Authenticator authenticator=new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(sender,password);}};Session session = Session.getInstance(props,authenticator);//创建邮件对象,并设置邮件内容MimeMessage message = new MimeMessage(session);message.setContent(mailMsg,"text/html;charset=utf-8");//设置邮件的内容message.setSubject(subject);//设置邮件标题message.setRecipient(Message.RecipientType.TO,new InternetAddress(reciver));//设置收件人message.setFrom(new InternetAddress(sender));//设置发件人//发送邮件Transport.send(message);}}
javaMail在项目中的应用:
业务层
public class UserServiceImpl implements UserService {private UserMapper userMapper;public UserServiceImpl(){userMapper= MybatisUtil.getMapper(UserMapper.class);}//注册成功后(即向数据库完成了新增),向用户在注册时提供的邮箱中发激活邮件@Overridepublic boolean register(User user) throws MessagingException {int i = userMapper.insertUser(user);if (i>0) {//注册成功,向用户的邮箱中发送激活邮件CommonsUtil.sendMail("hjy15823115656@163.com","ZTDHHXXGVZBYQXJO",user.getEmail(),"用户激活","<a href='http://127.0.0.1:8080/user.do?method=active&activeCode="+user.getActiveCode()+"'>"+user.getActiveCode()+"</a>");return true;}return false;}//处理激活用户的业务,基于请求中传递的激活码进行数据库修改操作,将用户的状态修改为已激活@Overridepublic boolean active(String activeCode) {int i=userMapper.updateUserByActiveCode(activeCode);if (i>0) {return true;}return false;}}
mapper层
public interface UserMapper {@Insert("insert into t_user(name,password,email,activeCode) values(#{name},#{password},#{email},#{activeCode})")int insertUser(User user);@Update("update t_user set state=1 where activeCode=#{activeCode}")int updateUserByActiveCode(String activeCode);}
5.3、注册按钮
验证用户名和邮箱都没有被注册才移除注册按钮的disabled属性
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title><script type="text/javascript" src="/js/jquery-3.3.1.js"></script></head><body><form action="/user.do" method="post"><table><tr><td>用户名</td><td><input type="text" name="username" id="username"></td><td></td></tr><tr><td>密码</td><td><input type="password" name="password"></td><td></td></tr><tr><td>电子邮箱</td><td><input type="text" name="email" id="email"></td><td></td></tr><tr><td colspan="3"><input type="submit" id="register" disabled value="立即注册"><input type="hidden" name="method" value="register"></td></tr></table></form><script>$(function () {var checkUserName=false;var checkEmail=false;$("#username").change(function () {$.getJSON("/user.do",{username:$(this).val(),method:"checkUserName"},function (resp) {if (resp) {checkUserName=true;}else{checkUserName=false;}if (checkUserName & checkEmail) {$("#register").removeAttr("disabled")}else{$("#register").attr("disabled","disabled")}})})$("#email").change(function () {$.getJSON("/user.do",{email:$(this).val(),method:"checkEmail"},function (resp) {if (resp) {checkEmail=true;}else{checkEmail=false;}if (checkUserName & checkEmail) {$("#register").removeAttr("disabled")}else{$("#register").attr("disabled","disabled")}})})})</script></body></html>
5.4、相关代码
Category
@Datapublic class Category {private Integer id;private String name;}
CategoryController
@WebServlet("/category.do")public class CategoryController extends BaseServlet {public void findAll(HttpServletRequest request, HttpServletResponse response) throws IOException {response.setContentType("text/html;charset=utf-8");List<Category> categories = new CategoryServiceImpl().findAll();response.getWriter().write(new JSONObject().toJSONString(categories));}}
CategoryServiceImpl
public class CategoryServiceImpl implements CategoryService {private CategoryMapper categoryMapper;public CategoryServiceImpl(){categoryMapper= MyBatisUtil.getMapper(CategoryMapper.class);}@Overridepublic List<Category> findAll() {return categoryMapper.findAll();}}
CategoryMapper
public interface CategoryMapper {@Select("select * from t_category")List<Category> findAll();}
Goods
@Datapublic class Goods {private Integer id;private String name;private Double price;private String image;private Integer cid;}
GoodsController
/*** 处理商品相关的请求*/@WebServlet("/goods.do")public class GoodsController extends BaseServlet {public void findGoodsByCid(HttpServletRequest request, HttpServletResponse response)throws IOException {response.setContentType("text/html;charset=utf-8");String cid = request.getParameter("cid");String pageNum = request.getParameter("pageNum");Integer num=null==pageNum?1:Integer.valueOf(pageNum);PageInfo<Goods> pageInfo=new GoodsServiceImpl().findGoodsByCid(num,Integer.valueOf(cid));response.getWriter().write(new JSONObject().toJSONString(pageInfo));}// /**// * 分页查询// * @param request// * @param response// */// public String page(HttpServletRequest request, HttpServletResponse response) throws IOException {// response.setContentType("text/html;charset=utf-8");// PageInfo<Goods> pageInfo = getPageInfo(request, response);//// HttpSession session = request.getSession();// //如果session不存在商品分类信息,就去查询数据库,得到对应的商品分类信息// if (null==session.getAttribute("categories")) {// List<Category> categories = new CategoryServiceImpl().findAll();// session.setAttribute("categories",categories);// }//// session.setAttribute("pageInfo",pageInfo);// return "r:/page/main.jsp";//// response.getWriter().write(new JSONObject().toJSONString(pageInfo));// }//// public void pageAjax(HttpServletRequest request, HttpServletResponse response) throws IOException {// response.setContentType("text/html;charset=utf-8");// response.getWriter().write(new JSONObject().toJSONString(getPageInfo(request,response)));// }//// public PageInfo<Goods> getPageInfo(HttpServletRequest request, HttpServletResponse response){// String number = request.getParameter("pageNum");// String size = request.getParameter("pageSize");// String cid = request.getParameter("cid");// Integer pageNum = null== number ?1:Integer.valueOf(number);// Integer pageSize = null== size ?5:Integer.valueOf(size);// Integer id=null==cid?1:Integer.valueOf(cid);// PageInfo<Goods> pageInfo=new GoodsServiceImpl().findByPage(pageNum,pageSize,id);// return pageInfo;// }//// public String getGoodsById(HttpServletRequest request, HttpServletResponse response){//// String id = request.getParameter("id");//// Goods goods=new GoodsServiceImpl().findById(Integer.valueOf(id));//// request.getSession().setAttribute("goods",goods);//// return "r:/page/goodsInfo.jsp";// }}
GoodsServiceImpl
public class GoodsServiceImpl implements GoodsService {private GoodsMapper goodsMapper;public GoodsServiceImpl(){goodsMapper = MyBatisUtil.getMapper(GoodsMapper.class);}@Overridepublic PageInfo<Goods> findByPage(Integer pageNum,Integer pageSize,Integer cid) {PageHelper.startPage(pageNum, pageSize);List<Goods> goodsList = goodsMapper.findAll(cid);PageInfo<Goods> pageInfo = new PageInfo<>(goodsList);return pageInfo;}@Overridepublic Goods findById(Integer id) {return goodsMapper.findById(id);}@Overridepublic PageInfo<Goods> findGoodsByCid(Integer pageNum,Integer cid) {PageHelper.startPage(pageNum,3);List<Goods> goodsList = goodsMapper.findGoodsByCid(cid);PageInfo<Goods> pageInfo = new PageInfo<>(goodsList);return pageInfo;}}
GoodsMapper
public interface GoodsMapper {@Select("select * from t_goods where cid=#{cid}")List<Goods> findAll(Integer cid);@Select("select * from t_goods where id=#{id}")Goods findById(Integer id);@Select("select * from t_goods where cid=#{cid}")List<Goods> findGoodsByCid(Integer cid);}
main.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title><script type="text/javascript" src="/js/jquery-3.3.1.js"></script><style>*{margin: 0;padding: 0;}li{list-style: none;width: 80px;height: 160px;border: 1px solid black;float: left;margin-left: 20px;}ul:after{content: '';display: block;clear: both;}#categories>li{width: 120px;height: 60px;border: 1px solid black;float: left;margin-left: 50px;text-align: center;line-height: 60px;}#categories{width:516px;height: 62px;margin: 0 auto;}#categories:after{content: '';display: block;clear: both;}#goodsList>div{width: 150px;height: 240px;border: 1px solid black;margin-left: 20px;float: left;}#goodsList:after{content: '';display: block;clear: both;}</style></head><body><%--展示商品大类信息--%><div id="categories"></div><hr><div id="goodsList"></div><div id="pagequery"></div><script>$(function () {//页面加载完成,查询到商品大类信息并将之渲染到页面中$.getJSON("/category.do",{method:"findAll"},function (resp) {var $categories = $("#categories");for(var i=0;i<resp.length;i++){//resp[i] --->category{id,name}var $div = $("<div cid='"+resp[i].id+"'>"+resp[i].name+"</div>");$div.click(function () {var cid = $(this).attr("cid");//查询对应商品大类的商品信息$.getJSON("/goods.do",{method:"findGoodsByCid",cid:cid},function (resp) {var $goodsList = $("#goodsList");var $pagequery = $("#pagequery");$goodsList.html("")$pagequery.html("")for (var j=0;j<resp.list.length;j++){var $goodsInfoDiv = $("<div><img src='/"+resp.list[j].image+"'width='150' height='200'/><p>"+resp.list[j].name+"</p><p>"+resp.list[j].price+"</p></div>");$goodsList.append($goodsInfoDiv)}for (var k=1;k<=resp.pages;k++){var $pageNum = $("<div pageNum='"+k+"' style='width: 20px;height: 20px;border: 1px solid black;border-radius: 50%;'>"+k+"</div>");$pageNum.click(function () {var pageNum = $(this).attr("pageNum");$.getJSON("/goods.do",{method:"findGoodsByCid",pageNum:pageNum,cid:resp.list[0].cid},function (resp) {var $goodsList = $("#goodsList");$goodsList.html("")for (var j=0;j<resp.list.length;j++){var $goodsInfoDiv = $("<div><img src='/"+resp.list[j].image+"'width='150' height='200'/><p>"+resp.list[j].name+"</p><p>"+resp.list[j].price+"</p></div>");$goodsList.append($goodsInfoDiv)}})})$pagequery.append($pageNum)}})})$categories.append($div);}})// $("#categories>li").click(function () {// var cid = $(this).attr("cid");// $.getJSON("/goods.do",{method:"pageAjax",cid:cid},function (resp) {// console.log(resp)// var $goods = $("#goods");// $goods.html("");// for (var i=0;i<resp.list.length;i++){// $goods.append("<li>" +// " <img src='/"+resp.list[i].image+"' width='78' height='140'/>" +// " <p>"+resp.list[i].name+"</p>\n" +// " <p>"+resp.list[i].price+"</p>\n" + // " </li>")// }// })// }) })</script><%--展示某一个商品大类对应的商品信息--%><ul id="goods"><c:forEach items="${pageInfo.list}" var="goods" begin="0" end="${pageInfo.list.size()}"><li><%-- <a href="/goods.do?method=getGoodsById&id=${goods.id}">--%><img class="goodsImg" gid="${goods.id}" src="/${goods.image}" width="78" height="140"/><%-- </a>--%><p>${goods.name}</p><p>${goods.price}</p></li></c:forEach></ul><script>$(function () {$(".goodsImg").click(function () {//sessionStorage.setItem("id",$(this).attr("gid"));//html5 web存储location.href="goodsInfo.jsp?id="+$(this).attr("gid")})})</script><%-- <div id="content"></div>--%><%-- <div id="div"></div>--%><%--<script>--%><%-- // $(function () {--%><%-- //页面加载完成,向后台发送请求:查询商品信息--%><%-- // $.getJSON("/goods.do",{method:"page"},function (resp) {--%><%-- // console.log(resp)--%><%-- // var $content = $("#content");--%><%-- // for (var i=0;i<resp.list.length;i++) {--%><%-- // $content.append("<span>"+resp.list[i].name+"</span>")--%><%-- // }--%><%-- // for (var j=0;j<resp.pages;j++) {--%><%-- // var $input = $("<input class='pageIndex' type='button' value='"+(j+1)+"'/>");--%><%-- // $input.click(function () {--%><%-- // var pageNum = $(this).val();--%><%-- // $.getJSON("/goods.do",{method:"page",pageNum:pageNum},function (resp) {--%><%-- // console.log(resp)--%><%-- // })--%><%-- // })--%><%-- // $("#div").append($input)--%><%-- // }--%><%-- // });--%><%-- // })--%><%--</script>--%></body></html>

