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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

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