• springMVC学习--day02


    响应

    返回字符串以及void的情况

    1.返回字符串
    <br>
    <a href="responseController/returnString">returnString</a>
    <br>
    2.没有返回值
    <br>
    <a href="responseController/returnVoid">returnVoid</a>
    <br>
    3.没有返回值,转发
    <br>
    <a href="responseController/returnVoidAndDispatcher">returnVoidAndDispatcher</a>
    <br>
    4.没有返回值,重定向
    <br>
    <a href="responseController/returnVoidAndResponse">returnVoidAndResponse</a>
    <br>
    5.没有返回值,转发到同一个控制器的其他映射方法
    <br>
    <a href="responseController/returnVoidAndDispatcherToConreoller">returnVoidAndDispatcherToConreoller</a>
    <br>
    6.没有返回值,重定向到其他控制器的其他映射方法
    <br>
    <a href="responseController/returnVoidAndDispatcherToConreoller2">returnVoidAndDispatcherToConreoller2</a>
    <br>
    @RequestMapping("/responseController")
    @Controller("responseController")
    public class _06ResponseController {
        /**
         * 1.测试返回字符串类型
         * 指的是返回逻辑结果视图名称
         * springMVC会以此返回值作为文件名,到视图解析器里面进行拼接成JSP页面,并最终跳转到该页面
         */
        @RequestMapping("/returnString")
        public static String returnString() {
            return "sucess";
        }
    
        /**
         * 2.没有返回值
         * 当我们的方法返回值是void时,springMVC会把@RequestMapping()里面的映射路径名作为返回值去视图解析器解析查找对应的页面
         * 例如,这里会:HTTP Status 404 - /springMVC_war/WEB-INF/pages/responseController/returnVoid.jsp
         * 我们可以通过转发或者重定向跳转到指定的JSP页面或者其他的映射方法(控制器)里面
         */
        @RequestMapping("/returnVoid")
        public static void returnVoids() {
            System.out.println("returnVoid方法执行");
        }
    
        /**
         * 2.1.转发到jsp
         */
        @RequestMapping("/returnVoidAndDispatcher")
        public static void returnVoidAndDispatcher(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //        /WEB-INF/下面的地址是服务器内部地址,我们使用转发访问
            request.getRequestDispatcher("/WEB-INF/pages/sucess.jsp").forward(request, response);
        }
    
        /**
         * 2.2重定向到jsp
         */
        @RequestMapping("/returnVoidAndResponse")
        public static void returnVoidAndResponse(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //      重定向的方式只能访问服务器外部资源,所有我们在/WEB-INF/文件夹之外新建一个redirectView.jsp页面
            System.out.println(request.getContextPath());
            response.sendRedirect(request.getContextPath() + "/redirectView.jsp");
        }
    
        /**
         * 2.3转发或者重定向到本控制器的其他控制方法
         */
        @RequestMapping("/returnVoidAndDispatcherToConreoller")
        public static void returnVoidAndDispatcherToConreoller(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //        转发到同一个Controller下面的其他控制器方法(浏览器地址栏还是:***/responseController/returnVoidAndDispatcherToConreoller
            request.getRequestDispatcher("returnString").forward(request, response);
            //也可以使用重定向方法(浏览器地址栏变为:***/responseController/returnString
    //        response.sendRedirect("returnString");
        }
    
        /**
         * 2.4重定向其他控制器
         * 跳转到其他控制器只能用重定向
         */
        @RequestMapping("/returnVoidAndDispatcherToConreoller2")
        public static void returnVoidAndDispatcherToConreoller2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //        重定向到其他Controller下面的控制器方法
    //        response.sendRedirect("test/hello");//不可用
    //        重定向其他Controller需要加request.getContextPath(),否则只会在本Controller下面寻找目标路径
            response.sendRedirect(request.getContextPath() + "/test/hello");
        }
    }

    原始servlet -API把响应数据带回浏览器

        /**
         * 3.1.转发到jsp并传值
         */
        @RequestMapping("/returnValue")
        public static void returnValue(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //        /WEB-INF/下面的地址是服务器内部地址,我们使用转发访问
            request.setAttribute("username", "李沁");
            request.setAttribute("password", "123456");
            request.getRequestDispatcher("/WEB-INF/pages/sucess.jsp").forward(request, response);
        }
    <html>
    <head>
        <title>成功页面</title>
    </head>
    <body>
    执行成功
    <%--
        JSP四大域对象:
             page域           PageContext         最小页面范围,出了当前页面就失效
             request域        ServletRequest      当前请求和当前请求的转发                  一次请求用
             session域        HttpSession         一次会话                                多次请求用
             application域    ServletContext      最大整个应用
    
         --%>
    后台传过来的username:${username}<%--相当于pageContext的getAttribute方法--%>
    后台传过来的password:${requestScope.password}<%--明确从请求域中获取数据--%>
    </body>
    </html>

    ModelAndView

    /**
     * 4.ModelAndView
     *      返回ModelAndView,该对象是spring为我们提供的可以存放响应数据的对象。
     *   它里面有两个方法:
     *      setViewName:用于设置逻辑结果视图名称
     *      addObject(String,Object):用于设置响应正文的内容。存放的结构是key=value的形式。存入的位置是请求域中
     */
    @RequestMapping("/returnModelAndView")
    public ModelAndView returnModelAndView(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ModelAndView modelAndView = new ModelAndView();
        ArrayList<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        modelAndView.addObject("list",list);
        modelAndView.setViewName("modelAndView");
        return modelAndView;
    }
    modelAndView.jsp:
    <%--导入jstl--%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>modelAndView</title>
    </head>
    <body>
    ${list}
    ${requestScope.list}
    <c:forEach items="${list}" var="str">
        ${str}
    </c:forEach>
    </body>
    </html>

    springMVC的转发和重定向

        /**
         * springmvc的请求转发:
          */
        @RequestMapping("/springmvcDispatcher")
        public static String springmvcDispatcher() {
    //        简写:写的是逻辑结果视图名称
    //        return "sucess";
    //        完整写法:写的是物理视图地址
            return "forward:/WEB-INF/pages/sucess.jsp";
        }
        /**
         * springmvc的请求重定向:
          */
        @RequestMapping("/springmvcRedirect")
        public static String springmvcRedirect() {
    //        return "forward:/WEB-INF/pages/sucess.jsp";///WEB-INF/下面的内容我们是无法重定向进去的,下面我们演示重定向到springmvcDispatcher这个方法映射
            return "redirect:springmvcDispatcher";
        }

    JSON数据的发送和返回

    @ResponseBody:
    @RequestBody:
    <html>
    <head>
        <title>responseJson</title>
    </head>
    <script src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
    <script>
        $(function () {
            $("#getJson").click(function () {
                alert(1)
                $.ajax({
                    type: "post",//请求的方式
                    url: "${pageContext.request.contextPath}/responseController/returnJson",//请求的地址
                    dataType: "json",//响应的数据格式
                    data: '{"id":1,"name":"李沁"}',//请求的正文(请求的参数)
                    contentType: "application/json;charset=utf-8",//请求参数的格式
                    success: function (data) {//执行成功后的回调函数
                        alert(data)
                    }
                })
            })
        })
    
    </script>
    <body>
    returnJson测试响应ison数据
    <br>
    <input type="button" value="提交" id="getJson">
    </body>
    </html>

    依赖支持:

    <!--    导入json支持jar-->
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-core</artifactId>
          <version>2.9.6</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-annotations</artifactId>
          <version>2.9.6</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.9.6</version>
        </dependency>
        /**
         * 7.测试响应ison数据
         * 应用场景:
         *      一般都是异步请求,不希望浏览器刷新。
         *      @ResponseBody:将返回值的对象封装成json格式之后返回
         *      @RequestBody:将前台传递过来的json字符串封装成对应的对象
         */
        @RequestMapping("/returnJson")
        public @ResponseBody Account returnJson(@RequestBody Account accountJson) {
            System.out.println(accountJson);
            return accountJson;
        }

     文件上传:

    1.传统方式:

    参考:https://www.cnblogs.com/luzhanshi/p/13285516.html

    2.springMVC提供的方式:

    所需依赖:

    <!--    上传文件所需jar包-->
        <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.3.3</version>
        </dependency>
        <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.4</version>
        </dependency>

    springMVC.xml新增配置:

    <!--    配置springmvc提供的文件解析器-->
    <!--    注意:!!!下面的id只能是multipartResolver!!!-->
        <bean  id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--        配置上传文件的最大尺寸为10M-->
            <property name="maxUploadSize">
                <value>10240000</value>
            </property>
        </bean>

    前台代码:

    <body>
    <form action="springMVCfileUploadController/fileUploadtest" method="post"  enctype="multipart/form-data">
       名称: <input type="text" name="text"><br>
       图片:<input type="file" name="file" multiple="multiple" accept="image/png,image/gif,image/jpeg, image/jp2,.txt" ><br>
        <input type="submit"><br>
    </form>
    </body>

    后台代码:

    @RequestMapping("/springMVCfileUploadController")
    @Controller("springMVCfileUploadController")
    public class _08springmvcFileUploadController {
        @RequestMapping("/fileUploadtest")
        public ModelAndView fileUploadtest(String text, MultipartFile file, HttpServletRequest request) throws Exception {
            System.out.println("文件上传方法执行了");
            System.out.println(text);
    //        1.设置保存目录
            File fatherDir = new File("D:\fileUpload");
    //        2.为防止文件过多,以日期为名创建子文件夹储存位置
            String childDir = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            File targetDir = new File(fatherDir, childDir);
            if (!targetDir.exists()) {
                targetDir.mkdirs();
            }
    //        3.获取上传文件名,并随机化
            String fileName = file.getOriginalFilename();
            String uuid = UUID.randomUUID().toString();
            String newFileName = uuid + "_" + fileName;
    //        4.写入文件
            file.transferTo(new File(targetDir, newFileName));
           
            return "sucess";
        }
    }

    3.springMVC跨服务器上传:

    在实际开发中,我们会有很多处理不同功能的服务器。例如:
    应用服务器:负责部署我们的应用

    数据库服务器:运行我们的数据库
    缓存和消息服务器:负责处理大并发访问的缓存和消息

    文件服务器:负责存储用户上传文件的服务器。
    (注意:此处说的不是服务器集群)

    分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

    所需依赖:

    <!--    上传文件所需jar包-->
        <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.3.3</version>
        </dependency>
        <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.4</version>
        </dependency>
    <!--    跨域上传文件额外所需jar包-->
        <!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-core -->
        <dependency>
          <groupId>com.sun.jersey</groupId>
          <artifactId>jersey-core</artifactId>
    <!--      我们一般在第二行直接写jar的名字,静静地等待maven给我们提示,然后回车补全,搞定-->
          <version>1.18.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-client -->
        <dependency>
          <groupId>com.sun.jersey</groupId>
          <artifactId>jersey-client</artifactId>
          <version>1.18.1</version>
        </dependency>

    导入jersey 失败?请参考https://www.cnblogs.com/luzhanshi/p/13286405.html解决

    springMVC.xml同样要新增配置:

    <!--    配置springmvc提供的文件解析器-->
    <!--    注意:!!!下面的id只能是multipartResolver!!!-->
        <bean  id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--        配置上传文件的最大尺寸为10M-->
            <property name="maxUploadSize">
                <value>10240000</value>
            </property>
        </bean>

    接收文件的Tomact服务器安装目录下的conf/web.xml配置文件中加上:(使得服务器允许文件写入。)

     <init-param>
            <param-name>readonly</param-name>
            <param-value>false</param-value>
        </init-param>

    否则会报如下错误:

     接收文件的服务器项目要保证有如下目录:

    否则会报如下错误:PUT http://localhost:9090/fileServer_War/upload/20160515104302348740.jpg returned a response status of 409 Conflict

     发送文件前台代码:

    <form action="springMVCTwoServerfileUploadController/fileUploadtest" method="post"  enctype="multipart/form-data">
       名称: <input type="text" name="text"><br>
       图片:<input type="file" name="file" multiple="multiple" accept="image/png,image/gif,image/jpeg, image/jp2" ><br>
        <input type="submit"><br>
    </form>

     发送文件后台代码:

    @RequestMapping("/springMVCTwoServerfileUploadController")
    @Controller("springMVCTwoServerfileUploadController")
    public class _08springmvcTwoServerFileUploadController {
        //    全局定义图片服务器路径
        private static final String FILESERVERPATH = "http://localhost:9090/fileServer_war/upload/";
    
        @RequestMapping("/fileUploadtest")
        public String fileUploadtest(String text, MultipartFile file, HttpServletRequest request) throws Exception {
            System.out.println("文件上传方法执行了");
            System.out.println(text);
    //        1.获取上传文件名,并随机化
            String fileName = file.getOriginalFilename();
            String uuid = UUID.randomUUID().toString();
            String newFileName = uuid + "_" + fileName;
    //        2.获取jersey的jar包中提供的Client对象
            Client client = Client.create();
    //        3.建立和图片服务器的联系
            WebResource resource = client.resource(FILESERVERPATH + newFileName);
    //        4.把文件写到远程服务器(String.class决定返回值类型)
            String s = resource.put(String.class, file.getBytes());
            System.out.println(s);
            return "sucess";
        }
    }

    演示效果

     最后一定要去tomcat发布项目的目录下去查看文件是否上传成功!!!不要傻傻的去项目里面的upload目录下去看

     自定义异常:

    1.创建自定义异常类

    /**
     * 客户自定义异常类;继承RuntimeException或者Exception
     */
    public class MyException extends RuntimeException {
    //    定义异常信息
        private String msg;
    //通过构造方法获取异常信息
        public MyException(String msg) {
            this.msg = msg;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

    2.创建自定义异常处理器:

    /**
     * 自定义异常处理器(需要实现:HandlerExceptionResolver)
     * 并且要注册为speing组件,对象的创建交给speing容器管理,可以使用下面注解的方式,也可以在speingMVC.xml里面配置bean:<bean id="myExceptionResolver" class="web.pojo.MyExceptionResolver"></bean>
     */
    @Component("myExceptionResolver")
    public class MyExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
    //        打印异常信息
            e.printStackTrace();
    //        定义自己的异常类对象
            MyException myException = null;
    //        判断当前传入的异常对象是否是我们的自定义对象对象
            if (e instanceof MyException) {//如果是,我们就直接强转为我们自定义的异常类型
                myException = (MyException) e;
            } else {//否则就获取该异常的异常信息创建我们的自定义异常
                myException = new MyException(e.getMessage());
            }
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("error");
            modelAndView.addObject("errorMsg", myException.getMsg());
            return modelAndView;
        }
    }

    3.新建统一错误信息展示页面:

    <html>
    <head>
        <title>失败页面</title>
    </head>
    <body>
    <%--注意!!!下面的"errorMsg"要和我们自定义异常处理器里面返回的错误信息字段名一致--%>
    ${errorMsg};
    </body>
    </html>

    4.测试代码:

    @RequestMapping("/exceptionController")
    @Controller("exceptionController")
    public class _10exceptionController {
        @RequestMapping("testException")
        public String testException(String name) throws MyException {
            System.out.println("测试异常方法执行了"+name);
            if (StringUtils.isEmpty(name))
            throw new RuntimeException("用户名不能为空");
    //        throw new MyException("用户名不能为空");//也可以抛出我们自定义异常
            return "sucess";
        }
    }

    自定义拦截器:

    拦截器:

    Spring MVC的处理器拦截器类似于Servlet开发中的过滤器Filter用于对处理器进行预处理和后处理。用户可以自己定义一些拦 截器来实现特定的功能。

    谈到拦截器;还要向太家提一个词一 拦截器链( Interceptor Chain)。 拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

    说到这里,可能大家脑海中有了一个疑问;这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来我们就来说说他们的区别:

    过滤器是Servlet规范中的一-部分,任何iava web工程都可以使用。

    拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。

    过滤器在url-pattern中配置了/*之后:可以对所有要访问的资源拦截。

    拦截器它是只会拦截访问的控制器方法,如果访问的是j3R: html, ce image或者ia是不会进行拦

    截的。

    它也是AOP思想的具体应用。

    我们要想自定义拦截器,要求必须实现: HandlerInterceptor接只。

     举例:假如我们要对用户访问下面的路径的时候要验证用户是否已经登录,没有登录不可以访问:

    @RequestMapping("/interceptorController")
    @Controller("interceptorController")
    public class _11interceptorController {
        @RequestMapping("/testInterceptor")
        public String testInterceptor(String name)  {
            System.out.println("控制器中方法执行了"+name+" 说明用户登录了");
            return "sucess";
        }
    }

    首先我们要编写一个拦截器:

    //自定义拦截器实现HandlerInterceptor并重写所有的方法
    public class CheckLoginInterceptor implements HandlerInterceptor {
        /**
         * preHandle
         * 当请求到达时,先执行此方法。
         * 此方法的返回值决定了是否放行
         * 返回true:放行放行的含义:如果有下一个拦截器执行下一个,如果该拦截器处于最后一个,则执行handler方法(控制器中的方法)
         * 返回false:不放行
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle方法执行了");
    //       1. 获取Session对象
            HttpSession session = request.getSession();
    //       2. 判断session域中是否有登录标记
            Object userinfo = session.getAttribute("userinfo");
            if (userinfo != null) {
                return true;
            }
            //        没有登录信息的情况下    跳转到登录页面
            request.getRequestDispatcher("/WEB-INF/pages/login.jsp").forward(request, response);
            return false;
        }
    
        /**
         * postHandle
         * 如何调用:
         * 按拦截器定义逆序调用
         * 何时调用:
         * 在拦截器链内所有拦戴器返成功调用
         * 有什么用:
         * 在业务处理器处理完请求后,但是DiapatcherServlet向客户端返回响应前,在该方法中对用户请求request进行处理。
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle方法执行了");
        }
    
        /**
         * afterCompletion
         * 如何调用:
         * 按拦截器定义逆序调用
         * 何时调用:
         * 只有preHandle返回true才调用
         * 有什么用:
         * 在DiapatcherServlet完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion方法执行了");
        }
    }

    然后我们需要在springMVC.xml里面配置拦截器:

    <!--配置自定义拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
    <!-- path="/interceptorController/**":表示拦截  interceptorController下面的所有映射路径         -->
                <mvc:mapping path="/interceptorController/**"/>
                <bean class="web.pojo.CheckLoginInterceptor" id="myInterceptor"></bean>
            </mvc:interceptor>
        </mvc:interceptors>
    </beans>

    我们的登录login.jsp:

    <body>
    <a href="${pageContext.request.contextPath}/login/userLogin">登录</a>
    <%--${pageContext.request.contextPath}:springMVC_war(项目的根目录)--%>
    </body>

    登录的Controller代码:

    @Controller("loginController")
    @RequestMapping("/login")
    public class LoginController {
        @RequestMapping("/userLogin")
        public String userLogin(HttpServletRequest request) {
    //        1.获取session
            request.getSession().setAttribute("userinfo", "...");
            return "redirect:/main.jsp";
        }
    }

    main.jsp:

    <body>
    主页
    </body>

     上述文件的位置:

     

    使得服务器允许文件写入。

     
  • 相关阅读:
    圈子
    限制我们的最大敌人不是自己,也不是思维,是时空。
    社交的本质就是生活!
    没有归零思维,就不会有突破
    什么是老板思维,什么是员工思维,深有体会,最近被N个行业洗脑……
    太相信书的人,格局不会太大
    在一个规则没有被建立好的时代,那些活生生的牛人,就是仅存的有效教科书
    个人发展阶段与回报对应表
    分布式,去中心化,协作性,可适应性
    [测试题]line
  • 原文地址:https://www.cnblogs.com/luzhanshi/p/13282128.html
Copyright © 2020-2023  润新知