基础复习7-JSP&SERVLET&FILTER&LISTENER

SUN->JAVA->applet->servlet(server applet)->JSP

MS->J++(完全同java一样)

Windows->JRE

SERVLET:一段java代码(java类)

<applet></applet>由服务端发送.class给客户端,则要求客户端主机具备java运行环境(jre),最开始的时候windows系统预装了JRE,但是微软更改了java的协议侵权,之后不再更新jre且不再自带jre。所以applet程序推广受阻,SUN开发了servlet,在服务端解析成html静态页面给客户端。Servlet写HTML代码的方式:

 

Tomcat

tomcat是目前应用最为广泛的web容器,有java开发,可以运行jsp,servlet等javaweb应用

 

Bin:tomcat启动与停止等相关批处理命令

Conf:tomcat配置目录(常用配置:编码,端口,虚拟路径等)

Lib:tomcat运行,以及内部项目运行所依赖的插件包

Logs:tomcat运行日志存储目录

Temp:存放临时文件

Webapps:web应用存储的根目录(web程序都应该存放在该目录)

Work:tomcat运行web应用时的核心目录(java,class) 缓存目录

tomcat运行要求(tomcat是java开发的)

1.必须安装jre

2.配置javahome环境变量

 

访问tomcat管理界面的图形界面。

配置manager,设置tomcat用户

F:\Java\Apache\apache-tomcat-9.0.6\conf\tomcat-users.xml

       <role rolename="manager"/>

       <role rolename="manager-gui"/>

       <role rolename="manager-script"/>

       <role rolename="manager-jmx"/>

       <role rolename="manager-status"/>

  <user username="admin1" password="admin1" roles="manager-gui,manager-script,manager-jmx,manager-status,manager"/>

如何创建一个静态web应用(只是静态界面)

  1. 在webapps里创建一个文件夹mypro
  2. 在mypro里放入一个icheck.html文件
  3. 浏览器访问127.0.0.1:8080/mypro/icheck.html访问

如果页面里有输出语句,会在Tomcat服务器界面里输出出来

 

导包+编码:<%@ page import="java.util.*" pageEncoding="utf-8"%>

JSP(Java Server Pages:java服务页面,在html页面中嵌入java代码,使得静态html网页变为动态的页面)

运行原理:

首先,当客户端浏览器对于指定的jsp第一次访问时,web容器(Tomcat)会对jsp文件进行解析,解析为一个java类(实则是一个Servlet类)

然后,将Servlet类编译为字节码文件(*.class)

最后执行该servlet类,将数据通过HTTP协议发送到客户端浏览器

Work目录详解:

HTML文件浏览器可以直接解析,所以work中不存在html文件。存放JSP->.java(Servlet)->.class文件

 

Eclipse修改web项目视图模式

Windows->show view->other->package Explorer

通用设置JSP编码window->preference->jsp Files->utf-8

只有web容器才能识别<%@符号 %>

 

2.5版本的web项目,会有web.xml文件,3.0之后没有

三大指令:

Page:jsp页面的配置

Language:设置页面的脚本语言

contentType:响应数据的类型(text/html charset=utf-8)http协议

pageEncoding:页面的编码模式,jsp页面

import:导包

isErrorPage:必须加这个才能使用exception对象

errorPage:指定处理异常与错误的页面

isELIgnored:是否不解析EL表达式

Include:静态包含,把其他页面导入到当前页面同时解析

动态包含:把其他被包含的页面分别解析,各自生成java文件,然后再动态的导入主页面中。

<jsp:include page=”xx.jsp”></jsp:include>

Taglib:标记库

内置对象九个

  1. request:接受客户端的Http请求(接收表单form),包含客户端提交到服务器的数据等信息

a.跳转页面后要使request.getAttribute(“”)生效,request.getRequestDispatcher(“login.jsp”).forward(request, response);

   2.response:封装jsp产生的响应,服务端可以通过该对象向客户端进行响应(数据输出,页面跳转)

   3.session:用于保存用户的信息,跟踪用户(会话跟踪)。客户端与服务端的一次会话,默认30分钟有效时间。服务器与客户端之间可以通过该对象进行数据共享

  4.application:多个用户共享该对象,可用于计数器。表示Servlet上下文对象(servletContext,应用的运行环境),只要服务器不停止,会一直存在,所有客户端之间都能共享该对象。

  5.page:表示jsp对象,实际为this对象

  6.pageContext:jsp页面的上下文,能够在当前的jsp页面中临时共享数据

  7.out:是基于response获取的输出流对象,可以使用该对象向客户端输出数据(HTML代码)

  8.config:表示应用程序的配置对象。表示jsp对应的servlet信息,可以获取web.xml中的信息 

  9.exception:页面中的错误与异常,是Throwable的实例。

重定向与请求转发

  1. 重定向:response.sendRedirect(“main.jsp”);

<a href=”main.jsp”>重定向跳转</a>

a.由客户端发起第二次请求,所以重定向又称之为客户端跳转,在客户端地址栏上显示的为最后一次请求的资源

b.重定向无法将在存储在请求范围内(request)的数据传递到下一个页面中

 

2、请求转发:request.getRequestDispatcher(“main.jsp”).forward(request, response);

a.由服务器发起第二次请求,所以请求转发又称之为服务端跳转,在客户端地址栏显示的为第一次请求的资源

b.请求转发可以将请求范围内数据(request)向下继续传递,只要保持是一个request对象,始终能够获取到request的值。

 

四大作用域

pageContext域—(PageContext)

1、生命周期:当对JSP的请求时开始,当响应结束时销毁。  

2、作用范围:整个JSP页面,是四大作用域中最小的一个。  

作用:   

 1)获取其它八大隐式对象,可以认为是一个入口对象。   

 2)获取其所有域中的数据      

pageContext  操作所有域中属性的方法      

public java.lang.Object getAttribute(java.lang.String name,int scope)      

public void setAttribute(java.lang.String name, java.lang.Object value,int scope)      

 public void removeAttribute(java.lang.String name,int scope)            

 pageContext 中代表域的常量      

 PageContext.APPLICATION_SCOPE      

 PageContext.SESSION_SCOPE      

 PageContext.REQUEST_SCOPE      

 PageContext.PAGE_SCOPE   

 

request范围:(HttpServletRequest)

1、生命周期:在service 方法调用前由服务器创建,传入service方法。整个请求结束,request生命结束。  

2、作用范围:整个请求链(请求转发也存在)。  

3、作用:  在整个请求链中共享数据。最常用到:在Servlet 中处理好的数据交给Jsp显示,此时参数就可以放置在Request域中带过去。

session 域 (HttpSession)每一个客户端和服务端都会建立一个session,

   HttpSession 在服务器中,为浏览器创建独一无二的内存空间,在其中保存会话相关的信息。  

1、生命周期:在第一次调用 request.getSession() 方法时,服务器会检查是否已经有对应的session,如果没有就在内存  中创建一个session并返回。   

当一段时间内session没有被使用(默认为30分钟),则服务器会销毁该session。   

如果服务器非正常关闭(强行关闭),没有到期的session也会跟着销毁。   

如果调用session提供的invalidate() ,可以立即销毁session。   

 注意:服务器正常关闭,再启动,Session对象会进行钝化和活化操作。同时如果服务器钝化的时间在session 默认销毁时间之内,则活化后session还是存在的。否则Session不存在。  如果JavaBean 数据在session钝化时,没有实现Serializable 则当Session活化时,会消失。

 2、作用范围:一次会话。只要连接不断开(不关浏览器),对象session一直在

 3作用:保存登录的用户信息、购物车信息等

 

application(ServletContext)

1、生命周期:当Web应用被加载进容器时创建代表整个web应用的application对象,当服务器关闭或Web应用被移除时,application对象跟着销毁。  只要服务器运行,所有客户端共享。换浏览器都行

2、作用范围:整个Web应用。

3、作用:   

    a)application.setAttribute(“key”,Object value):存储整个web应用公用的数据

b)在不同Servlet 之间转发(不常用)    

  this.getServletContext().getRequestDispatcher("/servlet/Demo10Servlet").forward(request,

response);   

  方法执行结束,service就会返回到服务器,再有服务器去调用目标servlet,其中request会重新创建,并将之前的request的数据拷贝进去。      

注意:由于request对象也有getRequestDispatcher("**")方法,所有我们开发是通常使用request调用该方法实现重定向。

 c)读取资源文件。

1、由于相对路径默认相对的是java虚拟机启动的目录,所以我们直接写相对路径将会是相对于tomcat/bin目录,所以是拿不到资源的。如果写成绝对路径,当项目发布到其他环境时,绝对路径就错了。    

 

 2、为了解决这个问题ServletContext提供了:

  this.getServletContext().getRealPath("/1.properties"),给进一个资源的虚拟路径,将会返回该资源在当前环境下的真实路径。        

this.getServletContext().getResourceAsStream("/1.properties"),给一个资源的虚拟路径返回到该资源真实路径的流。    

 

(了解)3、当在非servlet下获取资源文件时,就没有ServletContext对象用了,此时只能用类加载器     

classLoader.getResourceAsStream("../../1.properties"),此方法利用类加载器直接将资源加载到内存中,有更新延迟的问题,以及如果文件太大,占用内存过大。     

classLoader.getResource("../1.properties").getPath(),直接返回资源的真实路径,没有更新延迟的问题。

 网站点击量:统计点击网站的个数

网站访问量:统计session的个数

findAttribute方法,在四大域中搜寻属性,搜寻的顺序是page域、request域、session域、application域,从小域到大域开始搜索,如果搜索到就直接获取该值,如果所有域中都找不到,返回一个null(el表达式不同,此处返回null,对网页是不友好的)      

 

HTML文件转换为JSP文件

 

  1. 检查是否有乱码,解决:右键properties->Text file encoding->Other(UTF-8)

    2.加指令<%@ page language="java" contentType="text/html;

charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true" %>

  3.改后缀为.jsp

 

四种会话跟踪技术(客户端与服务端连接过程中传输数据的通道)

1).表单隐藏域传值

input type="hidden">,非常适合步需要大量数据存储的会话应用。

2).URL 重写:

URL 可以在后面附加参数,和服务器的请求一起发送,这些参数为名字/值对。 见 http://blog.csdn.net/xh16319/article/details/8464055

实现:URL重写在客户端浏览器不支持Cookie(下章介绍)的情况下使用的,它是客户端浏览器请求服务器时,URL地址后面加上类似于 “SESSIONID=***”形式的参数,服务器端通过获取SESSIONID关键字来获取会话值。

action这样传不回去

Method=”post”浏览器网址输入栏看不到传递的值

3).Cookie:存在客户端本地

Cookie免登录:取出cookie值跳后台验证账号密码。如果密码错误跳转注销界面clear

Cookie注销:设置账号密码有效时间为0

一个 Cookie 是一个小的,已命名数据元素。服务器使用 SET-Cookie 头标将它作为 HTTP

响应的一部分传送到客户端,客户端被请求保存 Cookie 值,在对同一服务器的后续请求使用一个

Cookie 头标将之返回到服务器。与其它技术比较,Cookie 的一个优点是在浏览器会话结束后,甚至

在客户端计算机重启后它仍可以保留其值。 见:http://blog.csdn.net/xh16319/article/details/8464319

4).Session:

使用 session.setAttribute(String str,Object obj)方法将对象捆绑到一个会话

七大动作

 

EL表达式,简化jsp页面的java代码

1、标题处

isELIgnored="false"<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>

127.0.0.1:8080/examples/jspEL表达式的例子)

   

 

2、运用

新建对象

<jsp:useBean id="myGroup" class="com.wan.DTO.Group" scope="page"></jsp:useBean>

为对象设置属性
<jsp:setProperty name="myGroup" property="gname" value="武汉" />

<jsp:useBean id="myUser" class="com.wan.DTO.Emp" scope="page"></jsp:useBean>
<jsp:setProperty name="myUser" property="user_name" value="wan" />
<jsp:setProperty name="myUser" property="password" value="123" />
<jsp:setProperty name="myUser" property="registerTime" value='<%=new Date()%>' />
<jsp:setProperty name="myUser" property="group" value="${myGroup}" />

3、获取值

获得Attribute的值:

${requestScope.req}<br>
${sessionScope.ses}<br>
${applicationScope.app}<br>
${pageScope.pageMsg}<br>
${1+1}<br>
<jsp:getProperty name="myUser" property="registerTime" />||${myUser.registerTime}<br>
<jsp:getProperty name="myUser" property="group" />||${myUser.group}<br>
<jsp:getProperty name="myGroup" property="gname" />||${myUser.group.gname}<br>

获得parameter的值,实际就是form.jsp?uname=wan&pass=111

<c:out value="${param.uname}"></c:out><br>

<c:out value="${param.pass}"></c:out><br>

JSTL标准标记库

循环---<c:forEach

循环数字1-10:

<c:forEach begin="1" end="10" var="i">
    <c:out value="${i}"></c:out>
</c:forEach><br>

每次循环跳过指定个数:

<%--step跳过两个元素执行--%>
是否第一个===是否最末个===下标===序号===数值<br>
<c:forEach begin="11" end="20" var="i" step="2" varStatus="stat">
    <c:out value="${stat.first}  ======== ${stat.last} ==== ${stat.index} ==== ${stat.count} ==== ${i}"></c:out><br>
</c:forEach>

items循环-> parameter:

从form.jsp表单提交到main.jsp中。通过${paramValues.lang}获取值

链接:main.jsp?lang=C%2B%2B&lang=PHP&lang=RUBY&lang=PYTHON

循环结果:

Form.jsp

<form action="main.jsp">
    <input type="checkbox" name="lang" value="JAVA">JAVA
    <
input type="checkbox" name="lang" value="C++">JAVA
    <
input type="checkbox" name="lang" value="PHP">PHP
    <
input type="checkbox" name="lang" value="RUBY">RUBY
    <
input type="checkbox" name="lang" value="PYTHON">PYTHON
    <
button>提交</button>
</form>

 

Main.jsp

<c:forEach items="${paramValues.lang}" var="lang">
    <c:out value="${lang}"></c:out>
</c:forEach><br>

items循环->数组:

<%
   
String[] s = {"zzzz1","aaaa2","ssss3"};
    request.setAttribute(
"langs",s);
%>
<%--将值设置到request范围内--%>
<c:set var="langs" value="${requestScope.langs}" scope="request"></c:set>
<%--循环--%>
<c:forEach items="${requestScope.langs}" var="lang">
    <c:out value="${lang}"></c:out>
</c:forEach><br>

items循环->对象:

<%
   
ArrayList<User> list = new ArrayList<User>();
    list.add(
new User(1,"admin"));
    list.add(
new User(2,"wan"));
    list.add(
new User(3,"111"));
    list.add(
new User(4,"b222bb"));
    list.add(
new User(5,"3333"));
    request.setAttribute(
"users", list);
%>
<br>下标---name---id<br>
<c:forEach items="${requestScope.users}" var="u" varStatus="stat">
    <c:choose>
        <c:when test="${stat.count%2==0}">
            <span style="background-color: #f00">
                <c:out value="${stat.index}----${u.userName}----${u.id}"></c:out>
            </span><br>
        </c:when>
        <c:otherwise>
            <span>
                <c:out value="${stat.index}----${u.userName}----${u.id}"></c:out>
            </span><br>
        </c:otherwise>
    </c:choose>
</c:forEach>

forTokens循环->截取字符串:

<%
   
String str = "唐僧,孙悟空,猪八戒,沙悟净,白龙马";
    request.setAttribute(
"names", str);
%>
<c:forTokens items="${names}" delims="," var="name">
    <c:out value="${name}"></c:out><br>
</c:forTokens>

导入其他界面<c:import

<c:import url="form.jsp"></c:import>

为对象设置属性值<c:set

<%
   
User user = new User();
    request.setAttribute(
"user", user);
%>
<%--为一个对象设置属性值--%><br><br>
<c:set property="userName" target="${requestScope.user}" value="www"></c:set>

输出对象的属性值${requestScope.user.userName}

<c:out value="${requestScope.user.userName}"></c:out><br>

if----<c:if

<c:if test="${requestScope.user.userName == 'www'}">

    欢迎你,www

</c:if><br>

Switch case---<c:choose>

<c:choose>

    <c:when test="${requestScope.user.userName == 'admin'}">

        欢迎你,超级管理员

    </c:when>

    <c:when test="${requestScope.user.userName eq 'wan'}">

        欢迎你,普通管理员

    </c:when>

    <c:otherwise>

        欢迎你,普通用户1

    </c:otherwise>

</c:choose><br>

创建一个url  ${targetPath}= form.jsp? uname= WAN& pass=123456

<%--创建一个url并存储到page范围/form.jsp?uname=wan&pass=123456--%>

<c:url var="targetPath" value="form.jsp" scope="page">

    <c:param name="uname" value="WAN"></c:param>

    <c:param name="pass" value="123456"></c:param>

</c:url>
<c:out value="${targetPath}"></c:out>

重定向<c:redirect

<c:redirect url="${targetPath}"></c:redirect>

 

分页

思想:将页码 和每页数据条数作为参数传到后台查询数据,然后前端for循环输出数据。

用cp接受页码,下图是三个table同时分页互不影响

<%

    String flag = request.getParameter("flag");

    //初始化分页基本参数 

    //数据包

    int[][] data = (int[][])session.getAttribute("data");

    if (data == null)

       //当前页码currentPage、每页显示条数pageSize、总页数totalPage、总数据条数totalNum

       data = new int[][]{{1,6,0,0},{1,6,0,0},{1,6,0,0}};

    if (flag == null) {

       data[0][3] = new TestDAO1().getCount();

       data[1][3] = new TestDAO2().getCount();

       data[2][3] = new TestDAO3().getCount();

       int count = 4;

       //循环3  三个table同时分页互不影响

       for (int i = 1; i < count; i++){

           //获取总页数

           if (data[i-1][3] % data[i-1][1] == 0){

              data[i-1][2] = data[i-1][3] / data[i-1][1];

           }else {

              data[i-1][2] = data[i-1][3] / data[i-1][1] + 1;

           }

       }

       session.setAttribute("data", data);

    }else {

       //获取需要显示的页码

       String cp = request.getParameter("cp");

       if (cp != null) {

           if ("1".equals(flag)){

              data[0][0] = Integer.parseInt(cp);

           }else if("2".equals(flag)){

              data[1][0] = Integer.parseInt(cp);

           }else if("3".equals(flag)){

              data[2][0] = Integer.parseInt(cp);

           }

       }

       //检查数据合理性

       for(int i = 0; i < 3; i++){

           //防止无限上一页

           if (data[i][0] < 1){

              data[i][0] = 1;

           }

           //防止无限下一页

           if (data[i][0] > data[i][2]){

              data[i][0] = data[i][2];

           }

       }

       //获取分页数据

       if ("1".equals(flag)){

           List<POJO1> list = new TestDAO1().findAll(data[0][1], data[0][0]);

       }else if("2".equals(flag)){

           List<POJO2> list = new TestDAO2().findAll(data[1][1], data[1][0]);

       }else if("3".equals(flag)){

           List<POJO3> list = new TestDAO3().findAll(data[2][1], data[2][0]);

       }

       session.setAttribute("data",data);

     } 

 %>

List<Emp> list = dao.findAll(DBConnection_JDBC.getConn(), 6, 2);//每页6条第2

@Override
public List<Emp> findAll(Connection conn, int pageSize, int currentPage) {
   
return DAOHelper.execQuery(conn, "select user_id,user_name,sex,mobile,password,registerTime from emp limit ?,?", new DAOHelper.CallBack<Emp>() {
       
@Override
       
public List<Emp> getDatas(ResultSet rs)  {
            List<Emp> list =
new ArrayList<>();
            ResultSetMetaData rsmd =
null;
            Map map =
new HashMap();
           
try {
                rsmd = rs.getMetaData();
               
int count = rsmd.getColumnCount();
               
while (rs.next()){
                    String label;
                   
for (int i = 0; i < count; i++) {
                        label = rsmd.getColumnLabel(i+
1);
                        map.put(label, rs.getObject(label));
                    }
                    Emp e =
new Emp();
                    e.setUser_id(map.get(
"user_id") + "");
                    e.setUser_name(map.get(
"user_name") + "");
                    e.setSex(map.get(
"sex") + "");
                    e.setMobile(map.get(
"mobile") + "");
                    e.setPassword(map.get(
"password") + "");
                    e.setRegisterTime((Timestamp)map.get(
"registerTime"));
                    list.add(e);
                }
            }
catch (SQLException e) {
                e.printStackTrace();
            }
           
return list;
        }
    }, (currentPage-
1)*pageSize, pageSize);
}

 

 

JSP小知识点汇总:

1、<a href = ‘javascript:history.back()’>返回</a>    作用,回退

请求转发、a标签跳转、form提交都可以回退上一层,重定向会回到第一个重定向之前的界面。

2、<form action=”a.jsp” id=“f”></form>  <input type=”submit” value=“提交f表单”    form=”f”>submit提交指定表单

3、<%@ %>标签报错:

(1)、将web项目部署到服务器中

(2)、右键项目add Library->Server Runtime

4、<%! Int a = 10;%> 定义全局变量

 

Servlet+applet

以前服务器返回给客户端applet,需要客户端有jre。现在请求servlet,servlet做数据处理传给jsp,jsp返回客户端纯html代码。

运行在服务端应用程序,降低客户端对JRE依赖,客户端请求服务端时,只需通过servlet向客户端返回html元素即可在客户端浏览器中呈现效果以及数据;

同时Servlet也存在一定缺陷:对于后端开发人员要求精通前端技术(HTML,CSS,JS),所以才出现JSP技术

      

       Servlet处理jsp的请求,通过重定向或请求转发做操作。

       Servlet处理ajax请求,out.println(“<scripe>alert(‘hhh’);history.back()  </scriper>”);

                                           out.flush();

SERVLET创建步骤

* 1、创建普通类继承HttpServlet
* 2
、重写servicedoGet/doPost)方法
* 3、配置servlet(在web2.0中注册servlet

Servlet的请求流程

* 1、客户端请求指定的servleturl
* 2、系统会根据web.xml的配置找到对应的url-pattern
* 3
、根据url-pattern找到对应servlet-name
* 4
、进入到指定的servlet类执行service方法

 

Servlet生命周期(重点)

* 1、容器(Tomcat)启动后,对web.xml进行加载(解析),验证映射配置是否正确,如果映射异常则服务器会抛出异常
* 2web.xml成功加载之后,当客户端对指定servlet第一次发起访问时,容器会自动执行servletinit方法(只在第一次访问时执行)(先执行构造器)
* 3、容器会自动执行service方法,再根据客户端发起的请求(getpost)决定调用doGet/doPost完成相应的操作
* 4、当容器(服务器)停止服务时,servlet会执行destroy完成销毁操作。

 

Get与post区别

get:将提交到后台的数据拼接在请求地址中传递,而请求地址的长度不能超过1024字节(1kb),从而也决定无法使用get请求向后台提交大量数据,所以get请求通常用于向服务端请求数据(查询)以及提交少量数据

 

post:将提交到后台的数据封装在请求头中,在地址栏中不会显示提交的数据,请求头中一般没有大小限制,所以可以使用post提交向后台传递大量数据,包括文件数据,post请求通常做文件上传,涉及到安全性表单提交

 

405问题:客户端请求与服务端接受方式不一致

解决方案:

  1. 直接使用service方法
  2. doGet方法中调用doPost方法

获取对象session application:根据源码知道JSP九大内置对象类型

Servlet3.0基于注解的配置

Jdk1.5之后新增的类型,通过在类,属性,方法上添加注解标记实现一个特定的功能

 

Servlet3.0新增对注解支持,可以通过注解的形式声明servlet类,filter(过滤器),listener(监听器)

使用servlet3.0的基本要求:

1.jdk1.6+

2.Tomcat7.0+

 

Filter过滤器

在对项目中的资源发起请求的时候,可以通过配置的过滤规则,队请求的资源请求进行拦截,执行完过滤器中的逻辑之后,再根据过滤器的放行规则决定是否对请求的资源放行。

 

实现原理:基于java的设计模式之代理模式完成

过滤器的创建方式(3.0以下版本)

  1. 创建一个普通类实现Filter接口
  2. 实现接口中方法init,doFilter,destroy
  3. 在web.xml中配置过滤器
4、放行: chain. doFilter(request,response)u

登录拦截:

未登录不准进入某些界面,某些界面可免登陆进入

Init-param配置免登陆界面

获取免登陆请求名字:存在数组里

Filter基于注解的配置

 

监听器:(session,request,application各两个)

  1. 监听请求本身的    创建,销毁

设置session的有效时间

销毁session

 

  2.监听属性的           增删改

AJAX请求:自己包装的,直接调用。CallBack就是个回调函数,ajax方法里面调用了这个回调,相当于一个接口的未实现方法,在调用ajax方法时自己要写出该回调函数的具体实现。

调用ajax请求的方法:

 

 

ajax调用json格式数据:

function modifySt(){
    var labCode = $("#lab_code_i_9999").val();
    var stId = $("#st_id_i_9999").val();
    var stRegion = $("#stRegion_i_9999").val();
    var stBuilding = $("#stBuilding_i_9999").val();
    var stRoomno = $("#stRoomno_i_9999").val();
    var buildingCode = $("#building_code_i_9999").val();
    var buildingLevelCode = $("#building_level_code_i_9999").val();
    var roomOpen = 'Y';    //设置roomOpen的值,action中用request.getPramaeter获取
    
    var data = {    //json格式
        "labCode":labCode,
        "stId":stId,
        "stRegion":stRegion,
        "stBuilding":stBuilding,
        "stRoomno":stRoomno,
        "buildingCode":buildingCode,
        "buildingLevelCode":buildingLevelCode,
        "roomOpen":roomOpen
    };
    doAjaxFunc("modifySt.action", data, function(data){

        $("#modifyStDiv").dialog("close");
        var trObj = $("#inputTable").children("tbody").eq(0).children("tr");
        var len = trObj.length - 2;
        for(var i = 0; i < len; i++){
            trObj.eq(i + 2).remove();
        }
        showRegisteredLab(labCode);
    }, null);
}

servlet获取data数据:

public void modifySt(){
        Connection conn = null;
        conn = DBTools_w.getConnection();
        Map<String, String> map = new HashMap<String, String>();
        try {
            conn.setAutoCommit(false);
            String labCode = Global.ntrim(request.getParameter("labCode"));
            Integer stId = Integer.parseInt(Global.ntrim(request.getParameter("stId")));
            String stRegion = Global.ntrim(request.getParameter("stRegion"));
            String roomOpen = Global.ntrim(request.getParameter("roomOpen"));

            if(stRegion.equals("")){
                Global.setErrResult(map, "请选择校区");
                return;
            }

HTTP协议、

  1. 请求响应模式

客户端向服务端发起请求,

服务端响应客户端连接后断开

  1. 无状态连接

下一次请求与上一次请求没有关联,当前请求不知道上一次请求的操作

多文件上传:本质是从客户端拷贝到服务端

Enctype=”multipart/fort-data”以二进制流传递数据,无法用request.getParameter获得text的内容,获取方法:

Com.jspsmart.upload request = SmartUpload.getRequest();

Request.getParameter(“name”);

 

Servlet2.5基于以下插件:

Commons-fileUpload

SmartUpload:以二进制流的方式传递文件,中文文件名会变成随机uuid(根据mac地址和系统时间生成)。如果想保留中文名,则<@ page contentype=”text/html; charset=GBK” pageEncoding>改成GBK格式

多文件上传有两种实现方式,一种写多个label,一种加multiple属性

 

获取文件上传信息:files 和file导的包是com.jspsmart.upload

防止重名:java.io.File.separator  分隔符,防止跨平台

BASE_DIR = D:/FILE

Servlet3.0之后自带文件上传组件Commons-fileUpload

图片上传并显示图片

服务器传给客户端绝对路径,就可以访问到图片

上传Servlet:

/Iconlist   /iconlistServlet:

icoList.jsp

<%

       String base = request.getContextPath();

       //项目在服务器的绝对路径

       String basePath = request.getScheme()+”://”+request.getServerName+”:”+request.getServerPort()+path+”/”;

%>

文件下载

在服务端的文件路径

 

配置虚拟路径:

 

项目案例:用户注册并上传头像,服务器先接收图片,然后再存储到虚拟路径下。登录后能根据虚拟路径显示头像(数据库里存文件名)

注意:图片可能同名所以要重命名再存储在虚拟路径

1、先在Servers里面配置虚拟路径

2、接受上传头像 并重命名 下载到本地(虚拟)路径

  3、文件名存到数据库

  4、登录:

跳转main.jsp,显示头像

Commons-Fileupload与Commons-FileUpload的区别

Smartupload上传文件时,是直接将文件加载内存中,所以能够上传的文件大小与内存空间大小有直接关系,所以在上传大文件时很容易溢出,而且上传效率较低

 

Commons-Fileupload:是apache开源项目下子项目,能够提供稳定高效的文件上传功能,在上传文件时是利用磁盘的指定目录作为临时目录(在文件上传时不是一次性将文件加载的内存中),通过指定临时目录作为文件上传时的临时缓存目录,在上传完成之后会清空临时文件,目前common-fileupload作为推荐文件上传组件(struts2框架默认就支持,以及servlet3.0也直接将其作为一个模块纳入进来)

非servlet3.0的项目需要使用commons-fileupload时需要导入一下包:

commons-fileupload-1.3.3.jar

commons-io-2.5.jar

 

美化文件上传界面:默认很丑

Servlet代码:

文件下载:

bos.close()

 

导出excel:

 

 

 

 

表单重复提交

  1. 将表单提价方式改为post(不是最终解决方案)
  2. Token机制(令牌)

验证码:

防止用于通过技术手段恶意侵入网站,比如恶意注册,访问,下载.主要验证操作是否认为而非机器,提升网站安全性

1.字符验证码

2.图像验证码(噪点,干扰线..)

3.计算验证码

4.中文验证码

5.图片验证码(12306)

6.图像拖拽验证(极验验证)

 

使用Servlet生成验证码

1.Random类

2.GUI技术之图像处理

3.Servlet之response对象

实例:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

    <title>验证码</title>

    <style>

        #vcode{

            width: 100px;

            height: 40px;

            float: left;

        }

        #vcodeImg{

            border: 1px solid rgba(0,0,0,0.2);

            cursor: pointer;

        }

    </style>

</head>

<body>

    <input type="text" name="vcode" id="vcode" placeholder="验证码">

    <img alt="验证码" src="ValidateCode" id="vcodeImg">

    <button onclick="checkCode()">验证</button>

<script>

    $('vcodeImg').addEventListener('click',function () {

        //设置图片的src,为了防止页面缓存,每次向后台传递一个随机数

       this.src = 'ValidateCode?r='+Math.random();

    });

    function $(id) {

        return document.getElementById(id);

    }

    function checkCode() {

        ajaxGet('ValidateServlet?vcode='+$('vcode').value, function (data) {

            if (data == 1){

                alert('验证码输入正确');

            } else {

                alert('请输入正确的验证码');

            }

        });

    }

    function ajaxGet(url, callback) {

        //声明XMLHttpRequest

        var xhr;

        //判断浏览器获取XMLHttpRequest

        if (window.XMLHttpRequest){

            xhr = new XMLHttpRequest();

        }else {

            //IE5,IE6支持ActiveX插件

            xhr = new ActiveXObject('microsoft.XMLHTTP');

        }

        //打开连接  1.请求方式 2.服务端的资源地址 3.是否为异步提交

        xhr.open('get', url, true);

        //发送请求 当请求方式为post时,send方法需要写参数

        xhr.send();

        //当请求状态发生改变时,执行回调

        xhr.onreadystatechange = function(){

            //readyState:请求状态,status服务器响应状态

            if (xhr.readyState == 4 && xhr.status == 200){

                //获取服务端的响应数据

                var data = xhr.responseText;

                //将字符串类型的json数据转换为js对象

                //data = JSON.parse(data);

                //执行回调

                callback(data);

            }

        }

    }

</script>

</body>

</html>

 

ValidateCode

package com.wan;



import javax.imageio.ImageIO;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.awt.*;

import java.awt.image.BufferedImage;

import java.io.IOException;

import java.util.Random;



/*生成验证码*/

/*不设置响应头,直接返回图片显示出来*/

@WebServlet("/ValidateCode")

public class ValidateCode extends HttpServlet {

    private static final String CODES = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    //初始化验证码的宽度与高度

    private static final int WIDTH = 100;

    private static final int HEIGHT = 40;

    //初始化验证码字符数

    private static final int CODE_COUNT = 4;

    //初始噪点比例

    private static final double POINTS = 0.05;

    //干扰线的条数

    private static final int LINE_COUNT = 10;

    private Random random = new Random();

    @Override

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        doPost(req,resp);

    }



    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1.生成验证码的字符



        //2.生成图片

        BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

        //获取画笔

        Graphics g = img.getGraphics();

        //填充可绘制区域

        g.fillRect(0,0, WIDTH, HEIGHT);

        //创建字体

        Font font = new Font("黑体",Font.BOLD,20);

        //生命缓冲字符串 对象,存储生成的验证码

        StringBuffer buff = new StringBuffer();

        for (int i = 0; i < CODE_COUNT; i++) {

            //设置画笔颜色

            g.setColor(genClor());

            //设置字体

            g.setFont(font);

            //生成一个字符

            char c = genCode();

            //绘制字符到图像中

            g.drawString(c+"",i*20,20);

            //拼接到字符串中

            buff.append(c);

        }

        //添加噪点(干扰) 面积*0.2

        int area = (int)(WIDTH * HEIGHT * POINTS);

        for (int i = 0; i < area; i++) {

            g.setColor(genClor());

            int x = random.nextInt(WIDTH);

            int y = random.nextInt(HEIGHT);

            img.setRGB(x, y, genClor().getRGB());

        }

        //添加干扰线

        for (int i = 0; i < LINE_COUNT; i++){

            //随机设置画笔的颜色

            g.setColor(genClor());

            int xstart = random.nextInt(WIDTH);

            int xend = random.nextInt(WIDTH);

            int ystart = random.nextInt(HEIGHT);

            int yend = random.nextInt(HEIGHT);

            //绘制线段

            g.drawLine(xstart,ystart,xend,yend);



        }







        //3.通过输出流输出

        //设置响应数据的类型

        resp.setContentType("image/jpeg;");//MIME-Type

        //向页面段输出

        ImageIO.write(img,"JPG",resp.getOutputStream());

        //清除缓存(禁止浏览器缓存)

        resp.setHeader("pregam","No-cache");

        resp.setHeader("cache-control","No-cache");

        resp.setDateHeader("expire",0);



        //4.验证码缓存到session中

        System.out.println("验证码:"+buff);

        //验证码缓存到session中

        req.getSession().setAttribute("realCode",buff.toString());

    }



    //随机生成一个字符

    private char genCode() {

        return CODES.charAt(random.nextInt(CODES.length()));

    }



    //随机生成颜色

    private Color genClor(){

        return new Color(random.nextInt(256),random.nextInt(256),random.nextInt(256));

    }

}

ValidateServlet

package com.wan;



import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.io.PrintWriter;



@WebServlet("/ValidateServlet")

public class ValidateServlet extends HttpServlet {

    @Override

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        doPost(req, resp);

    }



    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取用户输入的验证码

        String vcode = req.getParameter("vcode");

        //取出session中的验证码

        String svcode = req.getSession().getAttribute("realCode")+"";

        PrintWriter out = resp.getWriter();

        System.out.println("实际验证码:"+svcode);

        System.out.println("用户输入的:"+vcode);

        out.print(svcode.equals(vcode) ? 1 : -1);

    }

}

 

一些个人理解:

Servlet会给客户端打印html代码,如果没有则显示空白。Jsp中的html代码最后都会通过out.println()发送给客户端。默认的Service方法会调用doGet方法,servlet在首次访问时被创建,然后调用init方法。服务器停止时才会调用destroy方法,servlet按照名字一次存储在有序map中依次销毁。

//设置请求头的编码方式
request.setCharacterEncoding("utf-8");
//设置响应数据流编码
response.setCharacterEncoding("utf-8");
//设置响应头的内容(包括响应数据格式,编码格式)
response.setContentType("text/html;charset=utf-8");

 

Servlet可以通过重定向和请求转发跳转,如果是响应ajax请求则不用跳转,或者用out.println向请求者返回html代码,例如:out.println("<script>alert('中文n');history.back();</script>");

out.flush();
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://JAVA.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <display-name>springMVC</display-name> <welcome-file-list> <welcome-file>/WEB-INF/jsp/login.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-mybatis.xml</param-value> </context-param> <filter> <filter-name>encodingFilter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value> </context-param> <context-param> <param-name>webAppRootKey</param-name> <param-value>keshe_C12_09.root</param-value> </context-param> <listener> <listener-class> org.springframework.web.util.Log4jConfigListener </listener-class> </listener> </web-app>
07-16

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值