springmvc

 ̄綄美尐妖づ 提交于 2020-01-19 18:50:02

SpringMVC

第一章

1.1 三层架构

  • 表现层:web层,用来和客户端进行数据交互的,一般采用MVC的设计模式
  • 业务层:处理公司具体的业务逻辑的
  • 持久层:操作数据库的

1.2 MVC模型

  • Model:用来进行数据封装
  • View:用来展示数据给用户
  • Controller:用来接收用户请求,整个流程的控制器,进行数据校验等

1.3 SpringMVC的优势

  • 清晰的角色划分
    • 前端控制器(DispatcherServlet)
      • 控制流程的中心,有它调用其他组件处理用户的请求,解耦
    • 请求到处理器映射(HandlerMapping)
      • 负责根据用户请求找到Handler即处理器,SpringMVC 提供了不同的映射器实现不同的 映射方式,例如:配置文件方式,实现接口方式,注解方式等
    • 处理器(Handler)
      • 由DispatcherServlet把用户请求转发到Handler,由Handler对具体的用户请求进行处理
    • 处理器适配器(HandlerAdapter)
      • 充当接口作用
    • 视图解析器(ViewResolver)
      • 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名 即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户
    • 视图(view)
      • SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView 等。我们最常用的视图就是 jsp
    • 处理器或页面控制器(Controller)
    • 验证器( Validator)
    • 命令对象(Command 请求参数绑定到的对象就叫命令对象)
    • 表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)
  • 分工明确,容易扩展
  • 可使用命令对象直接作为业务对象
  • 和Spring无缝集成
  • 可适配
  • 可定制性

1.4 SpringMVC入门案例

  • 通过Maven创建web工程,引入依赖

  • 配置核心的控制器(在web.xml中配置DispatcherServlet)

    • <servlet>
        <servlet-name>dispatcherServlet</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启动时加载对象 -->
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
  • 编写springmvc.xml的配置文件

    • <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:mvc="http://www.springframework.org/schema/mvc"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="
              http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/mvc
              http://www.springframework.org/schema/mvc/spring-mvc.xsd
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context.xsd">
      
          <!-- 开启注解扫描 -->
          <context:component-scan base-package="cn.itcast"/>
          <!-- 视图解析器对象 -->
          <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix" value="/WEB-INF/pages/"/>
              <property name="suffix" value=".jsp"/>
          </bean>
          <!--配置自定义类型转换器-->
          <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
              <property name="converters">
                  <set>
                      <bean class="cn.itcast.utils.StringToDateConverter"/>
                  </set>
              </property>
          </bean>
          <!-- 开启SpringMVC框架注解的支持 -->
          <mvc:annotation-driven conversion-service="conversionService"/>
          <!-- SpringMVC的各个组件中,处理器映射器,处理器适配器,视图解析器成为SpringMVC三大组件,配置了上面这个标签,自动加载RequestMappingHandlerMapping (处理映射器)和 RequestMappingHandlerAdapter ( 处 理 适 配 器 ) -->
      
      </beans>
  • 编写index.jsp和HelloController控制器类

    • index.jsp

    • <body>        
          <h3>入门案例</h3>        
          <a href="${ pageContext.request.contextPath }/hello">入门案例</a>
      </body>
    • HelloController

    • @Controller 
      public class HelloController {        
          /**     * 接收请求     * @return     */    
          @RequestMapping(path="/hello")    
          public String sayHello() {        
              System.out.println("Hello SpringMVC!!");        
              return "success";    
          } 
      }
  • 在web-INF目录下创建pages文件夹,编写success.jsp的成功页面

    • <body>
          <h3>入门成功</h3>
      </body>
  • 测试

1.5 RequestMapping注解

@Controller("accountController") 
@RequestMapping("/account") 
public class AccountController { 
    @RequestMapping("/findAccount")  
    public String findAccount() {   
        System.out.println("查询了账户。。。。");   
        return "success";  
    } 
    
    //method属性:限定提交方式
    @RequestMapping(value="/saveAccount",method=RequestMethod.POST) 
    public String saveAccount() {  
        System.out.println("保存了账户");  
        return "success"; 
    }
    
    //限定了参数,<a href="account/removeAccount?accountName=aaa&money>100">可访问
    @RequestMapping(value="/removeAccount",params= {"accountName","money>100"}) 
    public String removeAccount() {  
        System.out.println("删除了账户");  
        return "success"; 
    }
} 
<!-- jsp中的使用 -->   
<body> 
  <!-- 第一种访问方式 -->   
    <a href="${pageContext.request.contextPath}/account/findAccount"> 
        查询账户   
    </a>  
    <br/> 
  <!-- 第二种访问方式 -->   
    <a href="account/findAccount">
            查询账户
    </a>  
</body> 

1.6 请求参数的绑定

<a href="account/findAccount?accountId=10">查询账户</a> 

//会自动将请求参数accountId=10作为方法的参数传入
@RequestMapping("/findAccount")  
public String findAccount(Integer accountId) {   
    System.out.println("查询了账户。。。。"+accountId);   
    return "success";  
}
  • 控制器方法中的形参支持的数据类型
    • 基本类型(加String类型)
      • 要求请求参数名称和控制器中方法的形参名称严格一致
    • POJO类型参数(实体类,相关联的实体类)
      • 要求表单中的参数名称和POJO类的属性名称保持一致,并且控制器方法的参数类型是POJO类型
    • 数组和集合类型参数
public class Account implements Serializable { 
    private Integer id;  
    private String name;  
    private Float money;  
    private Address address;  //getters and setters 
}
public class Address implements Serializable {    
    private String provinceName;  
    private String cityName;  //getters and setters 
}
public class User implements Serializable {    
    private String username;  
    private String password;  
    private Integer age;  
    private List<Account> accounts;  
    private Map<String,Account> accountMap; //getters and setters 
}
//在controller中
@RequestMapping("/saveAccount") 
public String saveAccount(Account account) {  
    System.out.println("保存了账户。。。。"+account);  
    return "success"; 
} 

@RequestMapping("/updateAccount") 
public String updateAccount(User user) {  
    System.out.println("更新了账户。。。。"+user);  
    return "success"; 
}
<form action="account/saveAccount" method="post"> 
    账户名称:<input type="text" name="name" ><br/>
    账户金额:<input type="text" name="money" ><br/>  
    账户省份:<input type="text" name="address.provinceName" ><br/>  
    账户城市:<input type="text" name="address.cityName" ><br/>  
    <input type="submit" value=" 保存 "> 
</form> 
    
<form action="account/updateAccount" method="post"> 
    用户名称:<input type="text" name="username" ><br/>  
    用户密码:<input type="password" name="password" ><br/>  
    用户年龄:<input type="text" name="age" ><br/>  
    账户 1 名称:<input type="text" name="accounts[0].name" ><br/>  
    账户 1 金额:<input type="text" name="accounts[0].money" ><br/>  
    账户 2 名称:<input type="text" name="accounts[1].name" ><br/>  
    账户 2 金额:<input type="text" name="accounts[1].money" ><br/>  
    账户 3 名称:<input type="text" name="accountMap['one'].name" ><br/>  
    账户 3 金额:<input type="text" name="accountMap['one'].money" ><br/>  
    账户 4 名称:<input type="text" name="accountMap['two'].name" ><br/>  
    账户 4 金额:<input type="text" name="accountMap['two'].money" ><br/>  
    <input type="submit" value=" 保存 "> 
</form>

1.7 请求参数乱码问题

post 请求方式: 在 web.xml 中配置一个过滤器 
<!-- 配置 springMVC 编码过滤器 -->   
<filter>    
    <filter-name>CharacterEncodingFilter</filter-name>   
    <filter-class>   
        org.springframework.web.filter.CharacterEncodingFilter 
    </filter-class> 
    <!-- 设置过滤器中的属性值 -->    
    <init-param>     
        <param-name>encoding</param-name>   
        <param-value>UTF-8</param-value>    
    </init-param>   
    <!-- 启动过滤器 -->    
    <init-param>     
        <param-name>forceEncoding</param-name>     
        <param-value>true</param-value>    
    </init-param>   
</filter>   
<!-- 过滤所有请求 -->   
<filter-mapping>    
    <filter-name>CharacterEncodingFilter</filter-name>    
    <url-pattern>/*</url-pattern>   
</filter-mapping> 

在 springmvc 的配置文件中可以配置,静态资源不过滤: 
<!-- location 表示路径,mapping 表示文件,**表示该目录下的文件以及子目录的文件 -->   
<mvc:resources location="/css/" mapping="/css/**"/>   
<mvc:resources location="/images/" mapping="/images/**"/>   
<mvc:resources location="/scripts/" mapping="/javascript/**"/>


get 请求方式: 
tomacat 对 GET和 POST 请求处理方式是不同的,GET请求的编码问题,要改 tomcat 的 server.xml 配置文件,如下: 
<Connector  connectionTimeout="20000"  port="8080"    protocol="HTTP/1.1"  redirectPort="8443"/> 
改为: 
<Connector  connectionTimeout="20000"  port="8080"     
           protocol="HTTP/1.1"  redirectPort="8443"  
            useBodyEncodingForURI="true"/> 
如果遇到 ajax 请求仍然乱码,请把:  useBodyEncodingForURI="true"改为 URIEncoding="UTF-8" 即可。

1.8 自定义类型转换器

  • 使用情况
<a href="account/deleteAccount?date=2018-01-01">根据日期删除账户</a> 
@RequestMapping("/deleteAccount") 
public String deleteAccount(String  date) {  
    System.out.println("删除了账户。。。。"+date);  
    return "success"; 
}//此时可能会报错,因为格式不匹配,自动转换要求不匹配
  • 使用步骤
第一步:定义一个类,实现 Converter 接口,该接口有两个泛型。 
public interface Converter<S, T> {//S:表示接受的类型,T:表示目标类型  
    /** 
    *  实现类型转换的方法  
    */  
    @Nullable  T convert(S source); 
}

public class StringToDateConverter implements Converter<String, Date> {  
    /** 
    * 用于把 String 类型转成日期类型   */ 
    @Override  public Date convert(String source) {   
        DateFormat format = null;   
        try {    
        if(StringUtils.isEmpty(source)) {     
            throw new NullPointerException("请输入要转换的日期");    
        }    
        format = new SimpleDateFormat("yyyy-MM-dd");    
        Date date = format.parse(source);    
        return date;   
        } catch (Exception e) {    
        throw new RuntimeException("输入日期有误");   
        }  
    } 
}
第二步:在 spring配置文件中配置类型转换器
<!-- 配置类型转换器工厂 --> 
<bean id="converterService"   
      class="org.springframework.context.support.ConversionServiceFactoryBean"> 
    <!-- 给工厂注入一个新的类型转换器 -->      
    <property name="converters"> 
        <array> 
            <!-- 配置自定义类型转换器,将自定义的转换器也加入其中 -->       
            <bean class="com.itheima.web.converter.StringToDateConverter"></bean> 
        </array>      
    </property> 
</bean>

第三步:在 annotation-driven标签中引用配置的类型转换服务 
<!-- 引用自定义类型转换器 --> 
<mvc:annotation-driven 
conversion-service="converterService"></mvc:annotation-driven> 

1.9 使用ServletAPI对象作为方法参数

<a href="account/testServletAPI">测试访问 ServletAPI</a> 
@RequestMapping("/testServletAPI") 
public String testServletAPI(HttpServletRequest request,        
                             HttpServletResponse response,      
                             HttpSession session) {  
    System.out.println(request);  System.out.println(response);     
    System.out.println(session);  
    return "success"; 
}

1.10 常用注解

  • RequestParam:把求情中指定名称的参数给控制器中的形参赋值
    • 属性
    • value:请求参数的名称
    • required:请求参数中是否必须提供此参数。默认值:true,表示必须提供,不提供则报错
  • RequestBody:用于获取请求体内容。直接使用得到是 key=value&key=value...结构的数据。 get 请求方式不适用。
    • 属性
    • required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值 为 false,get 请求得到是 null。
  • PathVaribale :用于绑定 url 中的占位符。
  • value:用于指定 url 中占位符名称
  • required:是否必须提供占位符。
  • RequestHeader :用于获取请求消息头
  • 属性
  • value:提供消息头名称
  • required:是否必须有此消息头
  • CookieValue :用于把指定 cookie 名称的值传入控制器方法参数。
  • value:指定 cookie 的名称。
  • required:是否必须有此 cookie
<a href="springmvc/useRequestParam?name=test">requestParam 注解</a> 

post 请求 jsp代码: 
<!-- request body 注解 --> 
<form action="springmvc/useRequestBody" method="post"> 
    用户名称:<input type="text" name="username" ><br/>  
    用户密码:<input type="password" name="password" ><br/>  
    用户年龄:<input type="text" name="age" ><br/> 
    <input type="submit" value=" 保存 "> 
</form> 

get 请求 jsp代码: 
<a href="springmvc/useRequestBody?body=test">requestBody 注解 get 请求</a>

<a href="springmvc/usePathVariable/100">pathVariable 注解</a> 

<a href="springmvc/useRequestHeader">获取请求消息头</a> 

<a href="springmvc/useCookieValue">绑定 cookie 的值</a> 
@RequestMapping("/useRequestParam") 
public String useRequestParam(@RequestParam("name")String username,       
                              @RequestParam(value="age",required=false)
                              Integer age){  
    System.out.println(username+","+age);  
    return "success"; 
}

@RequestMapping("/useRequestBody") 
public String useRequestBody(@RequestBody(required=false) String body){  
    System.out.println(body);  
    return "success"; 
} 

@RequestMapping("/usePathVariable/{id}") 
public String usePathVariable(@PathVariable("id") Integer id){  
    System.out.println(id);  return "success"; 
}

@RequestMapping("/useRequestHeader") 
public String useRequestHeader(
    @RequestHeader(value="Accept-Language", required=false)String requestHeader){       
    System.out.println(requestHeader);  
    return "success"; 
}

@RequestMapping("/useCookieValue") 
public String useCookieValue(
    @CookieValue(value="JSESSIONID",required=false) String cookieValue){  
    System.out.println(cookieValue);  
    return "success"; 
}
  • ModelAttribute :若一个方法被ModelAttribute修饰后,进行处理器请求方法之前它会被执行
<form action="springmvc/updateUser" method="post"> 
    用户名称:<input type="text" name="username" ><br/>     //输入cgx
    用户年龄:<input type="text" name="age" ><br/>           //输入23
    <input type="submit" value=" 保存 "> 
</form> 
@ModelAttribute  
public User showModel(User user) {   
    User abc = findUserByName(username); 
    System.out.println("执行了 showModel 方法"+abc);  
    return abc; 
}//username=cgx,password=123456,age=19,会将对象传递给下面的方法参数中


方式一:带返回值
@RequestMapping("/updateUser")  
public String testModelAttribute(User user) {   //会根据表单的值修改user对象内容。
    System.out.println("控制器中处理请求的方法:修改用户:"+user);  
    return "success";   
}//username=cgx,password=123456,age=23
private User findUserByName(String username) {  
    User user = new User();  
    user.setUsername(username); 
    user.setAge(19);  
    user.setPassword("123456");  
    return user; 
}

方式二:不带返回值
@ModelAttribute 
public void showModel(String username,Map<String,User> map) { 
    //模拟去数据库查询  
    User user = findUserByName(username); 
    System.out.println("执行了 showModel 方法"+user);  
    map.put("abc",user); 
}
@RequestMapping("/updateUser") 
public String testModelAttribute(@ModelAttribute("abc")User user) {  
    System.out.println("控制器中处理请求的方法:修改用户:"+user);  
    return "success"; 
}
  • SessionAttribute:用于多次执行控制器方法间的参数共享
<!-- SessionAttribute 注解的使用 --> 
<a href="springmvc/testPut">存入 SessionAttribute</a> <hr/> 
<a href="springmvc/testGet">取出 SessionAttribute</a> <hr/> 
<a href="springmvc/testClean">清除 SessionAttribute</a>
@Controller("sessionAttributeController") 
@RequestMapping("/springmvc") 
@SessionAttributes(value ={"username","password"},types={Integer.class})  
public class SessionAttributeController {    
    /** 
    * 把数据存入 SessionAttribute   
    * @param model   
    * @return 
    *  Model 是 spring 提供的一个接口,该接口有一个实现类 ExtendedModelMap   
    *  该类继承了 ModelMap,而 ModelMap 就是 LinkedHashMap 子类   
    */   
    @RequestMapping("/testPut")      //存入数据
    public String testPut(Model model){           
        model.addAttribute("username", "泰斯特");           
        model.addAttribute("password","123456");           
        model.addAttribute("age", 31);   
        //跳转之前将数据保存到 username、password 和 age 中,因为注解@SessionAttribute 中有 这几个参数           
        return "success";       
    }               
    @RequestMapping("/testGet")       //获取数据
    public String testGet(ModelMap model){         
        System.out.println(model.get("username")+";"
                        +model.get("password")+";"+model.get("a ge"));           
        return "success";       
    }             
    @RequestMapping("/testClean")        //清空数据
    public String complete(SessionStatus sessionStatus){         
        sessionStatus.setComplete();            
        return "success";        
    }   
}

第二章

2.1 返回值

//方式一:空返回值,通过resquest和response设置
@RequestMapping("/testReturnVoid") 
public void testReturnVoid(HttpServletRequest request,HttpServletResponse response) throws Exception { 
    //1、使用 request 转向页面,如下: 
    request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, 
response); 
    //2、也可以通过 response 页面重定向: 
    response.sendRedirect("testRetrunString") 
     //3、也可以通过 response 指定响应结果,例如响应 json 数据: 
    response.setCharacterEncoding("utf-8"); 
    response.setContentType("application/json;charset=utf-8"); 
    response.getWriter().write("json 串"); 
}

//方式二:ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值
@RequestMapping("/testReturnModelAndView") 
public ModelAndView testReturnModelAndView() {  
    ModelAndView mv = new ModelAndView();  
    mv.addObject("username", "张三");  //将属性添加到request域中
    mv.setViewName("success"); //设置转发视图页面
}
//获取
<body> 
执行成功! 
${requestScope.username} 
</body>

2.2 转发和重定向

//转发
@RequestMapping("/testForward")  
public String testForward() {   
    System.out.println("AccountController 的 testForward 方法执行了。。。。"); 
    return "forward:/WEB-INF/pages/success.jsp";  
}
//如果用了 formward:则路径必须写成实际视图 url,不能写逻辑视图
//它相当于“request.getRequestDispatcher("url").forward(request,response)”。

//重定向
@RequestMapping("/testRedirect") public String testRedirect() {  
    System.out.println("AccountController 的 testRedirect 方法执行了。。。。");  
    return "redirect:testReturnModelAndView"; 
}
//它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 页面,则 jsp 页面不 能写在 WEB-INF 目录中,否则无法找到

2.3 ResponseBody响应json数据

<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.min.js"></script> 
<script type="text/javascript">  
    $(function(){   
        $("#testJson").click(function(){            
            $.ajax({     
                type:"post",
                url:"${pageContext.request.contextPath}/testResponseJson",      
                contentType:"application/json;charset=utf-8", 
                data:'{"id":1,"name":"test","money":999.0}',     
                dataType:"json",     
                success:function(data){      
                    alert(data); 
                }    
            });   
        });  
    }) 
</script> 
<!-- 测试异步请求 --> 
<input type="button" value=" 测试 ajax请求 json和响应 json" id="testJson"/> 
@Controller("jsonController") 
public class JsonController {    
    /** 
    * 测试响应 json 数据   
    */  
    @RequestMapping("/testResponseJson")  
    public @ResponseBody Account testResponseJson(@RequestBody Account account) {       
        System.out.println("异步请求:"+account);   
        return account;  
    } 
}

2.4 SpringMVC实现文件上传

  • 前提
A form 表单的 enctype 取值必须是:multipart/form-data      
                    (默认值是:application/x-www-form-urlencoded)     
                enctype:是表单请求正文的类型 
B method 属性取值必须是 Post 
C 提供一个文件选择域<input type=”file” /> 

因为
当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。 
enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是:         
        key=value&key=value&key=value 
当 form 表单的 enctype 取值为 Mutilpart/form-data 时,请求正文内容就变成: 
每一部分都是 MIME 类型描述的正文
  • 导入相关依赖jar包(io,fileupload相关的jar包)
  • 编写jsp页面
  • 编写控制器
  • 配置文件解析器
<form action="/fileUpload" method="post" enctype="multipart/form-data"> 
    名称:<input type="text" name="picname"/><br/>  
    图片:<input type="file" name="uploadFile"/><br/>  
    <input type="submit" value=" 上传 "/> 
</form> 
@Controller("fileUploadController") 
public class FileUploadController {    
    /** 
    * 文件上传   
    */ 
    @RequestMapping("/fileUpload")  
    public String testResponseJson(String picname,MultipartFile uploadFile,HttpServletRequest request) throws Exception{   
        //定义文件名   
        String fileName = ""; 
        //1.获取原始文件名   
        String uploadFileName =  uploadFile.getOriginalFilename(); 
        //2.截取文件扩展名   
        String extendName = 
uploadFileName.substring(uploadFileName.lastIndexOf(".")+1, uploadFileName.length()); 
        //3.把文件加上随机数,防止文件重复   
        String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase(); 
        //4.判断是否输入了文件名   
        if(!StringUtils.isEmpty(picname)) {    
            fileName = uuid+"_"+picname+"."+extendName;   
        }else {    
            fileName = uuid+"_"+uploadFileName; 
        }   
        System.out.println(fileName); 
        //2.获取文件路径
        ServletContext context = request.getServletContext(); 
        String basePath = context.getRealPath("/uploads"); 
        //3.解决同一文件夹中文件过多问题   
        String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());   
        //4.判断路径是否存在   
        File file = new File(basePath+"/"+datePath);   
        if(!file.exists()) {    
            file.mkdirs();   
        }   
        //5.使用 MulitpartFile 接口中方法,把上传的文件写到指定位置   
        uploadFile.transferTo(new File(file,fileName));   
        return "success";  
    } 
} 
<!-- 配置文件上传解析器 --> 
 <!-- id 的值是固定的-->
<bean id="multipartResolver"   
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
    <!-- 设置上传文件的最大尺寸为 5MB -->  
    <property name="maxUploadSize">   
        <value>5242880</value>  
    </property> 
</bean> 
注意:  文件上传的解析器 id是固定的,不能起别的名称,否则无法实现请求参数的绑定。(不光是文件,其他 字段也将无法绑定) 

2.5 springmvc跨服务器的文件上传

  • 不同的服务器
    • 应用服务器:负责部署我们的应用
    • 数据库服务器:运行我们的数据库
    • 缓存和消息服务器:负责处理大并发访问的缓存和消息
    • 文件服务器:负责存储用户上传文件的服务器
  • 步骤

  • 准备两个 tomcat 服务器,并创建一个用于存放图片的 web 工程
  • 拷贝jar包(添加依赖)
  • 编写控制器实现上传图片
  • 编写jsp页面
  • 配置解析器
@Controller("fileUploadController2") 
public class FileUploadController2 {    
    public static final String FILESERVERURL = 
        "http://localhost:9090/day06_spring_image/uploads/";  
    /** 
    * 文件上传,保存文件到不同服务器   
    */  
    @RequestMapping("/fileUpload2")  
    public String testResponseJson(String picname,MultipartFile uploadFile) throws Exception{ 
        //定义文件名   
        String fileName = ""; 
        //1.获取原始文件名   
        String uploadFileName =  uploadFile.getOriginalFilename(); 
        //2.截取文件扩展名   
        String extendName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1, 
uploadFileName.length()); 
        //3.把文件加上随机数,防止文件重复   
        String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase(); 
        //4.判断是否输入了文件名   
        if(!StringUtils.isEmpty(picname)) {    
            fileName = uuid+"_"+picname+"."+extendName;   
        }else {    
            fileName = uuid+"_"+uploadFileName;   
        }   
        System.out.println(fileName);   
        //5.创建 sun 公司提供的 jersey 包中的 Client 对象   
        Client client = Client.create(); 
        //6.指定上传文件的地址,该地址是 web 路径   
        WebResource resource = client.resource(FILESERVERURL+fileName);   
        //7.实现上传   
        String result = resource.put(String.class,uploadFile.getBytes());   
        System.out.println(result);   
        return "success";  
    } 
}
<form action="fileUpload2" method="post" enctype="multipart/form-data"> 
    名称:<input type="text" name="picname"/><br/>  
    图片:<input type="file" name="uploadFile"/><br/>  
    <input type="submit" value="上传"/> 
</form> 
<!-- 配置文件上传解析器 --> 
<bean id="multipartResolver"   class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
    <!-- 设置上传文件的最大尺寸为 5MB --> 
    <property name="maxUploadSize">  
        <value>5242880</value>  
    </property> 
</bean>

3.6 SpringMVC中的异常处理

  • 编写异常类和错误页面
  • 自定义异常处理器
  • 配置异常处理器
public class CustomException extends Exception { 
    private String message; 
    public CustomException(String message) {   
        this.message = message;  
    } 
    public String getMessage() {   
        return message;  
    }
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 
<!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> 
        执行失败! 
        ${message } 
    </body> 
</html> 
public class CustomExceptionResolver implements HandlerExceptionResolver { 
    @Override 
    public ModelAndView resolveException(HttpServletRequest request,    HttpServletResponse response, Object handler, Exception ex) { 
        ex.printStackTrace();   
        CustomException customException = null;  
        //如果抛出的是系统自定义异常则直接转换   
        if(ex instanceof CustomException){    
            customException = (CustomException)ex;   
        }else{    
            //如果抛出的不是系统自定义异常则重新构造一个系统错误异常。    
            customException = new CustomException("系统错误,请与系统管理 员联系!");   
        }   
        ModelAndView modelAndView = new ModelAndView(); 
        modelAndView.addObject("message", customException.getMessage()); 
        modelAndView.setViewName("error");   
        return modelAndView;  
    } 
}
<bean id="handlerExceptionResolver"  
  class="com.itheima.exception.CustomExceptionResolver"/> 

3.7 SpringMVC中的拦截器

  • 编写一个普通类实现HandlerInterceptor接口
  • 配置拦截器
public class HandlerInterceptorDemo1 implements HandlerInterceptor { 
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {   
        System.out.println("preHandle 拦截器拦截了");   
        return true;  
    }
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {   
        System.out.println("postHandle 方法执行了");  
    } 
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {   
        System.out.println("afterCompletion 方法执行了");  
    } 
} 
<!-- 配置拦截器的作用范围 --> 
<mvc:interceptors>  
    <mvc:interceptor> 
        <mvc:mapping path="/**" /><!-- 用于指定对拦截的 url -->   
        <mvc:exclude-mapping path=""/><!-- 用于指定排除的 url-->   
        <bean id="handlerInterceptorDemo1"  
   class="com.itheima.web.interceptor.HandlerInterceptorDemo1"></bean>  
    </mvc:interceptor> 
</mvc:interceptors> 

第三章

3.1 SSM整合

  • 创建数据库和表结构
  • 创建Maven工程
  • 导入坐标引入依赖
  • 编写实体类
  • 编写业务层接口
  • 编写持久层接口
  • 保证Spring框架在web工程上独立运行
    • 编写spring配置文件并导入约束
    • 使用注解配置业务层和持久层
    • 测试spring能否独立运行
  • 保证SpringMVC在web工程独立运行
    • 在web.xml中配置核心控制器(DispatcherServlet)
    • 编写SpringMVC的配置文件
    • 编写Controller和jsp页面
  • 整合Spring和SpringMVC
    • 配置监听器实现启动服务创建容器
  • 保证MyBatis框架在web工程中独立运行
    • 编写AccountDao映射配置文件
    • 编写SqlMapConfig配置文件
    • 测试运行结果
  • 整合Spring和Mybatis
    • Spring接管MyBatis的Session工厂
    • 配置自动扫描所有Mapper接口和文件
    • 配置Spring的事物
    • 测试整合结果
  • 测试SSM整合结果
    • 编写测试jsp
    • 修改控制器的方法
    • 测试运行结果
create database ssm; 
create table account(  
    id int primary key auto_increment,  
    name varchar(100),  
    money double(7,2), 
);
@Service("accountService")
public class AccountServiceImpl implements AccountService{
    @Autowired
    private AccountDao accountDao;
    public List<Account> findAll() {
        System.out.println("业务层:查询所有账户...");
        return accountDao.findAll();
    }
    public void saveAccount(Account account) {
        System.out.println("业务层:保存帐户...");
        accountDao.saveAccount(account);
    }
}
@Repository
public interface AccountDao {
    // 查询所有账户
    @Select("select * from account")
    public List<Account> findAll();
    // 保存帐户信息
    @Insert("insert into account (name,money) values (#{name},#{money})")
    public void saveAccount(Account account);

}
//测试spring
public class Test01Spring { 
    public static void main(String[] args) {   
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");   
        IAccountService as = ac.getBean("accountService",IAccountService.class);   
        as.findAllAccount();  
    } 
}
//配置web.xml
<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!--配置Spring的监听器,默认只加载WEB-INF目录下的applicationContext.xml配置文件-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!--设置配置文件的路径-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <context-param>
    <param-name/>
    <param-value/>
  </context-param>

  <!--配置前端控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--加载springmvc.xml配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!--启动服务器,创建该servlet-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--解决中文乱码的过滤器-->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
</web-app>
//配置SpringMVC的配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启注解扫描,只扫描Controller注解-->
    <context:component-scan base-package="cn.itcast">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!--配置的视图解析器对象-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--过滤静态资源-->
    <mvc:resources location="/css/" mapping="/css/**" />
    <mvc:resources location="/images/" mapping="/images/**" />
    <mvc:resources location="/js/" mapping="/js/**" />

    <!--开启SpringMVC注解的支持-->
    <mvc:annotation-driven/>

</beans>
//编写jsp页面
<body>

    <a href="account/findAll">测试查询</a>

    <h3>测试包</h3>

    <form action="account/save" method="post">
        姓名:<input type="text" name="name" /><br/>
        金额:<input type="text" name="money" /><br/>
        <input type="submit" value="保存"/><br/>
    </form>

</body>
//控制器
@Controller
@RequestMapping("/account")
public class AccountController {

    @Autowired
    private AccountService accountService;

    @RequestMapping("/findAll")
    public String findAll(Model model){
        System.out.println("表现层:查询所有账户...");
        // 调用service的方法
        List<Account> list = accountService.findAll();
        model.addAttribute("list",list);
        return "list";
    }

    /**
     * 保存
     * @return
     */
    @RequestMapping("/save")
    public void save(Account account, HttpServletRequest request, HttpServletResponse response) throws IOException {
        accountService.saveAccount(account);
        response.sendRedirect(request.getContextPath()+"/account/findAll");
        return;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!