springMVC1

springMVC

SpringMVC分为:

  • 前端控制器:当用户请求时综合调用映射器、适配器、控制器、视图解析器对用户的请求进行响应

  • 映射器:对前端控制器发送的URL路径进行检查,如果路径错误返回404

  • 适配器:寻找正确的控制器,如果找不到抛出异常

  • 控制器:对用户的请求进行处理,将请求得到的数据以及要显示的视图放入ModelAndView对象中

  • 视图解析器:接收ModelAndView对象,从中获取数据,经过处理组合成视图交给前端控制器进行处理

DispatcherServlet原理

1、根据请求的路径找到HandlerMethod(带有Method反射属性,也就是对应Controller中的方法)

2、然后匹配路径对应的拦截器

3、通过HandlerMapping接口实现类获得HandlerExecutionChain对象(包含HandlerMethod和拦截器)

4、有了HandlerExecutionChain之后,通过HandlerAdapter对象进行处理得到ModelAndView对象

调用HandlerMethod内部handle的时候:
1、使用各种HandlerMethodArgumentResolver接口实现类,完成参数绑定

2、使用到各种Converter接口实现类,完成类型转换

3、使用各种HandlerMethodReturnValueHandler接口实现类,处理返回值

4、最终返回值被处理成ModelAndView对象

5、这期间发生的异常会被HandlerExceptionResolver接口实现类进行处理

5、RequestToViewNameTranslator接口实现类将请求地址解析为视图名(若有手动设置视图名,则使用手动设置的)

6、通过各种View和ViewResolver接口实现类渲染视图(将Model中的数据放到request域对象中,页面的编译。。。)

前端控制器

前端控制器在web.xml中配置

  <servlet>
  <!-- 命名 -->
    <servlet-name>springmvc</servlet-name>
    <!-- 加载包中的前端控制器 -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 让服务器已启动就开始加载文件springMVC.xml,用的是contextConfigLocation这个属性 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springMVC.xml</param-value>
    </init-param> 
        <!-- 启动加载 -->
    <load-on-startup>1</load-on-startup> 
  </servlet>

  <servlet-mapping>
  <!-- 对应上面的命名 -->
    <servlet-name>springmvc</servlet-name>
    <!-- 对文件进行拦截来执行上面的程序, "/"代表拦截所有的-->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

两种映射器

    <!-- 映射器 -->                    
   <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
   <!-- 映射器2 -->
   <bean class=" org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
            <!-- 这里的值要和控制器中的id相对应 -->
                <prop key="/text1">text</prop>
                <prop key="/text1">text</prop>
            </props>
        </property>
   </bean>

两种适配器

   <!-- 适配器  要实现Controller接口-->
   <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
   <!-- 适配器2 要实现 HttpRequestHandler接口 -->
   <bean class=" org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>

控制器

   <!-- 控制器 -->
   <bean class="com.hemi.controller.MyController"  name="/text" id="text"></bean>

后端控制器代码

public class MyController implements org.springframework.web.servlet.mvc.Controller{

    @Override
    public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {      
        String username = req.getParameter("username");
        String password = req.getParameter("password");
//      req.setAttribute("username", username);
//      req.setAttribute("password", password);
        ModelAndView view = new ModelAndView();
        if("lisi".equals(username)&&"123".equals(password)){
            view.setViewName("Hello.jsp");
        }
        else{
            view.setViewName("login.jsp");
        }

        return view;
    }

}

视图解析器

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>

视图解析器的配置前缀后缀

   <!-- 视图解析器 -->
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
   <!-- 前缀 -->
   <property name="prefix" value="/"></property>
   <!-- 后缀 -->
   <property name="suffix" value=".jsp"></property>
   </bean>

使用注解的方式配置springMVC

注意:注解适配器和映射器要一起使用才有效

注解适配器和映射器要一起使用才有效

     <!-- 扫描包 -->
   <context:component-scan base-package="com.hemi.controller"></context:component-scan>


   <!-- 配置注解 1-->
        <!-- 配置映射器注解 -->
   <bean class=" org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping "></bean>
        <!-- 配置适配器注解 -->
   <bean class=" org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>

    <!--配置注解2-->
    <!-- 终极替换上面的注解 -->
    <mvc:annotation-driven></mvc:annotation-driven>
  • @RequestMapping("path"):在方法上使用该注解,配置对应的映射路径
 @Controller
 public class TextControler{
       @RequestMapping("show1")
       public ModelAndView show1(){}
   }

springMVC后端控制器进行响应的三种方式

ModleAndView类型返回值:

  • view.setViewName("Hello"); 保存要显示的视图

  • view.addObject("password", password); 向域对象中保存数据(实际是保存到request域对象中)

   @RequestMapping("show1")
   public ModelAndView show1(HttpServletRequest req){
       String username = req.getParameter("username");
       String password = req.getParameter("password");
       ModelAndView view = new ModelAndView();
       view.addObject("username", username);
       view.addObject("password", password);       
       view.setViewName("Hello");
       return view;        
   }
@RequestMapping("show1")
   public ModelAndView show1(HttpServletRequest req){
       String username = req.getParameter("username");
       String password = req.getParameter("password");
       ModelAndView view = new ModelAndView();
       view.addObject("username", username);
       view.addObject("password", password);       
       view.setViewName("Hello");
       return view;        
   }
  • String类型返回值返回视图位置,使用Modle以及ModleMap来保存数据
    @RequestMapping("show2")
   public String show2(Model model,HttpServletRequest req){
       String username = req.getParameter("username");
       String password = req.getParameter("password");
       model.addAttribute("username", username);
       model.addAttribute("password", password);
       return "Hello";     
   }

void类型返回值要用域对象来保存数据,通过请求转发和重定向来进行响应

    @RequestMapping("show3")
   public void show3(HttpServletRequest req,HttpServletResponse resp){
       String username = req.getParameter("username");
       String password = req.getParameter("password");
       req.setAttribute("username", username);
       req.setAttribute("password", password);
       try {
           req.getRequestDispatcher("Hello.jsp").forward(req, resp);
       } catch (ServletException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       } catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }

参数绑定

简单参数绑定:传入的数据是以key/value的形式进行传递,key和后端控制器的形参名字相同,可以使用注解@RequestParam("username")为后端控制器的形参名起别名,与key相对应

Pojo参数绑定:传入的数据是以key/value的形式进行传递,key值与Pojo中的属性名称相同

自定义类型: 进行date和数据类型的绑定,需要自己编写转换类

自定义转换类型配置步骤:

  • 编写转换类
public class DateConvert implements Converter<String, Date>{

   @Override
   public Date convert(String source) {
       SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
       try {
           return format.parse(source);
       } catch (ParseException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }
       return null;
   }

}
  • 在spring配置文件中进行配置
   <mvc:annotation-driven conversion-service="conversionService">          
   </mvc:annotation-driven>

   <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
       <property name="converters">
           <list>
               <bean class="com.hemi.controller.convert.DateConvert"></bean>
           </list>         
       </property>

   </bean>
  • 在实体类中对绑定的Date属性值进行绑定
private String username;
private String password;
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date date;
  • 配置后端控制器
    @RequestMapping("show4")
   public String show4(Model model,User user){
       model.addAttribute("user", user);
       return "Hello";     
   }

参数绑定数组(数组和list集合一样)

前端页面

    <form action="show5" method="post">
       用户名:<input type="text" name="username"><br> 
       密码:<input type="password" name="password"> <br>
       日期<input type="text" name="date"><br>
       <!--传递list集合中装的是多个地址对象-->
       <input type="text" placeholder="请输入地址" name="add[0].addres"><br> 
       <input type="text" placeholder="请输入编码" name="add[0].code"><br> 
       <input type="text" placeholder="请输入地址" name="add[1].addres"><br> 
       <input type="text" placeholder="请输入编码" name="add[1].code"><br> 
       <!--传递单个地址的实体对象-->
       <input type="text" placeholder="请输入地址" name="add.addres"><br> 
       <input type="text" placeholder="请输入编码" name="add.code"><br> 
       <!--传递一个数组-->
       <input type="checkbox" name="hobby" value="basketball">篮球<br>
       <input type="checkbox" name="hobby" value="football">篮球<br>
       <input type="checkbox" name="hobby" value="tennis">网球
       <input type="submit" value="登录">
   </form>

实体类

private String username;
private String password;
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date date;
private List<Address> add;

控制器:

   @RequestMapping("show5")
   public String show5(String[] hobby){
   }

全局异常处理

  • 1、自定义异常类(继承Exception或RuntimeException)
public class CustomException extends Exception{
   private String msg;

   public CustomException(String msg) {
       super(msg);
       this.msg = msg;
   }

   public String getMsg() {
       return msg;
   }

   public void setMsg(String msg) {
       this.msg = msg;
   }
}
  • 2、自定义异常处理器实现 HandlerExceptionResolver接口
public class ExceptionHandler implements HandlerExceptionResolver{

   @Override
   public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse resp, Object object,
           Exception ex) {
       CustomException customException=null;
       if (ex instanceof CustomException) {
           customException=(CustomException)ex;
       }else{
           customException=new CustomException("未知错误");
       }
       ModelAndView view = new ModelAndView();
       view.addObject("error", customException);
       view.setViewName("error");
       return view;
   }
}
  • 3、在springmvc配置文件中配置全局异常控制器
<!-- 定义全局异常 -->
   <bean class="com.hemi.exception.handler.ExceptionHandler"></bean>

静态资源的释放

在配置文件中进行配置

    <!-- 静态资源释放-->
   <mvc:resources location="/image/" mapping="/image/*.*"></mvc:resources>

文件上传

1、编写配置文件

    <!-- 配置文件上传处理 -->
   <bean id="multipartResolver"
       class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
       <!-- 配置默认编码 -->
       <property name="defaultEncoding" value="utf-8"></property>
       <!-- 配置最大上传文件大小 -->
       <property name="maxUploadSize" value="10485760000"></property>
       <!-- 配置最大上传所用内存大小 -->
       <property name="maxInMemorySize" value="40960"></property>
   </bean>

2、上传单个文件,后端控制器:

    public String upload(MultipartFile file,HttpServletRequest req) throws IllegalStateException, IOException{
        if(file==null){
            return "uploadFile";            
        }
        //取出文件名
        String filename = file.getOriginalFilename();
        //根据文件的虚拟入境找到真实入境
        String path = req.getServletContext().getRealPath("/temp");
          File file2 = new File(path);
          if (!file2.exists()) {
            //创建目录
            file2.mkdirs();
        }
          //将传入的文件按照真实入境和文件名写出来
        file.transferTo(new File(file2,filename));
        return "success";       
    }

3、批量上传文件,后端控制器

    @RequestMapping("/upload1")
    public String upload1(MultipartFile[] file,HttpServletRequest req) throws IllegalStateException, IOException{
        for (MultipartFile multipartFile : file) {
             if(file==null){
            return "uploadFile";            
            }
            String filename = multipartFile.getOriginalFilename();
            String realPath = req.getServletContext().getRealPath("/team");
            File file2 = new File(realPath);
            if (!file2.exists()) {
                file2.mkdirs();
            }
            multipartFile.transferTo(new File(file2,filename));         
        }
        return "success";
    }

4、编写前端表单页面

    <form action="upload" method="post" enctype="multipart/form-data">
    请上传文件:<input type="file" name="file">
        <br>
        <input type="submit" value="upload">
    </form> 
    <hr>
    <form action="upload1" method="post" enctype="multipart/form-data">
    请上传文件:<input type="file" name="file">
        <br>
        请上传文件:<input type="file" name="file">
        <br>
        <input type="submit" value="upload1">
    </form> 

注意:

  • 把form表单的默认的enctype 类型改成 enctype="multipart/form-data"

  • 表单的提交方式设为:post

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,347评论 19 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,233评论 25 709
  • 1.Spring web mvc介绍 Spring web mvc和Struts2都属于表现层的框架,它是Spri...
    七弦桐语阅读 13,955评论 2 38
  • 这个时代里,我们应该踏下心来把自己像一颗种子一样摁到土里去,把自己像一个植物一样栽到花盆里面,让自己的根系在现实生...
    蝶衣宝贝阅读 1,404评论 0 0
  • 坚持不懈的努力造就成功。
    稼轩李德智阅读 4,542评论 1 9