Servlet基础+过滤器,表单提交

参考:https://how2j.cn/k/servlet/servlet-eclipse/558.html?p=136471

Servlet 本身不能独立运行,需要部署在tomcat中

一、准备

1.tomcat配置 tomcat/conf/sever.xml

// 将url的根路径映射到web目录下,同时删除tomcat\webapps下的ROOT目录,可能会有冲突
<Context path="/" docBase="D:\\workspace\\j2ee\\web" debug="0" reloadable="true" />

2.项目目录结构
web目录,用来存放html页面
web/WEB-INF 存放配置文件 web.xml和class目录
web/WEB-INF/class 存放编译后的class文件
在这里插入图片描述

3.web.xml 提供路径与servlet的映射关系

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>HelloServlet</servlet-class>
        // 选填,表明该Servlet会随着Tomcat的启动而初始化,调用对应的init方法
        // 取值范围1-99,数字越小优先级越高
        <load-on-startup>10</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

二、示例

1.处理流程
浏览器请求到达Tomcat后,根据web.xml中的映射关系,定位到LoginServlet

发现并没有LoginServlet的实例存在,于是调用LoginServlet的public无参构造方法实例化一个LoginServlet对象

Tomcat拿到实例之后,根据请求的方式去调用对应的doPost或者doGet方法
在执行doGet()或者doPost()之前,都会先执行service(),由service()方法判断到底该调用doGet()还是doPost()
service(), doGet(), doPost() 三种方式的参数列表都是一样的,所以有时候也会**直接重写service()**方法,在其中提供相应的服务,就不用区分到底是get还是post了。

在Servlet完成工作之后,tomcat拿到被Servlet修改过的response,根据这个response生成html 字符串,然后再通过HTTP协议回发给浏览器

浏览器再根据HTTP协议获取这个html字符串,并渲染在界面上。

2.示例

public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");    // 涉及中文时进行编码转换
        String name = request.getParameter("name");
        String password = request.getParameter("password");
  
        String html = null;
        if ("admin".equals(name) && "123".equals(password))
            html = "<div style='color:green'>成功</div>";
        else
            html = "<div style='color:red'>失败</div>";
        
        response.setContentType("text/html; charset=UTF-8");  
        PrintWriter pw = response.getWriter();
        pw.println(html);
    }
}

3.生命周期
一个Servlet的生命周期由 实例化,初始化,提供服务,销毁,被回收 几个步骤组成
构造方法 只会执行一次,所以Servlet是单实例的

 public class LoginServlet extends HttpServlet {
 
    public LoginServlet() {
        System.out.println("LoginServlet 构造方法 被调用");
    }
 
    public void init(ServletConfig config) {
        System.out.println("init(ServletConfig)");
    }
 
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 略
    }
     
    public void destroy() {
        System.out.println("destroy()");
    }
}

4.request 常见用法

// 服务端跳转,将success.html的内容发给浏览器,浏览器中的url不变
request.getRequestDispatcher("success.html").forward(request, response);

request.getParameter(): 获取单值的参数
request.getParameterValues(): 用于获取具有多值的参数,比如注册时候提交的 "hobits",可以是多选的。
request.getParameterMap(): 用于遍历所有的参数,并返回Map类型。

request.getRequestURL(): 浏览器发出请求时的完整URL,包括协议 主机名 端口(如果有)" 
request.getRequestURI(): 浏览器发出请求的资源名部分,去掉了协议和主机名" 
request.getQueryString(): 请求行中的参数部分,只能显示以get方式发出的参数,post方式的看不到
request.getRemoteAddr(): 浏览器所处于的客户机的IP地址
request.getRemoteHost(): 浏览器所处于的客户机的主机名
request.getRemotePort(): 浏览器所处于的客户机使用的网络端口
request.getLocalAddr(): 服务器的IP地址
request.getLocalName(): 服务器的主机名
request.getMethod(): 得到客户机请求方式一般是GET或者POST

request.getHeader() 获取浏览器传递过来的头信息。 
比如getHeader("user-agent") 可以获取浏览器的基本资料,这样就能判断是firefox、IE、chrome、或者是safari浏览器
request.getHeaderNames() 获取浏览器所有的头信息名称,根据头信息名称就能遍历出所有的头信息

5.response 常用方法

PrintWriter pw= response.getWriter();  // 获取一个PrintWriter 对象
// 可以使用println(),append(),write(),format()等等方法设置返回给浏览器的html内容。
pw.println("<h1>Hello Servlet</h1>");

// 设置响应编码和格式
response.setContentType("text/html; charset=UTF-8");

response.sendRedirect("fail.html");  // 重定向

// 通知浏览器不要使用缓存
response.setDateHeader("Expires",0 );
response.setHeader("Cache-Control","no-cache");
response.setHeader("pragma","no-cache");

6.表单提交 带文件

public class UploadPhotoServlet extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response) {
        // ServletFileUpload是用来处理上传文件的,他需要一个FileItemFactory类型的参数
        // FileItemFactory是一个接口,DiskFileItemFactory是他的实现类
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);

        String newFileName = null;  // 花括号中定义的都是局部变量,想全局访问就申明在花括号外面
        try{
            // 浏览器以二进制的形式提交数据,request.getParameter("heroName")就无效了
            List items = upload.parseRequest(request);
            Iterator iter = items.iterator();
            while (iter.hasNext()){
                FileItem item = (FileItem)iter.next();
                String fieldName = item.getFieldName();  // 获取的是表单元素的name属性
                // 判断是否为常规字段,即普通的文本信息
                if(item.isFormField()){
                    String value = item.getString();  // 获取字段的值
                    value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
                    if(fieldName.equals("heroName")){
                        System.out.printf("字段为:%s, 值为:%s%n", fieldName, value);
                    }else if(fieldName.equals("heroSex")) {
                        System.out.printf("字段为:%s, 值为:%s%n", fieldName, value);
                    }
                }else{
                    String fileName = item.getName();  // 获取上传的文件名
                    System.out.printf("上传文件的字段:%s,文件名为:%s%n", fieldName, fileName);
                    String uploadPath = request.getServletContext().getRealPath("upload");
                    newFileName = System.currentTimeMillis() + ".jpg";
                    File file = new File(uploadPath,newFileName);
                    item.write(file);
                }
            }
            response.setContentType("text/html; charset=UTF-8");
            PrintWriter pw = response.getWriter();
            String html = "<img src='upload/%s'/>";
            pw.format(html, newFileName);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

三、过滤器 Filter

类似django中的中间件,所有的web请求都会先经过filter,可以在里面做一些统一性的处理,如设置编码,验证是否 登陆等

1.设置编码的过滤器

package filter;

public class EncodingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException,ServletException {
        // 类型转换,方便调用某些方法
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        
        // 在过滤器中统一处理编码问题
        request.setCharacterEncoding("UTF-8");
        
        // 顺便再做些统计吧,应该分开写再另一个过滤器中的
        String ip = request.getRemoteAddr();
        String url = request.getRequestURL().toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = new Date();
        String date = sdf.format(d);
        System.out.printf("%s %s %s",date,ip,url);
        
		// 过滤器放行,表示继续运行下一个过滤器,或者最终访问的某个servlet,jsp,html等等
        chain.doFilter(request, response);
    }

    @Override
    public void destroy(){
    };

    @Override
    public void init(FilterConfig var1) throws ServletException{
    };
}

2.检查是否登陆

package filter;

public class AuthFilter implements Filter {
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        String uri = request.getRequestURI();
        // 判断是否是访问的login.html和login,这两个页面不需要登陆后才能访问
        if (uri.endsWith("login.html") || uri.endsWith("login")) {
            chain.doFilter(request, response);
            return;
        }

        // session中取出userName,没有的话重定向到登陆页面
        // 需要在登陆后设置 request.getSession().setAttribute("userName",userName);
        String userName = (String) request.getSession().getAttribute("userName");
        if (null == userName) {
            response.sendRedirect("login.html");
            return;
        }

        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }
}

3.web.xml

	<filter>
        <filter-name>filter.FirstFilter</filter-name>
        <filter-class>filter.FirstFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>filter.FirstFilter</filter-name>
        <!-- 表示所有的访问都会过滤 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值