Servlet/JSP

JSP 内置对象

9大内置对象。

  1. 为何有9大内置对象? 使用方便:不用声明变量,不用初始化,直接拿到使用!
  2. 已经预定义好的变量:

案例:

<%@ page language="java" 
    contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    errorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSP内置对象</title>
</head>
<body>
    <h1>JSP内置对象</h1>
    <h2>out 对象用于向页面输出信息。</h2>
    <p><% out.print("Hello World"); %></p>
    <h2>request用于获取浏览器发送来的请求信息</h2>
    <p><% 
        String ua=request.getHeader("User-Agent");
        out.print(ua);
    %></p>
    <h2>response用于向浏览器发送响应数据</h2>
    <p><% 
        response.setHeader("Message", "Hello World!");
    %></p>
    <h2>session 代表当前的会话对象</h2>
    <p><%
        out.println(session.getId());
    %></p>
    <h2>application 代表当前ServletContext</h2>
    <p><%
        out.print(application.getServerInfo());
    %></p>

    <h2>config 代表JSP的配置信息, 很少使用</h2>
    <p><%
        out.print(config.getServletName());
    %></p>

    <h2>page 代表当前JSP页面对象,很少用</h2>
    <%! 
        //在网页中声明方法
        public String toString(){
            return "Test Method!";
        }
    %>
    <p><%
        out.print(page); //调用toString方法
    %></p>
    <h2>pageContext 是当前页面的上下文(管家)</h2>
    <p>用于管理其他的内置对象,用于在当前页面内部共享数据</p>
    <p>
    <%
        JspWriter o = pageContext.getOut();
        o.print("试试out!");
        pageContext.setAttribute("msg", "测试信息");
        String msg=
            (String)pageContext.getAttribute("msg");
        out.print(msg);
    %>
    </p>
    <h2>exception 代表其他页面传递过来的异常(没用)</h2>
    <p><%
        out.print(pageContext.getException());
    %></p>
</body>
</html>

SmartMVC 自定义框架

MVC 模式: 解决用户界面问题的标准模式(套路)!

M Model 模型,封装业务逻辑 V View 视图,代表显示界面 C Controller 控制器,是用于连接整合 M和V

Sun给出web用户界面的建议:

  1. 使用Java Bean 作为Model,处理业务逻辑
  2. 使用JSP 作为视图,显示数据
  3. 使用Servlet作为控制器,整合JSP和JavaBean

一般情况将如上建议封装为框架(工具)减少后续编程量

框架实现步骤:

1. 拆分控制器为 前端控制器和子控制器

拆分的目的是将Web编程逻辑与业务处理逻辑进行剥离,将Web编程逻辑封装到前端控制器,达到简化子控制器逻辑,复用前端控制器的目的。

原理:

2. 利用request参数将控制器中的数据共享到JSP

为了避免用户直接访问JSP视图组件,将JSP保存到 /WEB-INF/jsp 文件夹中。

3. 利用注解将用户请求URL映射到子控制器的方法上

注解

  1. Java 5 提供了一种代码标注功能。
  2. 利用注解可以实现动态代码执行功能。
  3. 在软件运行期间动态解析注解动态执行方法。
  4. 使用注解:利用反射API解析使用注解。

案例:

@Retention(RUNTIME) //注解一值保留到运行期
@Target(METHOD) //此注解只能写在方法上
public @interface RequestMapping {
    String value(); //利用value()可以给注解添加默认参数
}

标注注解:

public class Controller {
    /**
     * 子控制器方法
     * @param request 用于在控制器和JSP直接传递数据
     * @return 转发的目标JSP页面
     * @throws Exception
     */
    @RequestMapping("/list.do") 
    public String execute(
            HttpServletRequest request) 
            throws Exception {
        UserDAO dao = new UserDAO();
        List<User> users = dao.findAll();
        //将users数据传递到JSP
        request.setAttribute("users", users); 
        return "list";
    }

    @RequestMapping("/add.do") 
    public String add(HttpServletRequest request) 
            throws Exception {
        return "add";
    }
}

反射API

  1. Java 提供的核心API
    1. java.lang.reflect 包中的系列API
  2. 提供功能:
    1. 动态解析对象的类型和内部结构,解析注解
    2. 动态加载类型
    3. 动态创建对象
    4. 动态执行方法

案例: 解析对象的内部结构

public class Test3 {

    public static void main(String[] args) {
        /**
         * 利用反射检查对象的类型和内部结构
         */
        test("ABC");
        test(5);
        ArrayList list = new ArrayList();
        Iterator i = list.iterator();
        test(i);
    }

    public static void test(Object obj) {
        //obj 引用对象的类型,以及内部结构是什么?
        //利用反射就可以动态检查对象的类型和内部结构

        // getClass() 获取当对象的实际类型
        Class cls = obj.getClass();
        System.out.println(cls); 
        //检查类型的内部结构
        // Declared 声明的  Field 字段、属性
        Field[] fields=cls.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);          
        }
        //Method: 方法 检查类型中声明的方法
        Method[] methods = cls.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method); 
        }

    }

}

案例: 利用反射API解析方法的注解

public class Demo {

    @RequestMapping("/list.do")
    public String list() {
        return "list";
    }

    @RequestMapping("/add.do")
    public String add() {
        return "add";
    }

}


public class Test4 {

    public static void main(String[] args) 
        throws Exception{
        /**
         * 动态解析类方法上标注的注解
         */
        Scanner in= new Scanner(System.in);
        System.out.print("输入类名:");
        String className=in.nextLine();

        //获取Demo的类型信息
        //Class cls = Demo.class;

        //forName() 可以动态加载一个类到内存中
        Class cls = Class.forName(className);

        //获取类型上全部的方法
        Method[] methods=cls.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
            //Annotation:注解
            //method.getAnnotations() 获取在方法上
            //标注的注解。此注解必须是 RUNTIME 注解
            Annotation[] anns=method.getAnnotations();
            //方法上只标注了一个注解,获取第一个注解
            Annotation ann = anns[0];
            System.out.println(ann);
            //读取注解上的value值
            if(ann instanceof RequestMapping) {
                RequestMapping rm=(RequestMapping)ann;
                System.out.println(rm.value()); 
            }
        }
    }
}

利用反射调用方法:

  1. 加载类
  2. 在类找到要执行的方法
  3. 创建对象
  4. 在对象上执行方法

案例:

public class Test5 {

    public static void main(String[] args) 
        throws Exception{
        /*
         * 利用反射执行方法
        1. 加载类
        2. 在类找到要执行的方法
        3. 创建对象
        4. 在对象上执行方法
         */
        Scanner in = new Scanner(System.in);
        System.out.print("输入类名:");
        String className = in.nextLine();

        //Class cls 是反射API的使用入口 
        //动态加载类
        Class cls = Class.forName(className);
        //输入方法名
        System.out.print("输入方法名:");
        String name = in.nextLine();
        //动态找到类上声明的方法,如果找不到就抛出异常!
        Method method = cls.getDeclaredMethod(name);
        //创建对象:动态创建对象, Instance实例
        //newInstance的使用前提是类型必须包含无参构造器
        Object obj = cls.newInstance();
        //在对象obj上调用method方法:
        //如果参数错误,或者对象上没有方法,或者方法执行
        //期间出现故障,都会抛出异常。
        Object val = method.invoke(obj);
        System.out.println(val); 
    }

}