SSM学习笔记

maven

什么是maven

项目管理工具

pom

mybatis参数

     ## 单个javabean

默认通过书信值引用。

多个参数

Girl queryByNameFlower(@Param("name") String name,@Param("flower") String flower);
<!--SELECT * FROM girl WHERE  name = #{param1} AND  flower = #{param2}-->
  <!--SELECT * FROM girl WHERE  name = #{arg0} AND  flower = #{arg1}-->
  SELECT * FROM girl WHERE  name = #{name} AND  flower = #{flower}

map

Map<String,Object> map = new HashMap<>();
map.put("name","he");
map.put("flower","flowerLi");

sql语句中直接用名称取值

多个javabean

类似于多个参数,只不过参数变成了对象

一组值的传入(List集合)

SQL标签

<!--foreach
    collection 描述集合
    open 以什么拼接符号开头
    close 以什么结尾
    item 一个数据项的代号
    separator item之间的分隔符
    index 如需使用标号,也可使用
    -->
<!--使用where标签,使得语法合法,
   自动消除多余的and,只能处理前置的and。
   if标签里有多个条件,则用and连接。
-->
<!--例如:传入非空值是修改,否则不修改.
set标签纠正语法,去掉后置的多余逗号。
-->

trim标签

<trim prefix="where" suffixOverrides="and">
    <if test="city != null">
        CITY = #{city} AND
    </if>
    <if test="country != null">
        COUNTRY = #{country}  AND
    </if>
</trim>
解决字符串拼接问题
1.可用sql函数
select * from address
where
city like concat('%',#{city},'%')

2.bind标签
<bind name="_city" value="'%'+city+'%'"/>
select * from address
where
city like #{_city}

sql标签

<sql id="baseCoulmn">
    city,country,state
</sql>

select <include refid="baseCoulmn"/>
from address

cach缓存

默认情况下,一级缓存是开启的,且无法关闭。

一级缓存是单个会话级别的

  1. 如果关闭会话,缓存失效。
  2. 如果会话过程有增删改操作,则缓存失效。
  3. java中 sqlSession.clearCache();清掉所有缓存

二级缓存是多个会话级别的

<setting name="cacheEnabled" value="true">

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

多表查询映射

<resultMap id="rMap" type="javaClass">
    <id property="id" column="id"/>
    <result property="id" column="id"/>
    <association property="\\class" javaType="">
        <result property="" column=""/>
    </association>
</resultMap>
<!--
collection标签用来描述集合
ofType是描述集合里的一个元素的类型
-->
List<Comment> comments;
    
<collection property="comments"
             ofType="self.he.pojo.Comment">
  <id property="id" column="cid"/>
  <result property="content" column="commentContent"/></collection>

spring

  1. 添加spring依赖
  2. 编写spring的配置文件
  3. 通过spring应用程序上下文获取对象

1.依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.4.RELEASE</version>
</dependency>

2.配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
<!--将对象的创建-交给spring容器,
    在配置文件里声明需要的对象。
    class:Java类的全限定名
    id: 此对象的昵称方便区分-->
    <bean class="self.he.pojo.Girl" id="girl">

    </bean>
</beans>

3.java代码

public class Girl {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
public void  m1(){
    //获取上下文对象,spring里面声明对象都需要通过上下文获取
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    //通过此对象获取girl
    Girl g = (Girl) ctx.getBean("girl");
    System.out.println(g);
}

核心内容

  • IOC
  • AOP

IOC

概念:控制反转。

将对象的创建交给Spring容器。

值的注入:

  • setter注入(最常用)

    • 必须有setter方法,如:name setName()

    • 用property标签注入

    • <bean class="self.he.pojo.PrettyGirl" id="girl">
          <property name="name" value="王妃"/>
      </bean>
      
    • 非字面值的注入问题:使用ref指向另一个bean

    • <bean class="self.he.pojo.Dog" id="dog">
          <property name="name" value="汪汪"/>
      </bean>
      <bean class="self.he.pojo.PrettyGirl" id="girl">
          <property name="dog" ref="dog"/>
      </bean>
      
    • String[]

    • <property name="friends">
          <array>
              <value>钰子</value>
              <value>雨子</value>
              <value>呀子</value>
          </array>
      </property>
      
    • List<>

    • <property name="nums">
          <list>
              <value>1</value>
              <value>3</value>
              <value>4</value>
          </list>
      </property>
      
    • set<>

    • <property name="grils">
          <set>
             <bean class="self.he.pojo.Girl">
                 <property name="age" value="18"/>
                 <property name="name" value="Li"/>
             </bean>
              <bean class="self.he.pojo.Girl">
                  <property name="age" value="11"/>
                  <property name="name" value="She"/>
              </bean>
          </set>
      

      Map<>

    • <property name="goddessMap">
          <map>
              <entry key="Li">
                  <bean class="self.he.pojo.Goddess">
                      <property name="name" value="Li"/>
                      <property name="hair" value="Red"/>
                  </bean>
              </entry>
              <entry key="Di">
                  <bean class="self.he.pojo.Goddess">
                      <property name="name" value="Di"/>
                      <property name="hair" value="Black"/>
                  </bean>
              </entry>
          </map>
      </property>
      
  • 构造器注入

    • 默认使用无参构造器

    • constructor-arg标签

    • <bean class="self.he.pojo.Cat" id="girl">
          <constructor-arg name="name" value="Li"/>
          <constructor-arg name="color" value="red"/>
      </bean>
      

bean标签的探讨:

  • abstract:抽象
  • parent:继承bean标签
  • destory-method: 这个bean销毁是执行的方法。容器close(),refresh()
  • init-method: 初始化时使用的方法。
  • scope:指定范围
    • singleton:单例,spring上下文
    • prototype:原型
  • lazy-init: true使用时初始化。
  • depends-on: 依赖bean,如果bean的使用严重依赖于另一个bean。

alias标签:

  • 注入别名

  • <alias name="dog" alias="gdog"/>
    
  • 自动注入,autowire属性

  • byType

  • byName

  • constructor:根据构造器的参数名去匹配bean。

  • no

  • <!--byType
        在上下文中,根据类型寻找cat 中的属性 girl,并以赋值,有且只有一个,否则报错-->
    <bean class="self.he.pojo.Cat" id="cat" autowire="byType">
        <property name="name" value="佩奇"/>
        <property name="color" value="pik"/>
    </bean>
    <bean class="self.he.pojo.Girl">
        <property name="name" value="Li"/>
        <property name="age"  value="18"/>
    </bean>
    <bean class="self.he.pojo.Cat" id="girl">
        <constructor-arg name="name" value="Li"/>
        <constructor-arg name="color" value="red"/>
    

resource

  • Xml文件里引入其他properties文件:

  • <context:property-placeholder location="classPath:xxx.properties"/>
    <!--用表达式${}去引用properties的属性的值,-->
    
    
  • 一个配置文件引入其他配置文件:classPath的根目录是resource目录

  • <import resource="classPath:xxx.xml"/>
    

常用注解

xml中要激活注解:

<context:component-scan base-package="self.he"/>
  • component
  • controller
  • service
  • repository
  • autowired自动注入

AOP

概念

面向切面编程。

依赖包:

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.2</version>
    </dependency>
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:aop="http://www.springframework.org/schema/aop"
       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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--1 aop是基于代理完成的,所以要激活自动代理-->
    <aop:aspectj-autoproxy/>
    <!--2 注册切面-->
    <bean class="self.he.advice.BeforeAdvice" id="beforeAdvice">
    </bean>
    <!--3 配置切入点等信息-->
    <aop:config>
        <aop:aspect id="beforeAspect" ref="beforeAdvice">
            <!--aop:before 表明前置通知
                method:指明使用哪个方法切
                pointcut:切入点
                          包,类,方法
            -->
            <aop:before method="methodBefore" pointcut="execution(* self.he.service.ProviderService.*(..))"></aop:before>
        </aop:aspect>
    </aop:config>

    <bean class="self.he.service.ProviderService"
          id="providerService"></bean>

</beans>

execution()表达式:

例如:execution(* self.he.service.ProviderService.*(..))

测试
@Test
public void m1(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/applicationContext.xml");

    //不是spring管理的bean,织入无效。
    ProviderService providerService = new ProviderService();
    providerService.add();

    ProviderService providerService1 = ctx.getBean("providerService", ProviderService.class);
    providerService1.add();
}

返回执行:after-returning

<aop:after-returning method="AfterReturn" returning="returning" pointcut="execution(* self.he.service.HelloService.*(..))"/>


注解模式

xml文件

<!--1 自动代理-->
<aop:aspectj-autoproxy/>

<!--2 配置自动扫描包-->
<context:component-scan base-package="self"/>

切面:

@Aspect//标记为一个切面
@Component//标记为一个组件,相当于在xml中注册一个bean
public class BeforeAdvice {
    @Before("execution(* self.she.service.HelloService.hello(String,String))")
    //获取方法名,参数
    public void before(JoinPoint joinPoint){
        System.out.println("before!!!!!"+joinPoint.getSignature().getName()+ Arrays.toString(joinPoint.getArgs()));
    }
    @Before("execution(* self..*.*(..))")
    public void before2(){
        System.out.println("before2!!!");
    }
}

切点:

@Component
public class HelloService {
    public void hello(String name,String sex){
        System.out.println("hello "+name+"!"+sex+"!!!");
    }
    public String eat(){
        System.out.println("eating!!!!");
        return "Li";
    }
}

注解方式获得bean

配置类

@Configuration
@ComponentScan(value = "self.she")
public class SpringConfig {

    @Bean("girl")
    public Girl creatGirl(){
        Girl girl = new Girl();
        girl.setName("Li");
        return girl;
    }

}

测试:

@Test
public void  m1(){
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
    Girl girl = ctx.getBean("girl",Girl.class);
    System.out.println(girl.getName());
}

springMVC

简介

springMVC是一个web层的框架。

model 模型

view 视图

controller 控制器

一种设计模式,将责任进行拆分,不同组件负责不同功能。

好处:

  • 结构清晰
  • 更好维护

坏处:

  • 更加复杂

入门体验

1.创建web项目

2.编写web.xml,注册一个特殊的servlet,前端控制器

3.编写一个springMVC的配置文件

  1. 注册一个视图解析器

4.编写一个控制器

5.编写一个结果页面

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
  <!--注册一个前端控制器-->
  <servlet>
    <!--这里名字有讲究,
        如果不修改spring配置文件的默认位置,那么springmvc
        会去web-inf下找一个springmvc-servlet.xml的文件-->
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  
  <!--servlet映射配置-->
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--统一写/-->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

pom.xml:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.1.4.RELEASE</version>
</dependency>

控制器代码:

package self.he.controller;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {


    @Nullable
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mav = new ModelAndView();
        mav.addObject("girl","Li");
        mav.setViewName("girl");
        return mav;
    }
}

视图代码:

<%--
  Created by IntelliJ IDEA.
  User: he
  Date: 2019/2/13
  Time: 16:19
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${girl}
</body>
</html>

解释分析

web.xml

注册前端控制器,目的让springmvc去处理请求

<!--servlet映射配置-->
<servlet-mapping>
  <servlet-name>springmvc</servlet-name>
  <!--统一写/-->
  <url-pattern>/</url-pattern>
</servlet-mapping>

url-pattern的写法问题:

  • /
  • /* (永远不要这样写,请求helloController时,过去后视图为girl.jsp,又将girl.jsp作为请求再去访问controller)
  • *.do

springMVC配置文件名

web.xml

默认情况下使用dispatcherServlet的名字作为命名空间

[servlet-name]-servlet.xml (WEB-INF)下寻找

[servlet-name]-servlet=namespace

<servlet>
  <!--这里名字有讲究,
      如果不修改spring配置文件的默认位置,那么springmvc
      会去web-inf下找一个springmvc-servlet.xml的文件-->
  <servlet-name>springmvc</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--重新命名配置文件名-->
  <init-param>
    <param-name>namespace</param-name>
    <param-value>mvc</param-value>
  </init-param>
</servlet>

配置文件默认在WEB-INF下,但是maven项目要求在resources目录下。

解决:重新指定上下文位置即可web.xml

<init-param>
  <!--上下文配置的位置的指定-->
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:mvc.xml</param-value>
</init-param>

此时在类路径下寻找mvc.xml

视图解析器

springMVC支持多种视图技术

  • jsp
  • freemaker(模板技术)

内部的资源视图解析器

  • 视图前缀

    • /jsp/ 请求响应的资源路径配置

      viewName:girl /jsp/girl

  • 后缀

    • .jsp 此时前缀+视图名+后缀 = /jsp/girl.jsp

注解开发模式

基本注解;

  • @Controller
  • @RequestMapping

开发步骤

1.配置注解扫描包

<!--配置注解扫描包-->
 <context:component-scan base-package="self.he.controller"/>


<!--配置一个视图解析器
        常用内部资源视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--1 前缀-->
        <property name="prefix" value="/jsp/"/>
        <!--2 后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>


2.在指定类上添加@Controller注解

3.添加@RequestMapping

@Controller//不需要继承任何类
@RequestMapping("/bye")
public class ByeController {

   @RequestMapping("/bye")
    public String bye(Model model){
       model.addAttribute("model","Li");
       // return的是ViewName
       //此时去的/jsp/bye.jsp
       return "bye";
    }

    @RequestMapping("/goodBye")
    public String goodBye(Model model){
        model.addAttribute("model","Lily");
        return "bye";
    }
}

list 问题

导入依赖

<!--jstl依赖-->
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
</dependency>

controller:

@RequestMapping("/byeBye")
public String byeBye(Model model){
    List<People> list = new ArrayList<>();
    People p1 = new People();
    p1.setName("Li");
    p1.setSex("girl");
    People p2 = new People();
    p2.setName("He");
    p2.setSex("boy");
    list.add(p1);
    list.add(p2);
    model.addAttribute("model",list);
    return "byeBye";
}

jsp:

<c:forEach items="${model}" var="obj">
    <tr>
        <td>${obj.name}</td>
        <td>${obj.sex}</td>
    </tr>
</c:forEach>

转发与重定向

  • 转发到页面

  • 重定向到另一个页面redirect:path

    @RequestMapping("redirect")
    public String redirect(Model model){
        model.addAttribute("model","hello");
        return "redirect:/jsp/redirect.jsp";
    }
    
  • 转发到另一个控制器forward:path

  • //    模拟请求
        @RequestMapping("/request")
        public String request(WebRequest request){
            System.out.println(request.getParameter("girl"));
            return "forward";
        }
    

@RequestMapping

  • @RequestMapping("/m1")
  • value 写的是路径,是一个数组的形式,可匹配多个路径,path与 value对等
    • @RequestMapping(value={"m1","m2"})
  • method 指定接收的请求类型,如果没写就所有类型都接收
    • @RequestMapping(value={"m1","m2"}, method= RequestMethod.GET)
  • params 可以指定参数
    • @RequestMapping(value="/m1",params={"girl","boy"})
    • 可以指定值params={"girl=王妃","boy!=爱卿"}
  • header 能够影响浏览器的行为
  • consumers 消费者,媒体类型,可以限定必须为application/json;chartset=UTF-8
  • produces 产生的响应的类型

请求路径的问题

Springmvc支持的ant风格

@RequestMapping("/Li?")

  • ?任意的字符,斜杠除外
  • *表示0-n,任意个字符都行,斜杠除外
  • /** 支持任意层路径

@GetMapping,@PostMapping.....

  • getMapping 只限定了get请求
  • postMapping 只限定了post请求

对于非get post请求的支持

需要有额外的内容添加,要增加一个过滤器来处理。

过滤器:

<!--注册一个支持所有http请求类型的过滤器-->
<filter>
  <filter-name>hiddenHttpMethodFilter</filter-name>
  <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>hiddenHttpMethodFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

表单还要添加隐藏参数;

delete
<form action="${ctx}/he/m1" method="post">
    <input type="hidden" name="_method" value="DELETE"/>
    <input type="submit" value="提交"/>
</form>

关于静态资源访问的问题

用于在web.xml中设置了servlet的url匹配方式为/ ,所以静态资源也当做一个后台请求。

解决方式:

1.交给默认servlet处理。不让DispatcherServlet处理。

在mvc配置文件中加

<!--默认servlet处理者,识别MIME类型-->
 <!--默认servlet处理者,只加它注解会失效-->
    <mvc:default-servlet-handler/>
    <!--重新激活注解模式-->
    <mvc:annotation-driven/>

2.通过映射关系描述

<mvc:resources mapping="/static/css/*" location="static/css/"/>

3.在web.xml定义映射规则

@PathVariable

路径变量。

@RequestMapping("/add/{name}/{sex}")
public String addPeople(@PathVariable("name") String name,@PathVariable("sex")String sex){
    System.out.println(name+":"+sex);
    return "forward";
}

@Responsebody

返回数据,一般情况下返回json格式数据。

    @PutMapping("/put")
    @ResponseBody//需要额外的json包的支持
    public String putPeople(String name){
        System.out.println(name+":");
//        Map<String,String> map = new HashMap<>();
//        map.put("msg","ok");
        return "ok";
    }

@RequestBody

json数据,不是通过form表单传递

ajax({

​ data:

​ } )

@SessionAttributes

用在类上面,将模型自动填充到会话里去。

@Controller
@RequestMapping("/people2")
@SessionAttributes("people")
public class People2Controller {
        @RequestMapping("/login3")
    public String login3(@ModelAttribute People people)     {
        System.out.println(people.getName());
        return "redirect:/jsp/login.jsp";
    }

}

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
 ${sessionScope.people.name}
</body>
</html>

@SessionAttribute

要求当前会话里必须要有某个对象。

 public String login3(@SessionAttribute People people)     {
        System.out.println(people.getName());
        return "redirect:/jsp/login.jsp";
    }

关于post请求中文乱码问题

添加过滤器,springmvc提供过滤器。

 <!--指定编码,这段配置要放在所有filter的最前面,否则会不生效-->
  <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>

关于form表单提交数据方式

方式一:通过属性名绑定

put people
<form action="${ctx}/people/put" method="post">
    <input type="hidden" name="_method" value="put"/>
    <input type="text" name="name"/><br>
    <input type="password" name="sex"/><br>
    <input type="submit" value="提交"/>
</form>
 @PutMapping("/put")
    @ResponseBody//需要额外的json包的支持
    public String putPeople(String name,String sex){
        System.out.println(name+":"+sex);
//        Map<String,String> map = new HashMap<>();
//        map.put("msg","ok");
        return "ok";
    }

方式二:@RequestParam()

 @PutMapping("/put")
    @ResponseBody//需要额外的json包的支持
    public String putPeople(@RequestParam("name")String name,@RequestParam("sex")String sex){
        System.out.println(name+":"+sex);
//        Map<String,String> map = new HashMap<>();
//        map.put("msg","ok");
        return "ok";
    }

方式三:直接用pojo形式

 @PutMapping("/put")
    @ResponseBody//需要额外的json包的支持
    public String putPeople(People people){
        System.out.println(people.getName()+":"+people.getSex());
        return "ok";
    }

关于表单提交date类型数据问题

put people and date
<form action="${ctx}/people/date" method="post">
    <input type="date" name="date"/><br>
    <input type="submit" value="提交"/>
</form>
@InitBinder
public void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    dateFormat.setLenient(false);
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}

 @PostMapping("/date")
    @ResponseBody//需要额外的json包的支持
    public String postPeople(People people){
        System.out.println("hhhh");
        System.out.println(people.getDate());
        return "ok";
    }

2.在属性上添加注解

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;

@ModelAttribute可解决页面间数据交换

使用方式一:

//在controller里任意一个方法执行前执行
@ModelAttribute
public People init(){
    System.out.println("init........");
    People people = new People();
    people.setName("Li");
    return people;
}

@RequestMapping("/login")
public String login(Model model){
    System.out.println(model.containsAttribute("people"));
    return "forward";
}

方法二:

@ModelAttribute("people")
public void init(Model model){
    System.out.println("init........");
    People people = new People();
    people.setName("Li");
    model.addAttribute("people",people);
}

方法三:

如果请求页面传了people则使用请求的值,如果没有则使用默认的。

可用于页面间数据交换。

@RequestMapping("/login2")
public String login2(@ModelAttribute People people){
    System.out.println(people.getName());
    return "login";
}
post people to other page
<form action="${ctx}/people2/login2" method="post">
    <input type="text" name="name"/><br>
    <input type="password" name="sex"/><br>
    <input type="submit" value="提交"/>
</form>

后台传json给前端

1.导入json解析依赖

<!--json依赖-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.9.8</version>
</dependency>

2.利用@ResponseBody

@RequestMapping("m1")
@ResponseBody
public People m1(){
    People people = new People();
    people.setName("Li");
    people.setSex("girl");
    people.setDate(new Date());
    return people;
}

前台解析json:

<script>
    $(function () {
        $("#b").click(function () {
            $.ajax({
                url:'${ctx}/json/m1',
                type:'post',
                success:function (data) {
                    alert(data.name+":"+data.sex)
                }
            })
        })
    })

</script>

前台ajax给后台传json

注意 contentType:'application/json',不可缺
$("#bb").click(function () {
    var obj={
        'name':'Li 李',
        'sex':'girl'
    };

    $.ajax({
        url:'${ctx}/json/m2',
        type:'post',
        contentType:'application/json',
        data:JSON.stringify(obj),
        success:function (data) {
                 alert(data.name);
                }
    })
})

后台用注解@RequestBody接收

//接收前台传来的json
@RequestMapping("/m2")
@ResponseBody
public People m1(@RequestBody People people){
    System.out.println(people.getName());
   People people = new People();
    people.setName("Li");
    people.setSex("girl");
    people.setDate(new Date());
    return people;
}

@RestController=@Controller+@ResponseBody

xml解析传输

很多第三方开发会使用xml传输数据,例如:微信

1.添加xml依赖

<!--xml依赖-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
  <version>2.9.8</version>
</dependency>

2.@RequestMapping

@RequestMapping(value = "/m1",produces ={MediaType.APPLICATION_XML_VALUE})
@ResponseBody
public People m1(){
    People people = new People();
    people.setName("Lily");
    people.setSex("girl");
    people.setDate(new Date());
    return people;
}

文件上传

1.加入依赖

<!--Apache文件上传依赖-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.4</version>
</dependency>

2.在springmvc配置文件中注册文件上传解析器

<!--文件上传解析器,
     id="multipartResolver"只能是这个,源代码规定的
     -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <!--定义最大文件上传大小,byte-->
    <property name="maxUploadSize" value="1024000"/>
    <!--指定上传的编码-->
    <property name="defaultEncoding" value="UTF-8"/>
    <!--单个文件最大大小-->
    <property name="maxUploadSizePerFile" value="200000"/>
    
</bean>

3.上传页面

<%--
  Created by IntelliJ IDEA.
  User: he
  Date: 2019/2/15
  Time: 9:39
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
单文件提交:
<form action="${ctx}/file/upload" method="post" enctype="multipart/form-data">
    文件:<input type="file" name="file"/><br>
    <input type="submit" value="提交">
</form>
<br>
多文件提交:
<form action="${ctx}/file/upload2" method="post" enctype="multipart/form-data">
    文件1:<input type="file" name="file"/><br>
    文件2:<input type="file" name="file"/><br>
    文件3:<input type="file" name="file"/><br>
    文件4:<input type="file" name="file"/><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

4.响应控制类

 private static String uploadPath = "E:"+ File.separator;

 @RequestMapping("/upload")
public String upload(@RequestParam("file")MultipartFile multipartFile, Model model){
     //1.传到哪里去。2.数据 3.传的细节
    if (multipartFile != null && !multipartFile.isEmpty()){
        //不空再传
        //1.获得文件名
        String originalFilename = multipartFile.getOriginalFilename();
        //2.截取文件名前缀
        String fileNamePrefix = originalFilename.substring(0,originalFilename.lastIndexOf('.'));
        //3.构建新文件名 前缀+时间戳
        String newFilePrefix = fileNamePrefix+new Date().getTime();
        //4.得到新文件名
        String newFileName =newFilePrefix+originalFilename.substring(originalFilename.lastIndexOf('.'));
        //5.构建文件对象
        File file = new File(uploadPath+newFileName);

        //6.写入文件
        try {
            multipartFile.transferTo(file);
            model.addAttribute("fileName",newFileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return "uploadSuc";
}

@RequestMapping("/upload2")
 public String upload2(@RequestParam("file") MultipartFile[] multipartFiles,Model model){
    List<String> fileNames = new ArrayList<>();
    System.out.println(multipartFiles != null && multipartFiles.length >0);
    if (multipartFiles != null && multipartFiles.length >0){
        for (MultipartFile multipartFile:multipartFiles) {
            if (multipartFile != null && !multipartFile.isEmpty()){
                //不空再传
                //1.获得文件名
                String originalFilename = multipartFile.getOriginalFilename();
                //2.截取文件名前缀
                String fileNamePrefix = originalFilename.substring(0,originalFilename.lastIndexOf('.'));
                //3.构建新文件名 前缀+时间戳
                String newFilePrefix = fileNamePrefix+new Date().getTime();
                //4.得到新文件名
                String newFileName =newFilePrefix+originalFilename.substring(originalFilename.lastIndexOf('.'));
                //5.构建文件对象
                File file = new File(uploadPath+newFileName);

                //6.写入文件
                try {
                    multipartFile.transferTo(file);

                    fileNames.add(newFileName);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    model.addAttribute("fileNames",fileNames);
    return "uploadSuc";
}

文件下载

@RequestMapping("/down")
    public void fileDown(HttpServletResponse response){
        //通过输出流写入客户端
//       response.setCharacterEncoding("UTF-8");
       //1.获取下载文件名
       String fileName = "哈哈.jpg";
       //2.构建一个文件对象,通过Paths工具类获得Path对象
       Path path = Paths.get(uploadPath,fileName);

       //3.判断它是否存在
       if(Files.exists(path)){
           //存在则下载
           //4.设定response的响应类型
                //获取文件后缀
           String fileSuffix = fileName.substring(fileName.lastIndexOf('.')+1);
                //设置contentType
           response.setContentType("application/"+fileSuffix);
           try {
               //ISO8859-1编码
               response.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes("UTF-8"),"ISO8859-1"));
           } catch (UnsupportedEncodingException e) {
               e.printStackTrace();
           }
           System.out.println(fileSuffix);
           //5 通过Path写出去
           try {
               Files.copy(path,response.getOutputStream());
           } catch (IOException e) {
               e.printStackTrace();
           }
       }

   }

注意事项: //ISO8859-1编码
response.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes("UTF-8"),"ISO8859-1"));

避免中文无法识别

拦截器

通过实现HandlerInterceptor

  • 前置处理
  • 后置处理
  • 完成处理

案例:

登录请求拦截,如果session有user,不拦截,没有则拦截,但/user/login不拦截。

1.拦截类

package self.he.interceptors;

import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import self.he.pojo.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SessionInterceptor implements HandlerInterceptor{


    private static final Logger LOGGER = Logger.getLogger(SessionInterceptor.class);

    //检查当前会话是否有User,有则放行,没有则拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        Object user = request.getSession().getAttribute("SESSION_USER");

        if(user == null){
            LOGGER.warn("没有权限,请先登录!");
            return false;
        }

        if(user instanceof User){
            //查数据库检查
            User u = (User)user;
            u.setPwd(null);
            request.getSession().setAttribute("SESSION_USER",u);
            LOGGER.info(u.getName()+"会话中。。");
            return true;

        }else {
            LOGGER.warn("不要搞事,请先登录!");
            return false;
        }

    }
}

2.配置拦截器

<!--拦截器配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**/*"/>
        <bean class="self.he.interceptors.MethodTimerInterceptor">

        </bean>
    </mvc:interceptor>

    <mvc:interceptor>
        <!-----------------------------------------------
            拦截user下的,但login除外
        -->
        <mvc:mapping path="/user/**/*"/>
        <mvc:exclude-mapping path="/user/login"/>
        <bean class="self.he.interceptors.SessionInterceptor">
       </bean>
    </mvc:interceptor>
</mvc:interceptors>

控制类:

package self.he.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import self.he.pojo.User;

import javax.servlet.http.HttpSession;

@Controller
@RequestMapping("/user")
public class UserController {


    @RequestMapping("/login")
    public String login(User user, HttpSession session){

        if(user != null&& user.getName()!= null && user.getName().equals("Li")){
            //(数据库检查)
            session.setAttribute("SESSION_USER",user);
            return "user";
        }
        System.out.println("....login...........");
        return "redirect:/login.jsp";
    }

    @RequestMapping("/delete")
    public String delete(){
        System.out.println("....可以为所欲为了delete...........");
        return "user";
    }
}

拦截器执行顺序问题

有N个拦截器,都能拦截同一个URI时,执行顺序:

在springmvc配置中配置的顺序有关。配置在前的先执行。

前置处理与后置处理顺序刚好相反。

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

推荐阅读更多精彩内容