Servlet基础

C/S B/S架构

C/S架构(Client/Server 客户端/服务器)
B/S架构(Browser/Server浏览器/服务器)

什么是Web

web是sun公司提供的用于开发动态Web的一门技术
常见的web服务器有:tomcat、jetty、resin
tomcat是apache提供的
bin:目录存放二进制文件
conf:目录存放配置文件
webapps:存放web项目
lib:存放依赖第三方包
logs:存放日志文件
temp:存放临时文件
work:存放运行时生成的文件

Tomcat

网页页面和web-INF同级,存放在web目录下
web-INF下的web.xml是配置文件
lib目录放在web-INF下
浏览器url:http://localhost:8080/

配置文件:

tomcat的xml选择2.5的需要手动配置
可以设置优先级load-on-startup
浏览器读取到访问路径为url-pattern
—)精确匹配 /url
—)后缀匹配*.xxx
—)通配符匹配/*
在mapping文件中找到servlet-name
通过servlet找到对应的servlet-name
通过servlet-name找到对应的Servlet类(全限定类名)

在这里插入图片描述

<servlet>
        <servlet-name>up_download</servlet-name>
        <servlet-class>Servlet_up</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>up_download</servlet-name>
        <url-pattern>/up_load</url-pattern>
    </servlet-mapping>

3.0以上的版本使用注解的方式

//Servlet文件
@WebServlet("/login")
public class ServletLogin extends HttpServlet {
//------------------------------------------
//html文件
<form method="post" action="login">
    用户名:<input type="text" name="uname"><br>
    密码:<input type="password" name="upwd"><br>
    <input type="submit" value="登录" ><br>
</form>

http以及抓包工具esclips中的tcp/ip-monitor

超文本传输协议
请求报文包括:请求行、请求头、空行、请求正文
响应报文包括:响应行、响应头、空行、响应正文
请求报文:
--------请求行 http协议 地址 方式
--------请求头 key-value
--------空行
--------请求正文 数据(post)
响应报文:
--------响应行 http协议 状态码
--------响应头 key-value
--------空行
--------响应正文 数据
常见的状态码
--------4开头客户端错误
--------5开头服务器错误

Servlet

需要导入jar包
Servlet是一个接口
需要进行idea部署tamcat和配置Servlet

Servlet接口
----下面有GenericServlet抽象类
-----------GenericServlet抽象类下有HttpServlet抽象类
----通常我们直接继承HttpServlet类
----可以通过implements实现Servlet接口或者继承HttpServlet类
-------------方法:init\destroy\service
------------------------doGet,如果 servlet 支持 HTTP GET 请求
------------------------doPost,用于 HTTP POST 请求
------------------------doPut,用于 HTTP PUT 请求
------------------------doDelete,用于 HTTP DELETE 请求

Get/Post请求

get请求,地址栏可以看到数据,地址栏或者a标签
传输的数据量小
不安全、效率高
对应doGet方法

post请求,地址栏看不到数据,form表单
可以传输较大的数据
安全,效率相对低
对应doPost方法

<form method="post" action="login">
    用户名:<input type="text" name="uname"><br>
    密码:<input type="password" name="upwd"><br>
    <input type="submit" value="登录" ><br>
</form>

页面里的文本框的名字用于在Servlet中使用req获取请求参数时,使用此名字去获取对应的数据

 @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /**
         * 设置编码得到参数用session传递
         */
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        //获取页面中姓名文本框里的数据
        String uname = req.getParameter("uname");
        //同理获取页面中密码框的数据
        String upwd = req.getParameter("upwd");
        //使用session作用域保存数据,request请求在一次请求中有效
        //session在一次服务器中有效
        HttpSession session = req.getSession();

        IManagerService iManagerService= new  ManagerServiceImpl();
        Manager manager = iManagerService.login(uname, upwd);
        if (manager!=null){
            session.setAttribute("manager",manager);
            req.getRequestDispatcher("showAll").forward(req,resp);
//            resp.sendRedirect("showAll");
        }else {
            resp.getWriter().println("<script>alert('登录失败,请重新登录');window.location='login.jsp'</script>");
//            resp.getWriter().println("<script>alert('用户名或密码错误'); window.location='login.jsp' </script>");
//            resp.sendRedirect("login.jsp");
        }



    }

解决乱码的问题:
------7版本以下 get、post请求都会出现乱码
-------------解决请求:
get 请求
将字符串拆解成getbyte 并且设置iso-8859-1
将得到的字节数组转回成字符串 设置编码为utf-8
post 请求
------------ 直接用req.setCharacterEncoding(“utf-8”);

------------解决响应:
---------resp.setContentType(“text/html;charset=utf-8”);
或者
【//设置响应编码格式为utf-8
-----response.setCharacterEncoding(“utf-8”);
-----response.setHeader(“ContentType”,“text/html;charset=UTF-8”);
----】

-------8版本以上,自动解决了get请求的乱码问题,只会出现post乱码
解决:
req.setCharacterEncoding(“utf-8”);
resp.setContentType(“text/html;charset=utf-8”);

请求转发

请求转发:request.getRequestDispatcher(“url路径”).forward(req,resp)跳转到用注解标识的Servlet类
一次请求中有效
通过req.setAttribute(key,value)保存数据
通过request.getAttribute(key);取数据

特点:
有作用域
服务器行为
只做了一次访问请求
浏览器地址不变
信息不会丢失可以进行数据传递
只能在同一个web应用中

重定向

response.sendRedirect(“目标URI”);
没有作用域
可以通过地址栏传数据 ?username=123&pwd=123
属于多次请求
地址栏发生变化
客户端行为
信息会丢失
可以访问外部路径

Servlet生命周期

实例化,只执行一次(设置优先级 可以优先实例化否则和初始化一起,但还是需要先实例化才能使用初始化init方法)
初始化调用init方法
服务service、doGet、doPost
销毁destroy
如果优先级为1,先实例化和初始化,浏览器访问时才调用service方法
如果默认优先级,则浏览器访问的时候才调用实例化初始化和service方法

线程安全问题

线程安全问题
解决方法1、同步代码块,安全但是效率低
方法2、ThreadLocal方式,效率高一点
方法3、作为局部变量放在doPost方法里
方法4、使用SingleThreadModel(不推荐使用)

public class UserServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	private String name;
	
	@Override
	public void init() throws ServletException {
		System.out.println("UserServlet.init()");
	}
	
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println(this);
		 name = Thread.currentThread().getName();
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"===>"+name);
	}
}  

Cookie

http是无连接的,cookie作为标识符帮助服务器识别用户端
cookie存放在本地,4K-8K的内容
具有时间限制(秒)
默认关闭浏览器就失效
服务器发送cookie给浏览器,通过域名和路径保存
cookie只能保存key-value的字符串

创建和使用
response.add 响应加cookie
request.get 请求获得cookie
同域名同路径同名的cookie会覆盖

//创建Cookie
		Cookie ck=new Cookie("code", code);
		ck.setPath("/webs");//设置Cookie的路径
		ck.setMaxAge(-1);//内存存储,取值有三种:>0有效期,单位秒;=0浏览器关闭;<0内存存储,默认-1
		response.addCookie(ck);//添加到response对象中,响应时发送给客户端
        //注意:有效路径: 当前访问资源的上一级目录,不带主机名
//获取所有的Cookie
Cookie[] cks=request.getCookies();
		//遍历Cookie
		for(Cookie ck:cks){
          //检索出自己的Cookie
			if(ck.getName().equals("code"))
			{
              //记录Cookie的值
				code=ck.getValue();
				break;
			}
		}

cookie的编码和解码(7版本以下中文会出现乱码),8以上解决了乱码问题
String name= URLEncoder.encode(“张三”,“UTF-8”);
Cookie cookie=new Cookie(“name”,name);
-----------------------------------------------------------------()
URLDecoder.decode(cc.getName(), “UTF-8”)

 // 使用中文的 Cookie. name 与 value 都使用 UTF-8 编码. 
    Cookie cookie = new Cookie(
        URLEncoder.encode("姓名", "UTF-8"), 
        URLEncoder.encode("张三", "UTF-8"));
    // 发送到客户端   
    response.addCookie(cookie);
 if(request.getCookies() != null){
        for(Cookie cc : request.getCookies()){
            String cookieName = URLDecoder.decode(cc.getName(), "UTF-8");
            String cookieValue = URLDecoder.decode(cc.getValue(), "UTF-8");
            out.println(cookieName + "=");
            out.println(cookieValue + "; <br/>");
        }
    }
    else{
        out.println("Cookie 已经写入客户端. 请刷新页面. ");
    }

Session作用域

底层是个cookie,是服务器创建的
一次会话中有效,可以发送多次请求,浏览器改变则session改变
默认浏览器关闭就失效
通过req.getSession()获取,然后用session的set、get方法赋值和取值
作用域:浏览器有效,可以任意跳转重定向访问
有不使用时的时间限制
超时session.setMaxInactiveInterval(seconds);//设置最大有效时间(单位:秒)
手工销毁,则失效session.invalidate();//登录退出、注销
getSessionId是cookie里的JssessionID

@WebServlet("/ServletSession")
public class ServletSession extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf8");
        response.setContentType("text/html;charset=utf8");
        String uname = request.getParameter("uname");
        String upwd = request.getParameter("upwd");
        //session和cookie都是浏览会话就结束
        //request是一次请求中有效
        //session是一次会话有效 服务器创建的
        HttpSession session = request.getSession();
        if ("admin".equals(uname)&&"123".equals(upwd)){
            //将值放入session域中
            session.setAttribute("user",uname);
        }else {
            response.getWriter().println("登录失败");
        }

        String id = session.getId();
        System.out.println("session的id"+id);
//        Object jsessionid = session.getAttribute("JSESSIONID");
//        System.out.println(jsessionid);
        Cookie cookie=new Cookie("name","admin");
        response.addCookie(cookie);


    }

外部直接访问localhost:8080/ServletIsLogin 显示未登录
进入页面登录,跳转到ServletSession的Servlet中进行操作,登录成功后将数据保存再session中,再次在ServletIsLogin中验证,如果确实登录成功,再次访问localhost:8080/ServletIsLogin时就会显示欢迎【"+user+"】登录

@WebServlet("/ServletIsLogin")
public class ServletIsLogin extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf8");
        HttpSession session = request.getSession();
        Object user = session.getAttribute("user");
        //判断是否把登录的信息存入到了session中以及对里面的值进行判断
        //直接访问这个网站 会显示没有登录,登录之后再访问 session有数据 能够共享
        //一次会话中有效即浏览器不关闭
        if (user!=null){
            response.getWriter().println("欢迎【"+user+"】登录");
        }else {
            response.getWriter().println("你还未登录,请先登录");
        }

    }

ServletConfig (了解)

可以在初始化的时候配置固定参数例如用户名和密码
两种方式
第一种通过注解给配置信息进行配置

@WebServlet(value = "/ServletSession",initParams = {
        @WebInitParam(name="uname",value = "admin"),
        @WebInitParam(name = "upwd",value = "123")}
)

ServletConfig来获取单个Servlet的配置信息
ServletContext获取全局的配置信息
方法二在配置文件中进行配置,每一个Servlet有对应一个ServletConfig 不用担心重名问题,全局配置用<context-param> 标签 与<servlet>标签并列

<servlet>
        <servlet-name>ServletSession</servlet-name>
        <servlet-class>ServletSession</servlet-class>
        //配置初始化信息 配置用户名和密码在这个servlet-class中
        	<init-param>
            	<param-name>name</param-name>
            	<param-value>admin</param-value>
        	</init-param>
        	<init-param>
            	<param-name>password</param-name>
            	<param-value>12345</param-value>
        	</init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>ServletSession</servlet-name>
        <url-pattern>/ServletSession</url-pattern>
    </servlet-mapping>

验证码的实现

导入第三方jar包 valicadeCode.jar

//引入第三方jar包 实现验证码 页面的img直接链接到此Servlet实现
        ValidateCode validateCode=new ValidateCode(200,30,4,10);
        String code = validateCode.getCode();
        System.out.println(code);
        //页面中显示验证码图形
        validateCode.write(response.getOutputStream());
        //将code保存在session域中
        HttpSession session = request.getSession();
        session.setAttribute("code",code);

ServletContext

作用域范围最大,服务器不关闭就始终有效
request、session、servletcontext都是当前Web项目内使用
request一次请求有效
session一次会话即一次浏览器有效
servletcontext当前服务器开启内有效
request、session、ServletContext都能获取到servletcontext

Filter过滤器

可以使用配置文件或者注解的方式设置一些可以改变的值
用config获取配置的信息
Servlet用<Servlet>配置
Filter用<Filter>配置
Listener用<Listener>配置
注意过滤条件,达到条件就放行chain.doFilter(request, response);
条件可以在请求时放在地址栏传递
容器启动时创建,关闭时销毁
uri传递的是较短的路径
url传递的是http开始的长路径

	<listener>
        <listener-class></listener-class>
    </listener>
    <filter>
        <filter-name></filter-name>
        <filter-class></filter-class>
    </filter>
@WebFilter(value = "/*",initParams = @WebInitParam(name = "encode",value = "utf8"))
public class EncodeFilter implements Filter {
    private static  String encode;
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request=(HttpServletRequest)req;
         HttpServletResponse response = (HttpServletResponse) resp;
        //对编码进行过滤
        request.setCharacterEncoding("utf8");
        response.setContentType("text/html;charset="+encode);
        //放行
        chain.doFilter(request, response);
    }

    public void init(FilterConfig config) throws ServletException {
          encode = config.getInitParameter("encode");
        System.out.println(encode);
    }

}

Listener监听器

可以对request、session、ServletContext进行创建销毁的监听和取值赋值的监听
注意加注解@WebListener

@WebListener
public class SessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("session注销了");
        ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
        ArrayList<String> list = (ArrayList<String>)servletContext.getAttribute("list");
        Object dName = httpSessionEvent.getSession().getAttribute("dName");
        list.remove(dName);
        System.out.println(list);
        System.out.println(dName);
       servletContext.setAttribute("list",list);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值