轻量级框架
aop(面向切面编程,切面修改源代码)、ioc(控制反转,创建组件)
一站式框架web层:springMVC
service层:spring的ioc
dao层:spring的jdbcTemplate官方建议配置文件(名称 位置没要求 ): applicationContext.xml
-->xiaokai
实体类的无参数构造创建(重点)
<bean id="user" class="cn.itcast.ioc.User" scope="prototype">bean>
如果只有有参构造,没有无参构造,会报如下错:No default constructor found
静态工厂创建(工厂方法是static)
创建静态的方法,返回类对象
public class Bean2Factory {
//静态的方法,返回Bean2对象
public static Bean2 getBean2(){
return new Bean2();
}
}
xml中配置
<bean id="bean2" class="cn.itcast.bean.Bean2Factory" factory-method="getBean2">bean>
实例工厂创建(方法不是静态的)
创建不是静态的方法,返回类对象
public class Bean3Factory {
public Bean3 getBean3() {
return new Bean3();
}
}
xml配置
<bean id="bean3Factory" class="cn.itcast.bean.Bean3Factory">bean>
<bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3">bean>
Bean标签常用属性
(1)id属性:起名称,id属性值名称任意命名
- id属性值,不能包含特殊符号
- 根据id值得到配置对象
(2)class属性:创建对象所在类的全路径
(3)scope属性
- singleton:默认值,单例
- prototype:多例
- request:创建对象把对象放到request域里面
- session:创建对象把对象放到session域里面
- globalSession:创建对象把对象放到globalSession里面
有参构造注入
//代码
public class PropertyDemo1 {
private String username;
public PropertyDemo1(String username) {
this.username = username;
}
public void test1() {
System.out.println("demo1.........."+username);
}
}
<bean id="demo" class="cn.itcast.property.PropertyDemo1"> -->
<constructor-arg name="username" value="小王小马">constructor-arg>
bean>
set方法注入(重点)
private String bookname;
//set方法
public void setBookname(String bookname) {
this.bookname = bookname;
}
方式一:
(**重点**)
<bean id="book" class="cn.itcast.property.Book"> -->
<property name="bookname" value="易筋经">property>
bean>
方式二:
beans标签内加入属性:xmlns:p="http://www.springframework.org/schema/p"
beans标签内加入子标签:
<bean id="book" class="cn.itcast.property.Book" p:bookname="易筋经">bean>
第一步 创建实体类,定义成员变量数组arrs,List数组list,Map集合map,Properties类型properties;创建这几个成员变量的set方法
第二步 xml配置
<bean id="person" class="cn.itcast.property.Person">
<property name="arrs">
<list>
<value>小王value>
<value>小马value>
<value>小宋value>
list>
property>
<property name="list">
<list>
<value>小奥value>
<value>小金value>
<value>小普value>
list>
property>
<property name="map">
<map>
<entry key="aa" value="lucy">entry>
<entry key="bb" value="mary">entry>
<entry key="cc" value="tom">entry>
map>
property>
<property name="properties">
<props>
<prop key="driverclass">com.mysql.jdbc.Driverprop>
<prop key="username">rootprop>
props>
property>
bean>
创建service类和dao类,在service得到dao对象(不通过new出来)
具体实现过程
//1 定义dao类型属性
private UserDao userDao;
//2 生成set方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
<bean id="userService" class="cn.itcast.ioc.UserService"> -->
<property name="userDao" ref="userDao">property>
bean>
1 ) 导入jar包
基本jar包:
spring-beans.jar
spring-context.jar
spring-core.jar
spring-expression.jar
commons-logging.jar
log4j.jar
注解jar包:
spring-aop-4.2.4.jar
2 ) 创建spring配置文件,引入约束
<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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
beans>
<context:component-scan base-package="cn.itcast">context:component-scan>
3 ) 具体注解
注解创建对象
@Component
@Controller :web层
@Service :业务层
@Repository :持久层
@Scope(value="")
不写这个属性默认是单实例
具体见上面的:Bean标签常用属性知识点
注解注入属性
第一个注解方式:
//得到dao对象
//1 定义dao类型属性
//在dao属性上面使用注解 完成对象注入
@Autowired
private UserDao userDao;
第二个注解方式:(更直观)
// name属性值 写 注解创建dao对象 value值
@Resource(name="userDao")
private UserDao userDao;
默认使用规则
创建对象操作使用配置文件,属性注入使用注解
1 ) 需要jar包/aop约束
aopalliance.jar
aspectjweaver.jar
spring-aop.jar
spring-aspects.jar
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
2 ) 使用表达式配置切入点
切入点: 实际增强的方法
常用表达式: 格式:execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
例子:
(1)execution(* cn.itcast.aop.Book.add(..))---->*表示任意修饰;cn.itcast.aop.book类中的add(..)方法增强;add(..)中两个..表示任意参数
(2)execution(* cn.itcast.aop.Book.*(..))---->book类中的所有方法
(3)execution(* *.*(..))---->所有类中的所有方法
(4) 匹配所有save开头的方法 execution(* save*(..))
xml配置
目标: 执行cn.itcast.aop.Book中的add()时,默认先执行MyBook中的增强方法
xml配置(beans标签内):
<bean id="book" class="cn.itcast.aop.Book">bean>
<bean id="myBook" class="cn.itcast.aop.MyBook">bean>
<aop:config>
<aop:pointcut expression="execution(* cn.itcast.aop.Book.*(..))" id="pointcut1"/>
<aop:aspect ref="myBook">
<aop:before method="before1" pointcut-ref="pointcut1"/>
<aop:after-returning method="after1" pointcut-ref="pointcut1"/>
<aop:around method="around1" pointcut-ref="pointcut1"/>
aop:aspect>
aop:config>
环绕增强的实体类方法:
//环绕通知
//参数ProceedingJoinPoint会默认调用被增强的方法执行
public void around1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//方法之前
System.out.println("方法之前.....");
//执行被增强的方法
proceedingJoinPoint.proceed();
//方法之后
System.out.println("方法之后.....");
}
注解
创建对象
<bean id="book" class="cn.itcast.aop.Book">bean>
<bean id="myBook" class="cn.itcast.aop.MyBook">bean>
在spring核心配置文件中,开启aop操作
<aop:aspectj-autoproxy>aop:aspectj-autoproxy>
在增强类上面使用注解完成aop操作
@Aspect
public class MyBook {
//在方法上面使用注解完成增强配置
@Before(value="execution(* cn.itcast.aop.Book.*(..))")
public void before() {
System.out.println("before.......");
}
}
@Before :前置通知
@AfterReturing :后置通知
@Around :环绕通知
@After :最终通知
@AfterThrowing :异常抛出通知
```
针对spring中服务器启动时加载配置文件,自动创建对象放到ServletContext域中,需要导入spring-web.jar
//在web.xml中配置
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:bean1.xmlparam-value>
context-param>
注意:默认到WEB-INF下面找applicationContext.xml文件,实际我们不是放到这个路径也不叫这个名称,所以需要自己配置路径
以及jdbcTemplate/jdbc/dbutils的对比,看spring笔记
xml
配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
配置事务增强
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="account*" propagation="REQUIRED"/>
tx:attributes>
tx:advice>
配置切面
<aop:config>
<aop:pointcut expression="execution(* cn.itcast.service.OrdersService.*(..))" id="pointcut1"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/>
aop:config>
注解
配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
配置事务注解扫描
<tx:annotation-driven transaction-manager="transactionManager"/>
使用注解
//有注解的类,类里面的所有方法都加事务管理
@Transactional
public class OrdersService() {
}
//创建对象(标注在类上)
@Component
@Controller :web层
@Service :业务层
@Repository :持久层
//创建对象时是否使用单实例(标注在类上)
//不写这个属性默认是单实例
@Scope(value="")
//引入别的类对象(标注在成员变量上)
@Autowired
@Resource(name="userDao")
//切面,指明这个类中用于方法增强(标注在类上)
@Aspect
//具体需要增强的方法(标注在方法上)
@Before :前置通知
@AfterReturing :后置通知
@Around :环绕通知
@After :最终通知
@AfterThrowing :异常抛出通知
//操作数据时的事务管理(标注在类上,此时类中所有方法都会进行事务管理)
@Transactional
//扫面创建对象的注解
<context:component-scan base-package="cn.itcast">context:component-scan>
//扫描aop增强注解
<aop:aspectj-autoproxy>aop:aspectj-autoproxy>
<tx:annotation-driven transaction-manager="transactionManager"/>
表现层框架
一站式框架
官方推荐配置文件: springmvc.xml
一个中心三大组件(springmvc核心)
一个中心: DispatcherServlet(前段控制器)
三大组件: HandlerMapping(处理器映射器)、HandlerAdapter(处理器适配器)、ViewResolver(视图解析器)
组件说明:
配置前端控制器
web.xml中:
<servlet>
<servlet-name>springmvc-firstservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>springmvc-firstservlet-name>
<url-pattern>*.actionurl-pattern>
servlet-mapping>
组件注解自动扫描
springmvc.xml中:
<context:component-scan base-package="cn.itcast.springmvc.controller" />
处理器映射器
对类中标记了@RequestMapping的方法进行映射.
根据@ResquestMapping定义的value中的url匹配@ResquestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器。
springmvc.xml中:
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
注解描述: @RequestMapping:定义请求url到处理器功能方法的映射
处理器适配器
对标记@RequestMapping的方法进行适配
springmvc.xml中:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
注解驱动(相当于配置了处理器映射器和处理器适配器)
<mvc:annotation-driven />
视图解析器
springmv.xml中:
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
bean>
逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为ItemList,则最终返回的jsp视图地址:“WEB-INF/jsp/itemList.jsp”
最终jsp物理地址:前缀+逻辑视图名+后缀
例子:
// @RequestMapping:里面放的是请求的url,和用户请求的url进行匹配
// action可以写也可以不写
@RequestMapping("/itemList.action")
public ModelAndView queryItemList() {
// 创建页面需要显示的商品数据
List<Item> list = new ArrayList<>();
list.add(new Item(1, "1华为 荣耀8", 2399, new Date(), "质量好!1"));
list.add(new Item(2, "2华为 荣耀8", 2399, new Date(), "质量好!2"));
list.add(new Item(3, "3华为 荣耀8", 2399, new Date(), "质量好!3"));
// 创建ModelAndView,用来存放数据和视图
ModelAndView modelAndView = new ModelAndView();
// 设置数据到模型中
modelAndView.addObject("itemList", list);
// 设置视图jsp,需要设置视图的物理地址
// modelAndView.setViewName("/WEB-INF/jsp/itemList.jsp");
// 配置好视图解析器前缀和后缀,这里只需要设置逻辑视图就可以了
// 视图解析器根据前缀+逻辑视图名+后缀拼接出来物理路径
modelAndView.setViewName("itemList");
return modelAndView;
}
整合目标:控制层采用springmvc、持久层使用mybatis实现。
需要jar包(去李旭springmvc资料里面找)
1.spring(包括springmvc)
2.mybatis
3.mybatis-spring整合包
4.数据库驱动
5.第三方连接池
整合思路
Dao层:
1、SqlMapConfig.xml,空文件即可,但是需要文件头。
2、applicationContext-dao.xml
a)数据库连接池
b)SqlSessionFactory对象,需要spring和mybatis整合包下的
c)配置mapper文件扫描器
Service层:
1、applicationContext-service.xml包扫描器,扫描@service注解的类
2、applicationContext-trans.xml配置事务
Controller层:
1、Springmvc.xml
a)包扫描器,扫描@Controller注解的类
b)配置注解驱动
c)配置视图解析器
Web.xml文件:
1、配置spring
2、配置前端控制器
#这些文件看同级文件夹resource
sqlMapConfig.xml
applicationContext-dao.xml
db.properties
applicationContext-service.xml
applicationContext-trans.xml
springmvc.xml
web.xml
1 ) 默认支持的参数类型
使用在controller的方法形参内
HttpServletRequest、HttpServletResponse、HttpSession
可以向原生态servlet一样获取域对象
ModelAndView、Model、ModelMap
三者只能选择一个使用
ModelAndView返回一个对象(对象中包括数据和页面地址)
Model返回一个字符串(字符串是页面地址,数据直接放在了域对象中)
是一个接口,Model向页面传递数据,View可以使用String返回值代替
ModelMap是Model接口的实现类,使用Model和ModelMap效果一样,如果直接使用Mode,springmvc会自动实例化ModelMap.
/**
* 根据id查询商品
*/
@RequestMapping("/itemEdit")
public ModelAndView queryItemById(HttpServletRequest request) {
// 从request中获取请求参数
String strId = request.getParameter("id");
Integer id = Integer.valueOf(strId);
// 根据id查询商品数据
Item item = this.itemService.queryItemById(id);
// 把结果传递给页面
ModelAndView modelAndView = new ModelAndView();
// 把商品数据放在模型中
modelAndView.addObject("item", item);
// 设置逻辑视图
modelAndView.setViewName("itemEdit");
return modelAndView;
}
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, Model model) {
// 从request中获取请求参数
String strId = request.getParameter("id");
Integer id = Integer.valueOf(strId);
// 根据id查询商品数据
Item item = this.itemService.queryItemById(id);
// 把商品数据放在模型中
model.addAttribute("item", item);
//返回视图地址
return "itemEdit";
}
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, ModelMap model) {
// 从request中获取请求参数
String strId = request.getParameter("id");
Integer id = Integer.valueOf(strId);
// 根据id查询商品数据
Item item = this.itemService.queryItemById(id);
// 把商品数据放在模型中
model.addAttribute("item", item);
return "itemEdit";
}
2 ) 绑定简单类型
当请求的参数名称和处理器形参**名称一致**时会将请求参数与形参进行绑定,这样从Request取参数的方法就可以进一步简化
整形:Integer、int
字符串:String
单精度:Float、float
双精度:Double、double
布尔型:Boolean、boolean
对于布尔类型的参数,请求的参数值为true或false或者1或0
请求url:http://localhost:8080/xxx.action?id=2&status=false
处理器方法:
public String editItem(Model model,Integer id,Boolean status)
@RequestParam
使用@RequestParam常用于处理简单类型的绑定
// value:参数名字,即入参的请求参数名字,如value=“itemId”表示请求的参数区中的名字为itemId的参数的值将传入
// required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报错TTP Status 400 - Required Integer parameter 'XXXX' is not present
// defaultValue:默认值,表示如果请求中没有同名参数时的默认值
@RequestMapping("/itemEdit")
public String queryItemById(@RequestParam(value = "itemId", required = true, defaultValue = "1") Integer id,
ModelMap modelMap) {
// 根据id查询商品数据
Item item = this.itemService.queryItemById(id);
// 把商品数据放在模型中
modelMap.addAttribute("item", item);
return "itemEdit";
}
@RequestParam(…) Integer id 与直接使用 Integer id的区别 :
例如: http://localhost:8080/project/item?item=1
生效: @RequestParam(value = “item”, required = true, defaultValue = “1”) Integer id
无效: Integer id
http://localhost:8080/project/item?id=1
无效: @RequestParam(value = “item”, required = true, defaultValue = “1”) Integer id
生效: Integer id
本质上不加@RequestParam也可以获得参数,但是异常处理或者方便前端传参变化,建议使用注解
3 ) 绑定pojo类型
使用pojo接收表单数据,要求:pojo对象中的属性名和表单中input的name属性一致
提交的表单中不要有日期类型的数据,否则会报400错误,日期类型的数据需要用自定义参数绑定
代码写法就是跟简单类型一样,现在是用类类型定义形参
/**
* 更新商品,绑定pojo类型
*/
@RequestMapping("/updateItem")
public String updateItem(Item item) {
// 调用服务更新商品
this.itemService.updateItemById(item);
// 返回逻辑视图
return "success";
}
4 ) 绑定包装pojo
包装类
public class QueryVo {
private Item item;
//set/get。。。
}
contrller层
// 绑定包装数据类型
@RequestMapping("/queryItem")
public String queryItem(QueryVo queryVo) {
System.out.println(queryVo.getItem().getId());
System.out.println(queryVo.getItem().getName());
return "success";
}
5 ) 自定义参数绑定
例子: 根据业务需求自定义日期格式存储
自定义converter转化器进行参数绑定
自定义的转换器类
//Converter
//S:source,需要转换的源的类型
//T:target,需要转换的目标类型
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
try {
// 把字符串转换为日期类型
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
Date date = simpleDateFormat.parse(source);
return date;
} catch (ParseException e) {
e.printStackTrace();
}
// 如果转换异常则返回空
return null;
}
}
配置Converer
<mvc:annotation-driven conversion-service="conversionService" />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.itcast.springmvc.converter.DateConverter" />
set>
property>
bean>
6 ) 高级参数绑定(这块儿其实有点懵逼,后期回归)
表单数据->数组
/**
* 包装类型 绑定数组类型,可以使用两种方式,pojo的属性接收,和直接接收(直接接收就相当于简单类型绑定)
*
*/
@RequestMapping("queryItem")
public String queryItem(QueryVo queryVo, Integer[] ids) {
System.out.println(queryVo.getItem().getId());
System.out.println(queryVo.getItem().getName());
System.out.println(queryVo.getIds().length);
System.out.println(ids.length);
return "success";
}
表单数据->List
post乱码
web.xml中:
<filter>
<filter-name>encodingfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
get乱码
方式一:
修改tomcat配置文件添加编码与工程编码一致,如下:(server.xml)
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
方式二:
对参数进行重新编码:
String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
//ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
@RequestMapping(value=“item”)或@RequestMapping(“/item”)
value的值是数组,可以将多个url映射到同一个方法中
使用方式
类上: 在class上@RequestMapping(url)指定通用请求前缀,限制此类下的所有方法请求url必须以请求前缀开头!
方法上
可以限定post/get方法才可以请求该方法(默认不指定是都可以请求)
@RequestMapping(method = RequestMethod.GET)
@RequestMapping(value = “itemList”,method = RequestMethod.POST)
//post/get都可以访问
@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})
注意使用需要导入json的jar包: jackson
@RequestBody
post请求体中json数据给Controller,@RequestBody负责把json数据转为java对象并绑定到Controller方法的形参上
{
"id": 1,
"name": "测试商品",
"price": 99.9,
"detail": "测试商品描述",
"pic": "123456.jpg"
}
#@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象进行绑定
#通过springmvc提供的HttpMessageConverter接口
@ResponseBody
@ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
/**
* 测试json的交互
* 请求是json,返回也是json,证明json解析到Item对象,Item封装到json,都是正确的
*/
@RequestMapping("testJson")
public @ResponseBody Item testJson(@RequestBody Item item) {
return item;
}
如果加上@ResponseBody注解,就不会走视图解析器,不会返回页面,只会返回的json数据。如果不加,就走视图解析器,返回页面
ModelAndView
void(不使用,springmvc有自己的重定向方法,返回值是String)
/**
* 返回void测试
*/
@RequestMapping("queryItem")
public void queryItem(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 1 使用request进行转发
//request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request,
// response);
// 2 使用response进行重定向到编辑页面
// response.sendRedirect("/springmvc-web2/itemEdit.action");
// 3 使用response直接显示
response.getWriter().print("{\"abc\":123}");
}
//知识补充:
//转发之后request和response域中对象不会失效,但是重定向就会失效
//转发就相当于连个jsp页面拼起来,重定向则是换了一个新的jsp(这也是域对象会失效的原因)
//转发浏览器地址不会改变,重定向会改变(转发是偷梁换柱暗度陈仓,重定向是光明磊落说一不二)
string
逻辑视图名
Redirect重定向
@RequestMapping("updateItem")
public String updateItemById(Item item) {
// 更新商品
this.itemService.updateItemById(item);
// 修改商品成功后,重定向到商品编辑页面
// 重定向后浏览器地址栏变更为重定向的地址,
// 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失
// 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数
return "redirect:/itemEdit.action?itemId=" + item.getId();
}
forward转发
@RequestMapping("updateItem")
public String updateItemById(Item item) {
// 更新商品
this.itemService.updateItemById(item);
// 修改商品成功后,继续执行另一个方法
// 使用转发的方式实现。转发后浏览器地址栏还是原来的请求地址,
// 转发并没有执行新的request和response,所以之前的请求参数都存在
return "forward:/itemEdit.action";
}
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
传统方式操作资源-> http://127.0.0.1/item/queryItem.action?id=1 查询,GET
使用RESTful操作资源-> http://127.0.0.1/item/1 查询,GET
需求: RESTful方式实现商品信息查询,返回json数据
实现
从url上获取参数
我们需要从url上获取商品id,步骤如下:
使用注解**@RequestMapping(“item/{id}”)**声明请求的url
{xxx}叫做占位符,请求的URL可以是“item /1”或“item/2”
使用(@PathVariable() Integer id)获取url上的数据
/**
* 使用RESTful风格开发接口,实现根据id查询商品
* 请求路径: http://127.0.0.1/item/1
* Variable-变量
*/
@RequestMapping("item/{id}")
@ResponseBody
public Item queryItemById(@PathVariable() Integer id) {
Item item = this.itemService.queryItemById(id);
return item;
}
// 如果@RequestMapping中表示为"item/{id}",id和形参名称一致
// @PathVariable不用指定名称;
// 如果不一致,例如"item/{ItemId}"
// 则需要指定名称@PathVariable("itemId")
@PathVariable是获取url上数据的。@RequestParam获取请求参数的(包括post表单提交)
配置虚拟目录
server.xml中:
#相当于是虚拟路经和真是路径绑定
<Context docBase="D:\develop\upload\temp" path="/pic" reloadable="false"/>
导入jar
commons-fileupdate-1.2.2.jar
commons-io-2.4.jar
配置传解析器
springmvc.xml中:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="5000000" />
bean>
代码
/**
* 更新商品
*/
@RequestMapping("updateItem")
public String updateItemById(Item item, MultipartFile pictureFile) throws Exception {
// 图片上传
// 设置图片名称,不能重复,可以使用uuid
String picName = UUID.randomUUID().toString();
// 获取文件名
String oriName = pictureFile.getOriginalFilename();
// 获取图片后缀
String extName = oriName.substring(oriName.lastIndexOf("."));
// 开始上传
pictureFile.transferTo(new File("C:/upload/image/" + picName + extName));
// 设置图片名到商品中
item.setPic(picName + extName);
// ---------------------------------------------
// 更新商品
this.itemService.updateItemById(item);
return "forward:/itemEdit.action";
}
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
自定义异常类
public class MyException extends Exception {
// 异常信息
private String message;
//有参和无参构造
public MyException() {
super();
}
public MyException(String message) {
super();
this.message = message;
}
//set\get(message)
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
自定义异常处理类
public class CustomHandleException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) {
// 定义异常信息
String msg;
// 判断异常类型
//instanceof 是否属于某个类(是否是谁的实例)
if (exception instanceof MyException) {
// 如果是自定义异常,读取异常信息
msg = exception.getMessage();
} else {
// 如果是运行时异常,则取错误堆栈,从堆栈中获取异常信息
Writer out = new StringWriter();
PrintWriter s = new PrintWriter(out);
exception.printStackTrace(s);
msg = out.toString();
}
// 把错误信息发给相关人员,邮件,短信等方式
// TODO
// 返回错误页面,给用户友好页面显示错误信息
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", msg);
modelAndView.setViewName("error");
return modelAndView;
}
}
springmvc.xml配置
<bean
id="customHandleException" class="cn.itcast.ssm.exception.CustomHandleException"/>
测试异常类
/**
* 查询商品列表
*/
@RequestMapping(value = { "itemList", "itemListAll" })
public ModelAndView queryItemList() throws Exception {
// 自定义异常
if (true) {
throw new MyException("自定义异常出现了~");
}
// 运行时异常
int a = 1 / 0;
// 查询商品数据
List<Item> list = this.itemService.queryItemList();
// 创建ModelAndView,设置逻辑视图名
ModelAndView mv = new ModelAndView("itemList");
// 把商品数据放到模型中
mv.addObject("itemList", list);
return mv;
}
类似于servlet中的Filter过滤器,用于对处理器进行预处理和后处理
自定义拦截器
// 实现HandlerInterceptor接口
public class HandlerInterceptor1 implements HandlerInterceptor {
// controller执行后且视图返回后调用此方法
// 这里可得到执行controller时的异常信息
// 这里可记录操作日志
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("HandlerInterceptor1....afterCompletion");
}
// controller执行后但未返回视图前调用此方法
// 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("HandlerInterceptor1....postHandle");
}
// Controller执行前调用此方法
// 返回true表示继续执行,返回false中止执行
// 这里可以加入登录校验、权限拦截等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("HandlerInterceptor1....preHandle");
// 设置为true,测试使用
return true;
}
}
拦截器配置
springmvc.xml中:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1" />
mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2" />
mvc:interceptor>
mvc:interceptors>
多个拦截器执行顺序(一般之定义一个拦截器)
总结:
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内所有拦截器返成功调用
afterCompletion只有preHandle返回true才调用
拦截器应用实例(判断用户是否登录)
//匹配访问路径(类上、方法上)
@RequestMapping
//获取请求参数(controller方法形参内)
@RequestParam
//前端给的json串解析成java对象,映射在形参对象里(controller方法形参内)
@RequestBody
//返给前端的对象解析成一个json串(controller方法中,返回值位置)
@ResponseBody
//获取url上数据(controller方法形参内)
@PathVariable
#前端控制器
web.xml
#处理器映射器
springmvc.xml
#处理器适配器
springmvc.xml
#注解驱动(相当于配置了==处理器映射器==和==处理器适配器==)
#视图解析器
springmvc.xml
#解决post/get请求数据保存到数据库乱码问题
web.xml
#上传图片(配置虚拟目录)
server.xml
#配置全局异常处理器
springmvc.xml
#拦截器配置
springmvc.xml
#具体配置详情见每一项小标题具体说明