标签 javaee 下的文章

小编今天发现在eclipse里面的WebContent里面不能新建文件夹了,也不知道进行了什么样的操作,肯定是点到了哪里了,一通乱点之后还是不行。。。。。。
然后自己直接去项目里面建立了一个文件夹,重新打开eclipse,果然出现了,只不过显示的样式不是文件夹,而是包,这是什么情况,可以使用吗???新建一个jsp页面瞅瞅。运行之后没有问题,可以使用,这肯定是eclipse的问题了,不行就充值吧,不舍的,配置了好多东西呢。。。
然后发现这个(WebContent)文件夹怎么这么眼熟呢,他也不是文件夹了,是包。好吧,把你取消掉。

操作方法:
右击当前的web工程,选择里面的属性或Build Path,点击里面仅有的一个选项,进去之后点击,Source,把你的WebContent,remove掉,然后保存就可以了,妥妥。

小编在新建了一个j2ee的项目之后,发现在里面新建的jsp页面都出现了"javax.servlet.http.HttpServlet" was not found on the Java Build Path的错误,我们不难发现,这句话是说javax.servlet.http.HttpServlet这个包找不到,很显然这个包属于tomcat的包,我们只需要把他导入到项目中就可以解决这个办法了。
解决办法:
右击当前的web工程,选择里面的属性或Build Path,找到Java Build Path->Libraries点击Add Libray...,然后点击Server Runtime ,最后选择你的Tomcat Server,然后保存就大功告成了。

jsp概述及原理

JSP全称是Java Server Pages,中文名叫java服务器页面,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。JSP实际上就是Servlet。可以理解为:jsp = html + java

注意:

  • servlet:服务器端的小应用程序。主要功能为:获取表单数据、处理业务逻辑、分发转向。
  • jsp:适合编写输出动态内容,但不适合编写java逻辑。

jsp的原理:jsp文件翻译称为.java文件;.java文件编译生成.class文件。

jsp的基本语法

JSP的脚本
小脚本 <% java代码 %>
表达式 <%= 表达式 %> 等价于out.print(表达式);
声明
<%!declaration; [ declaration; ]+ ... %> 表示在类中定义全局成员,和静态块。
JSP注释
JSP注释:<%-- 被注释的内容 --%> 特点:网页源代码中不可见。安全,省流量
网页注释: 特点:网页源代码中可见。不安全,费流量

jsp的3个指令

JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。

page指令
语法:
<%@ 指令名称 属性1="属性值1" 属性2="属性值2"...%>
或者:
<%@ 指令名称 属性1="属性值1"%>
<%@ 指令名称 属性2="属性值2"%>
如:解决中文乱码:

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

作用:用于定义JSP页面的各种属性
属性:(基本上使用默认的就行)

  • import 和java代码中的import是一样的
    比如:

    <%@ page import="java.util.Date,java.util.List"%>

    JSP会自动导入以下的包:

    import java.lang.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.jsp.*;
  • session: 是否会自动创建session对象。默认值是true。
  • buffer: JSP中有javax.servlet.jsp.JspWriter输出字符流。设置输出数据的缓存大小,默认是8kb。
  • errorPage: 如果页面中有错误,则跳转到指定的资源。
    errorPage="/uri" 如果写“/”则代表当前应用的目录下,绝对路径。如果不写“/”则代表相对路径。
  • isErrorPage: 是否创建throwable对象。默认是false。
  • contextType: 等同于response.setContextType("text/html;charset=utf-8")。
  • pageEncoding: 告诉JSP引擎要翻译的文件使用的编码。
  • isELIgnored: 是否支持EL表达式。 默认是false

include指令
静态包含:把其它资源包含到当前页面中。
<%@ include file="..." %>
动态包含:
<jsp:include page="..."></jsp:include>

两者的区别:
翻译的时间段不同
静态包含:在翻译时就把两个文件合并
动态包含:不会合并文件,当代码执行到include时,才包含另一个文件的内容。

原则:能用静态包含就不用动态包含。

taglib指令
作用:在JSP页面中导入JSTL标签库。替换jsp中的java代码片段。
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

jsp的6个动作

  • jsp:include 在页面被请求的时候引入一个文件。
  • jsp:useBean 寻找或者实例化一个JavaBean。
  • jsp:setProperty 设置JavaBean的属性。
  • jsp:getProperty 输出某个JavaBean的属性。
  • jsp:forward 把请求转到一个新的页面。
  • jsp:plugin 根据浏览器类型为Java插件生成OBJECT或EMBED标记。
  • jsp:element 定义动态XML元素
  • jsp:attribute 设置动态定义的XML元素属性。
  • jsp:body 设置动态定义的XML元素内容。
  • jsp:text 在JSP页面和文档中使用写入文本的模板。

JSP 隐式对象

JSP隐式对象是JSP容器为每个页面提供的Java对象,开发者可以直接使用它们而不用显式声明。JSP隐式对象也被称为预定义变量。及:指在JSP的<%=%> 和<% %>中可以直接使用的对象。

  • request HttpServletRequest类的实例。
  • response HttpServletResponse类的实例。
  • out JspWriter类的实例,用于把结果输出至网页上。
  • session HttpSession类的实例。
  • application ServletContext类的实例,与应用上下文有关。
  • config ServletConfig类的实例。
  • pageContext PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问。本身也是一个域对象:它可以操作其它三个域对象(request session application)的数据
  • page 类似于Java类中的this关键字。
  • Exception Exception类的对象,代表发生错误的JSP页面中对应的异常对象。
    附:四大域对象
  • PageContext : pageConext 存放的数据在当前页面有效,开发时使用较少。
  • ServletRequest: request 存放的数据在一次请求(转发)内有效。
  • HttpSession: session 存放的数据在一次会话中有效。使用的比较多。
  • ServletContext: application 存放的数据在整个应用范围内都有效,因为范围太大,应尽量少用。

会话概念

会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。简单的说就是,用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

Cookie

概念
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。由于cookie是由客户端浏览器保存和携带的,所以称之为客户端技术。
常用方法:

  • public Cookie(String name,String value)构造方法,传入cooke名称和cookie的值。
  • public int getMaxAge()返回该cookie的最长存活时间,以毫秒计。默认为-1,表明该cookie将persist(存留)直到浏览器关闭。
  • public String getName()取得Cookie的名字,名称不能唯一确定一个Cookie,因为路径可能不同。
  • public String getPath()返回浏览器返回该cookie到服务器的路径。cookie对于服务器上所有的子路径都是可见的。
  • public String getValue()取得Cookie的值。
  • public void setMaxAge(int expiry)设置Cookie的最大保存时间,即cookie的有效期,当服务器给浏览器回送一个cookie时。默认是-1(默认存在浏览器的内存中)单位是秒。负数:cookie的数据存在浏览器缓存中;0:删除。路径要保持一致,否则可能删错;正数:缓存(持久化到磁盘上)的时间。
  • public void setPath(String uri)设置浏览器返回该cookie的路径;默认值是写Cookie的那个程序的访问路径。不能存中文。
  • public void setValue(String newValue)设置Cookie的值。

注意:

  • 一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。
  • 一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。
  • 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
  • 如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。
  • 删除cookie时,path必须一致,否则不会删除。

Session

概念:
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。

常用方法:

  • request.getSession()获取Session对象,如果不存在就直接创建。
  • request.getSession(boolean create)获取Session对象,如果不存在就返回false。
  • getId()获取SessionId。
  • getCreationTime()获取当前session对象的创建时间。
  • getLastAccessedTime()获取最后一次访问该session对象的时间。
  • setMaxInactiveInterval()设置Session最大时效
  • getMaxInactiveInterval() 获取Session最大时效
  • invalidate()销毁当前Session对象
  • setAttribute()设置session属性
  • getAttribute()获得session属性
  • removeAttribute()移除session属性
  • getAttributeNames()

session实现会话过程数据共享的原理
Session是基于Cookie的、服务器创建每个session的时候,会为每个session分配一个ID号,即 JSESSIONID,服务器会以cookie的方式把session 的id号写给浏览器、所以session是基于cookie的。当浏览器再次访问的时候,会带着session id号的cookie过来 ,这就是session实现共享的原理。服务器写这个cookie的时候,是没有写有效期的,所以当浏览器关闭的时候,cookie也就没了,session也就结束了,即会话过程。

客户端禁用Cookie后的会话数据保存问题
客户端禁用cookie:浏览器永远不会向服务器发送cookie的请求消息头
解决方案:
方案一:在主页上给出提示,提示用户cookie异常。
方案二:URL重写。必须对网站的所有地址都重写。不以cookie的方式把JSESSIONID带给服务器,而是把JSESSIONID以url的方式带到服务器,即:URL重写,URL重写解决了禁用cookie后,Session的共享问题。
response.encodeURL(String url);该方法可以识别浏览器有没有发送cookie请求消息头,没有就重写URL,有就不重写。
前提request.getSession()必须写。

HttpServletRequest

请求消息行

方法:
getMethod(); 获得请求方式
getRequestURL();返回客户端发出请求时的完整URL。
getRequestURI(); 返回请求行中的资源名部分。
getContextPath(); 当前应用的虚拟目录 。
getQueryString() ; 返回请求行中的参数部分。

请求消息头

String getHeader(String name); 根据头名称得到头信息值
Enumeration getHeaderNames(); 得到所有头信息name
Enumeration getHeaders(String name); 根据头名称得到相同名称头信息值

请求正文

与获取表单数据相关的方法

getParameter(name) 根据表单中name属性的名,获取value属性的值方法
getParameterValues(String name)专业为复选框取取提供的方法
getParameterNames() 得到表单提交的所有name的方法
getParameterMap 到表单提交的所有值的方法 //做框架用,非常实用
附录:框架的使用

导入commons-beanutils-1.8.3.jar和commons-logging-1.1.1.jar包
import org.apache.commons.beanutils.BeanUtils;//导包
BeanUtils.populate(new User(), request.getParameterMap());//调用方法

getInputStream 以字节流的方式得到所有表单数据

ServletInputStream sis = request.getInputStream();
        int len = 0;
    byte[] b = new byte[1024];
    while((len=sis.read(b))!=-1){
        
        System.out.println(new String(b, 0, len, "UTF-8"));
    }
        
    sis.close();

与操作非表单数据相关的方法(request也是一个域对象)

void setAttribute(String name, Object value);
Object getAttribute(String name);
Void removeAttribute(String name);

与请求转发相关的方法

//得到请求转发或请求包含的协助对象

RequestDispatcher getRequestDispatcher(String path)
forward(ServletRequest request, ServletResponse response) //转发的方法
include(ServletRequest request, ServletResponse response) //请求包含

与请求编码相关的方法:

  • 解决post方式编码
    request.setCharacterEncoding("UTF-8"); //告诉服务器客户端什么编码,只能处理post请求方式
  • 解决get方式编码

    String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);

HttpServletResponse

响应消息行

setStatus(int sc) 设置响应状态码

响应头

sendRedirect(String location) 请求重定向
setHeader(String name, String value) 设置响应头信息

  • 告知浏览器使用什么码表

    response.setHeader("content-type", "text/html;charset=UTF-8");
    • 告知客户端不缓存
    response.setHeader("pragma", "no-cache");
    response.setHeader("cache-control", "no-cache");
    response.setDateHeader("expires", 0);
    • Referesh刷新

    响应正文(主体)

    getWrite(); 字符输出流
    getOutputStream(); 字节输出流
    setCharacterEncoding(String charset) 告知服务器使用什么编码
    setContentType(String type)

首先导入ValidateCode.jar包
jar包的下载可以关注小宁博客公众号

实现类

public class ServletDemo4 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //告诉客户端不使用缓存
        response.setHeader("pragma", "no-cache");
        response.setHeader("cache-control", "no-cache");
        response.setIntHeader("expires", 0);
        
        
        ValidateCode vc = new ValidateCode(110, 25, 4, 9);
        String code = vc.getCode();//得到生成的字符
        vc.write(response.getOutputStream());
        
    }
}

网页代码

网页代码

<script type="text/javascript">
    function changeCode(){
        //得到图片元素
        var img = document.getElementsByTagName("img")[0];
        //img.setAttribute("src","/day09_00_HttpServletResponse/servlet/demo");//XML Dom 语法
        img.src = "/day09_00_HttpServletResponse/servlet/demo?time="+new Date().getTime();
    }
</script>
<img src="/day09_00_HttpServletResponse/servlet/demo4" onclick="changeCode()"/>
<a href="javascript:changeCode()" >看不清换一张</a>

自己用servlet实现0-9验证码,并且点击刷新,但是不建议还用,可以直接使用jar包自动生成
详情请见:servlet实现验证码

实现类

public class Demo extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
  
        code();
    }

    
    private void code HttpServletResponse response) throws IOException {
        int width = 110;
        int height = 25;
        //在内存中创建一个图像对象
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        
        //创建一个画笔
        Graphics g = img.getGraphics();
        
        //给图片添加背景色
        g.setColor(Color.PINK);//设置一个颜色
        g.fillRect(1, 1, width-2, height-2);//填充颜色
        
        //给边框一个色
        g.setColor(Color.RED);
        g.drawRect(0, 0, width-1, height-1);//设置边框的显示坐标
        
        //设置文本样式
        g.setColor(Color.BLUE);
        g.setFont(new Font("宋体", Font.BOLD|Font.ITALIC, 15));
        
        //给图片添加文本
        Random rand = new Random();
        int position = 20;
        for (int i = 0; i < 4; i++) {
            g.drawString(rand.nextInt(10)+"", position, 20);//给图片填充文本
            position+=20;
        }
        
        //添加9条干扰线
        for (int i = 0; i < 9; i++) {
            g.drawLine(rand.nextInt(width), rand.nextInt(height), rand.nextInt(width), rand.nextInt(height));
        }
        //将图片对象以流的方式输出的客户端
        ImageIO.write(img, "jpg", response.getOutputStream());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

网页代码

<script type="text/javascript">
    function changeCode(){
        //得到图片元素
        var img = document.getElementsByTagName("img")[0];
        //img.setAttribute("src","/day09_00_HttpServletResponse/servlet/demo");//XML Dom 语法
        img.src = "/day09_00_HttpServletResponse/servlet/demo?time="+new Date().getTime();
    }
</script>
<img src="/day09_00_HttpServletResponse/servlet/demo4" onclick="changeCode()"/>
<a href="javascript:changeCode()" >看不清换一张</a>

通过servlet实现文件的下载,实例代码为下载一张jpg的图片

public class Demo extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //通过路径得到一个输入流
        String path = this.getServletContext().getRealPath("/WEB-INF/classes/img.jpg");
        FileInputStream fis = new FileInputStream(path);
        //创建字节输出流
        ServletOutputStream sos = response.getOutputStream();
        
        //得到要下载的文件名
        String filename = path.substring(path.lastIndexOf("\\")+1);
        
        //设置文件名的编码
        filename = URLEncoder.encode(filename, "UTF-8");//将不安全的文件名改为UTF-8格式
        
        //告知客户端要下载文件
        response.setHeader("content-disposition", "attachment;filename="+filename);
        response.setHeader("content-type", "image/jpeg");
        
        //执行输出操作
        int len = 1;
        byte[] b = new byte[1024];
        while((len=fis.read(b))!=-1){
            sos.write(b,0,len);
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

ServletConfig

1.可以获取servlet配置信息

public class ServletConfigDemo1 extends HttpServlet {
    /*private ServletConfig config;
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
    }*/
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
    /*String encoding = config.getInitParameter("encoding");//获得配置文件中的信息的
    System.out.println(encoding);*/
    //第二种方式
    String encoding = this.getServletConfig().getInitParameter("encoding");
    System.out.println(encoding);
    //第三种方式
    /*String encoding = super.getInitParameter("encoding");
    System.out.println(encoding);*/
}

       public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        doGet(request, response);
    }

}

2.可以获得ServletContext对象

ServletContext

ServletContext: 代表的是整个应用。一个应用只有一个ServletContext对象。单实例。
作用:
域对象:在一定范围内(当前应用),使多个Servlet共享数据。
常用方法:
void setAttribute(String name,object value);//向ServletContext对象的map中添加数据
Object getAttribute(String name);//从ServletContext对象的map中取数据
void rmoveAttribute(String name);//根据name去移除数据
作用

  • 获取全局配置信息

String getInitParameter(String name); //根据配置文件中的key得到value

  • 获取资源路径

String getRealPath(String path);//根据资源名称得到资源的绝对路径。可以得到当前应用任何位置的任何资源。

  • 实现Servlet的转发。
    RequestDispatcher getRequestDispatcher(String path);//参数表示要跳转到位置

Servlet的三种创建方式

实现javax.servlet.Servlet接口

public class ServletDemo implements Servlet{
    //Servlet生命周期的方法
    //在servlet第一次被访问时调用
    //实例化
    public ServletDemo(){
        
    }
    //Servlet生命周期的方法
    //在servlet第一次被访问时调用
    //初始化
    public void init(ServletConfig arg0) throws ServletException {
        
        
    }
    //Servlet生命周期的方法
    //服务
    //每次访问时都会被调用
    public void service(ServletRequest arg0, ServletResponse arg1)
            throws ServletException, IOException {
        
    }
    
    //Servlet生命周期的方法
    //销毁
    public void destroy() {
        
    }

    public ServletConfig getServletConfig() {
        
        return null;
    }

    public String getServletInfo() {
        
        return null;
    }

继承javax.servet.GenericServlet类(适配器模式)

public class ServletDemo extends GenericServlet{

    @Override
    public void service(ServletRequest arg0, ServletResponse arg1)
            throws ServletException, IOException {
        
    }

}

继承javax.servlet.http.HttpServlet类(模板方法设计模式)

public class ServletDemo3 extends HttpServlet{

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

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

注:解决线程安全问题的最佳办法,不要写全局变量,而写局部变量。