SpringMVC进击

本文详细介绍了Spring MVC框架的使用方法,包括@RequestMapping注解的功能、控制器方法的返回值处理、异常处理策略、文件上传流程、JSON数据交互、Restful风格的应用以及拦截器的配置。

Spring进击

一、@RequestMapping

通过RequestMapping注解可以定义不同的处理器映射

  1. URL路径映射

    @RequestMapping(value=”/test”) 可以不写value值 默认是value值

    value值可以是数组,可以将多个url映射到同一个方法中。

  2. 窄化请求映射

    这个方式是在class上添加@RequestMapping(url)来指定请求前缀,从而限制了此类下的所有方法请求必须以这个url为签注,这个方式能对url进行分类管理,在实际项目中一个模块不可能全由一个人实现,所以很有可能我们自己在类的方法上写的url会重复,我们就可以通过这种方式来避免

    举个例子

    
    @Controller
    @RequestMapping("/user")
    public class UserTest{
    @RequestMapping("/list")
    public void getList(){
    
    }
    }
    如果我们要访问getList() 我们的访问地址就是/user/list
  3. 限制请求方法

    1. 限定GET方法

      @RequestMapping(method = RequestMethod.GET)

      如果通过Post访问则报错:

      HTTP Status 405 - Request method ‘POST’ notsupported

      例如:

      @RequestMapping(value=”/test”,method=RequestMethod.GET)

    2. 限定POST方法

      @RequestMapping(method = RequestMethod.POST)

      如果通过Post访问则报错:

      HTTP Status 405 - Request method ‘GET’ notsupported

      例如:

      @RequestMapping(value=”/test”,method=RequestMethod.POST)

    3. GET和POST都可以

      @RequestMapping(method={RequestMethod.GET,RequestMethod.POST})

二、controller方法返回值

  1. 返回ModelAndView(掌握)

    在controller方法中new 一个ModelAndView对象并返回,对象中我们可以添加Model数据,指定view

    modelAndView.addObject(“test”, test); 指定返回页面的数据

    modelAndView.setViewName(“index”) 指定返回的页面是index

  2. 返回void(破坏 了SpringMVC结构,不建议使用)

    可以在controller方法上定义request和response,通过request和response指定响应结果:

    1. 使用request.getRequestDispatcher(url).forward(request, response) 转向页面

    2. 使用response.sendRedirect(url)重定向

    3. 使用response指定响应结果,

      例如响应json数据

      response.setCharacterEncoding("utf-8");
      response.setContentType("application/json;charset=utf-8");
      response.getWriter().write("json串");

    注意:如果controller返回值是void的话,要写页面的完整路径

  3. 返回String(推荐使用)

    1. 返回逻辑视图名

      controller方法返回字符串可以指定逻辑视图名,通过视图解析器(这个通常在xml文件中配置好)解析为物理视图地址

    2. Redirect 重定向

      controller方法返回结果重定向到一个url地址,例如我们要重定向到test

      return “redirect:test”

      redirect方式相当于“response.sendRedirect()”,转发后浏览器的地址栏变为转发后的地址,因为转发即执行了一个新的request和response。由于新发起一个request原来的参数在转发时就不能传递到下一个url,如果要传参数可以在test后边加参数。

    3. forward 转发

      controller方法执行后继续执行另一个controller方法,forward方式相当于 “request.getRequestDispatcher(url).forward(request,response)”,转发后浏览器地址栏还是原来的地址。转发并没有执行新的request和response,而是和转发前的请求共用一个request和response。所以转发前请求的参数在转发后仍然可以读取到。

三、异常处理器

​ 主要是为了防止项目上线后给用户抛500等异常信息,所以我们必须处理好异常,不然别人会说你个辣鸡,连异常都不处理,抛给我看干什么我又不知道怎么改,真是弱鸡

异常分为两类:

  1. 预期异常

    通过捕获异常的到异常信息

  2. 运行时异常RuntimeException

    通过规范代码开发、测试等手段减少异常的发生

解决异常的方法是自定义全局异常处理器实现HandlerExceptionResolver接口(interface)在SpringMVC.xml文件中配置生效

  1. 自定义异常类

    为了区分不同的异常,根据异常的类型来自定义异常类,举个例子,在这我创建一个自定义系统异常, 如果有抛出此类异常就是系统预期处理的异常信息

    public class MyException extends Exception {
    /** serialVersionUID*/
    private static final long serialVersionUID = -5212079010855161498L;
    //异常信息
    private String message;
    
    public MyException(String message){
        super(message);
        this.message = message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
    }
    
  2. 自定义异常处理器

    // 记得要实现HandlerExceptionResolver接口哦
    public class MyExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception exception) {
    
        // 打印异常信息
        exception.printStackTrace();
    
        MyException myException = null;
    
        //如果抛出的是系统自定义异常则直接转换
        if(exception instanceof MyException){
            myException = (MyException)exception;
        }else{
            //如果抛出的不是系统自定义异常则重新构造一个系统错误异常。
            myException = new MyException("系统错误!");
        }
    
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message", myException.getMessage());
        modelAndView.setViewName("error");
        return modelAndView;
    }
    }
    
  3. 异常错误界面

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%> 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>错误页面</title>
    </head>
     <body>
     您的操作出现错误如下:<br/>
     ${message }
     </body>
    </html>
    
  4. 异常处理器配置(xml中)

    在SpringMVC.xml文件中声明

    <!-- 异常处理器 -->
    <bean id="handlerExceptionResolver"      class="cn.itcast.ssm.controller.exceptionResolver.CustomExceptionResolver"/>
    

四、上传图片

这个是为了解决 当你的用户端需要传输图片久而久之造成服务器负载的情况

  1. 配置虚拟目录

    在Tomcat上配置图片的虚拟目录,在conf/server.xml文件中加入

    <Context docBase="存放图片的路径" path=“/pic” reloadable=“false”/>

    我们访问 localhost:8080/pic, 即可访问我们存放图片路径下的图片了

  2. 依赖

       <dependency>
         <groupId>commons-fileupload</groupId>
         <artifactId>commons-fileupload</artifactId>
         <version>1.2.2</version>
       </dependency>
       <dependency>
         <groupId>commons-io</groupId>
         <artifactId>commons-io</artifactId>
         <version>2.4</version>
       </dependency>
  3. 配置解析器(配置于SpringMVC.xml文件中)

    <!-- 文件上传 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置上传文件的最大尺寸 -->
    <property name="maxUploadSize">
        <value>5242880</value>
    </property>
    </bean>
  4. 上传图片

    //假设我们用户有一张图片 我们上传一张图片 并把其信息存到用户的信息中
    @RequestMapping("/test")
    public String test(User user, MultipartFile pictureFile)throws Exception{
    //原始文件名称
    String pictureFile_name =  pictureFile.getOriginalFilename();
    //新文件名称 防止文件名重复
    String newFileName = UUID.randomUUID().toString()+pictureFile_name.substring(pictureFile_name.lastIndexOf("."));
    //上传图片
    File uploadPic = new java.io.File("存放图片的位置"+newFileName);
    if(!uploadPic.exists()){
        uploadPic.mkdirs();
    }
    //向磁盘写文件
    pictureFile.transferTo(uploadPic);
    user.setPic(newFileName);
    //更新用户在数据库之中的信息
    ..................
    return "success";
    }
  5. 页面

    <form id="userForm"
    action="${pageContext.request.contextPath }/user/test"
        method="post" enctype="multipart/form-data">
        <input type="hidden" name="pic" value="${user.pic }" />
    <tr>
        <td>商品图片</td>
        <td>
            <c:if test="${user.pic !=null}">
                <img src="/pic/${user.pic}" width=100 height=100 />
                <br/>
            </c:if> 
            <input type="file" name="pictureFile" />
        </td>
    </tr>
    </form>
    

五、json数据的交互

  1. @RequestBody

    作用:

    @RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。

    List.action?id=1&name=zhangsan&age=12

    本例子应用:

    @RequestBody注解实现接收http请求的json数据,将json数据转换为java对象

  2. @ResponseBody

    作用:

    该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

    本例子应用:

    @ResponseBody注解实现将controller方法返回对象转换为json响应给客户端

  3. 请求json,响应json实现

    1. 配置依赖

        <!-- JSON -->
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-annotations</artifactId>
          <version>2.4.0</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-core</artifactId>
          <version>2.4.2</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.4.2</version>
        </dependency>
    2. 配置json转换器

      <!--注解适配器 --><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
      <property name="messageConverters">
          <list>
              <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">               </bean>
          </list>
      </property>
      </bean>
      

      如果使用<mvc:annotation-driven/> 则不用定义上边的内容。

    3. controller

      // 提交json信息,响应json信息
      @RequestMapping("/submit_RequestJson")
      public @ResponseBody User submit_RequestJson(@RequestBody User user) throws Exception {
      System.out.println(user);
      // 处理
      .........................
      return user;
      }
      
    4. 页面上

      引入jQuery
      
      /请求json响应json
      function request_json(){
      $.ajax({
      type:"post",
      url:"${pageContext.request.contextPath }/user/submit_RequestJson",
          contentType:"application/json;charset=utf-8",
          data:'{"name":"test","sex":1}',
          success:function(data){
              alert(data);
          }
      });
      }

六、Restful

​ Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格,是对http协议的诠释。资源定位:互联网所有的事物都是资源,要求url中没有动词,只有名词。没有参数

Url格式:http://test/article/details/45621673

资源操作:使用put、delete、post、get,使用不同方法对资源进行操作。分别对应添加、删除、修改、查询。一般使用时还是post和get。Put和Delete几乎不使用。

how to deploy it

  1. 添加DispatcherServlet的rest配置(写于web.xml文件中)
<servlet>
    <servlet-name>springmvc-servlet-rest</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
         <param-value>classpath:SpringMvc.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc-servlet-rest</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
  1. 进行URL模板模式映射

    @RequestMapping(value=”/ viewItems/{id}”):{×××}占位符,请求的URL可以是“/viewItems/1”或“/viewItems/2”,通过在方法中使用@PathVariable获取{×××}中的×××变量。
    @PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。

    @RequestMapping("/viewItems/{id}") 
    public @ResponseBody viewItems(@PathVariable("id") String id,Model model) throws Exception{
    //方法中使用@PathVariable获取useried的值,使用model传回页面
    //调用 service查询商品信息
    ItemsCustom itemsCustom = itemsService.findItemsById(id);
    return itemsCustom;
    }
    

    如果RequestMapping中表示为”/viewItems/{id}”,id和形参名称一致,@PathVariable不用指定名称。

  2. 静态资源访问<mvc:resources>

    如果在DispatcherServlet中设置url-pattern为 /则必须对静态资源进行访问处理。

    spring mvc 的<mvc:resources mapping="" location="">实现对静态资源进行映射访问。

    如下是对js文件访问配置:

    <mvc:resources location="/js/" mapping="/js/**"/>

七、拦截器

​ 功能就是和servlet开发中的过滤器Filter类似的,用于对处理器进行预处理和后处理

  1. 定义拦截器

    实现HandlerInterceptor接口

    public class HandlerInterceptor1 implements HandlerInterceptor{
    /**
     * controller执行前调用此方法
     * 返回true表示继续执行,返回false中止执行
     * 这里可以加入登录校验、权限拦截等
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        Return false;
    }
    /**
     * controller执行后但未返回视图前调用此方法
     * 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
     */
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
    }
    /**
     * controller执行后且视图返回后调用此方法
     * 这里可得到执行controller时的异常信息
     * 这里可记录操作日志,资源清理等
     */
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }
    }
    
  2. 拦截器配置

    1. 针对某种mapping配置拦截器

      <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
      <property name="interceptors">
          <list>
              <ref bean="handlerInterceptor1"/>
              <ref bean="handlerInterceptor2"/>
          </list>
      </property>
      </bean>
      <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
      <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
    2. 针对所有的mapping配置全局拦截器

      <mvc:interceptors>
      <mvc:interceptor>
          <!-- 要拦截所有,必须配置为 /** -->
          <mvc:mapping path="/**" />
          <!-- 指定拦截器的位置 -->
          <bean class="com.lj.interceptor.LoginInterceptor1" id="loginInterceptor" />
      </mvc:interceptor>
      <mvc:interceptor>
          <!-- 要拦截所有,必须配置为 /** -->
          <mvc:mapping path="/**" />
          <!-- 指定拦截器的位置 -->
          <bean class="com.lj.interceptor.LoginInterceptor2" id="loginInterceptor" />
      </mvc:interceptor>
      </mvc:interceptors>
      
      

    针对拦截器举个例子

    检测用户是否登录了,没有登录就拦截

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    public class LoginInterceptor implements HandlerInterceptor {
    
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        // TODO Auto-generated method stub
    
    }
    
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
        // TODO Auto-generated method stub
    
    }
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
        //判断当前访问路径是否为登录的路径,如果是则放行
        if(request.getRequestURI().indexOf("/login") >= 0){
            return true;
        }
        //判断session中是否有登录信息,如果没有则跳转到登录页面,如果有则放行
        HttpSession session = request.getSession();
        if(session.getAttribute("username") != null){
            return true;
        }
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        return false;
    }
    
    }
    

    用户登录的controller

    //登陆页面
    @RequestMapping("/login")
    public String login(Model model)throws Exception{
        return "login";
    }
    //登陆提交
    // userid:用户账号,pwd:密码
    @RequestMapping("/loginsubmit")
    public String loginsubmit(HttpSession session,String userid,String pwd)throws Exception{
        //向session记录用户身份信息
        session.setAttribute("activeUser", userid);
        return "redirect:user/userShow";
    }
    //退出
    @RequestMapping("/logout")
    public String logout(HttpSession session)throws Exception{
        //session过期
        session.invalidate();
        return "redirect:user/userShow";
    }
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值