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_4_0.xsd"
version="4.0">
<!--配置编码过滤器-->
<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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:bean.xml</param-value>
</context-param>
<!--配置DispatcherServlet-->
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-web.xml</param-value>
</init-param>
<!--值为0或正数整时,servlet随容器启动而创建
值为负数整时,servlet随容器启动而创建-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring-web.xml配置
location元素表示webapp目录下的static包下的所有文件;
mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--<!–配置映射器RequestMappingHandlerMapping–>-->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>-->
<!--<!–配置适配器–>-->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>-->
<!--使用mvc驱动进行配置适配器和映射器,这样做可以使用mvc的@DateTimeFormat和@NumberFormat来处理400的参数绑定失败错误-->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 对于静态的资源,配置后将不经过dispatcherServlet管理,配置mapper映射关系,mapper为在请求的路径,location为对该请求配置对应的本地路径-->
<mvc:resources mapping="/css/**" location="/css/"></mvc:resources>
<mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
<mvc:resources mapping="/font/**" location="/font/"></mvc:resources>
<!--配置视图器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<context:component-scan base-package="com.hn"></context:component-scan>
</beans>
spring-datasource.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&setCharacterEncoding=utf-8"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath*:mapper/*.xml" />
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<value>
helperDialect=mysql
reasonable=true
supportMethodsArguments=true
params=count=countSql
autoRuntimeDialect=true
</value>
</property>
</bean>
</array>
</property>
</bean>
<!--将mapper的实现类放入springIOC中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.hn.mapper" />
</bean>
</beans>
beans.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<import resource="classpath*:data-source.xml"></import>
</beans>
jsp的时间格式化
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:formatDate value="${user.date}" pattern="yyyy/MM/dd HH:mm:ss"></fmt:formatDate>
打印输出
<input type="date" name="date" value="<fmt:formatDate value='${user.date}' pattern='yyyy-MM-dd'></fmt:formatDate>">
增删改查
进行修改操作表单的ajax
<script>
$(function(){
$("form").submit(function (){
$.ajax({
type:"post",
data:id=$.param({id:${user.id}})+'&'+$("form").serialize(),
url:'${pageContext.request.contextPath}/user/update',
success:function(){
$("#alarm").show();
setTimeout("location.href='${pageContext.request.contextPath}/user/list'",1000);
}
})
return false;
})
})
</script>
controller的基本使用
controller方法的使用
1.@RequestMapping(value=“user”),创建请求映射。method设置约束接收的请求方式
2.@RequestParam使用在参数上,用于跟请求的数据名进行绑定,参数名称自定义配置,可定义默认值
3.@PathVariable使用/{}来传递get请求
4.ModelAndView的传递参数,可以在方法中增加Model的参数,来返回String替代ModelAndView.
5.拿到cookie的值 public ModelAndView cookie(@CookieValue(“JSESSIONID”)String value)
6.地址的请求转发和重定向
使用forward:,redirect:前缀后InternalResourceViewResolver的前缀和后缀将失效
forward:请求转发地址默认以配置的视图器为基准
redirect:重定向地址默认以相对路径为基准
都可以使用/来绝对工程路径
7.因为请求传递过来的数据实际上是字符串,因此要对请求传递过来的一些参数进行格式化
http常见响应码
200 请求成功
500 代码错误
400 Bad request 一般是数据类型无法绑定所造成的
405 拒绝请求类型,比如@RequestMapping设置的请求方式约束
controller代码实现
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private IUserService userService;
@RequestMapping("/list")
public ModelAndView list(@RequestParam(value = "page", defaultValue = "1") int page) {
ModelAndView mav = new ModelAndView();
mav.setViewName( "user/list" );
Page<User> pageUser = (Page<User>) userService.list( page, 4 );
mav.addObject( "users", pageUser );
return mav;
}
@RequestMapping("/add")
public String goAdd() {
return "user/add";
}
@RequestMapping("/doAdd")
public String add(User user) {
userService.addUser( user );
return "redirect:/";
}
@RequestMapping("/to_update/{uid}")
public ModelAndView toUpdate(@PathVariable("uid")int uid) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName( "user/to_update" );
modelAndView.addObject( "user", userService.getUserById( uid ) );
return modelAndView;
}
日期类型参数绑定
方式一:实体类属性加@DateTimeFormat(pattern = “yyyy-MM-dd”)
方式二:在controller层创建@InitBinder对获取指定的数据参数名进行处理。
@InitBinder
public void initDate(WebDataBinder dataBinder){
dataBinder.addCustomFormatter( new DateFormatter("yyyy-MM-dd"),"date" );
}
方式三:自定义spring参数处理器、
自定义注解
@Target( ElementType.PARAMETER )
@Retention(RetentionPolicy.RUNTIME)
public @interface MyDate {
String[] params() default "";
String pattern() default "yyyy-MM-dd";
}
实现自定义参数解析器
public class MyHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver{
private String[] params; /*属性*/
private String pattern; /*日期的格式*/
//表单中传入birthday参数到controller的参数User的birthday,如何转换
@Override
public Object resolveArgument(MethodParameter methodParam, ModelAndViewContainer arg1, NativeWebRequest webRequest,
WebDataBinderFactory arg3) throws Exception {
//1.获取controller方法参数Users user的类型对象
Object object = BeanUtils.instantiateClass(methodParam.getParameterType());
//2.获取参数类型对象的类信息(Users类的属性和方法)
BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
//3.获取请求对象Request
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
//4.获取Users类类型对象的所有属性描述(获取Users类的所有属性)
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
//5.得到每个属性的名字(Users类的属性名),并根据属性名称得到请求参数的值
String value = request.getParameter(propertyDescriptor.getName());
//6.判断非空
if (!StringUtils.isEmpty(value)) {
//5.得到属性的set方法
Method writeMethod = propertyDescriptor.getWriteMethod();
//6.如果set方法为非公有方法,暴力破解
if (!Modifier.isPublic(writeMethod.getModifiers())) {
writeMethod.setAccessible(true);
}
//7.判断属性名是否为Date指定的params值,如果是params指定值 则进行日期转换
if (propertyDescriptor.getName().equals(params[0])) {//日期属性
SimpleDateFormat sdf = new SimpleDateFormat(this.pattern);
java.util.Date date = sdf.parse(value);
//调用setBirthday(date)
writeMethod.invoke(object, date);
} else {//非日期的属性
//属性类型为Integer
if(propertyDescriptor.getPropertyType().equals(Integer.class)) {
writeMethod.invoke(object, Integer.parseInt(value));
//属性类型为字符串
}else {
writeMethod.invoke(object, value);
}
}
}
}
return object;
}
//哪些参数才需要调用我们上面的解析方法进行解析
@Override
public boolean supportsParameter(MethodParameter parameter) {
//1、判断controller方法上是否有MyDate注解
boolean hasParameterAnnotation = parameter.hasParameterAnnotation(MyDate.class);
if (!hasParameterAnnotation) {
//不会进入下面的resolveArgument方法进行参数的解析
return false;
}
//2、获取Date注解对象
MyDate parameterAnnotations = parameter.getParameterAnnotation(MyDate.class);
//3、获取Date注解的params参数
String[] parameters = parameterAnnotations.params();
if (!StringUtils.isEmpty(parameters)) {
params = parameters;
//4.获取Date注解的pattern参数
pattern = parameterAnnotations.pattern();
//进入下面的resolveArgument方法进行参数的解析
return true;
}
return false;
}
}
spring-web.xml配置
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="com.hn.annotation.MyHandlerMethodArgumentResolver"></bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
然后再参数上使用注解即可
@RequestMapping("/doAdd")
public String add(@MyDate(params = "date") User user) {
userService.addUser( user );
return "redirect:/";
}
通过request获取服务器相对路径及绝对路径
String scheme = request.getScheme();//http
String serverName = request.getServerName();//localhost
int port = request.getServerPort();//8080
String context = request.getContextPath();// /demo(项目名称);
String path = scheme+"😕/"+serverName+":"+port+context+"/" // http://localhost:8080/demo/
获取上传文件保存服务器的路径
String filePath = request.getSession().getServletContext().getRealPath(“uploadFiles/pictures”);
C:\Program Files (x86)\apache-tomcat-7.0\uploadFiles\pictures
统一异常处理
1.实现org.springframework.web.servlet.HandlerExceptionResolver接口,缺点只能返回ModelAndView,实际情况都使用json,因此,此方法实际作用很低。
@component
public class ExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
// System.out.println(o);
e.printStackTrace();
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName( "404" );
modelAndView.addObject( "msg",e.getMessage() );
return modelAndView;
}
}
2.注解声明
package com.hn.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice//控制层增强
public class AnnotationExceptionHandle {
@ExceptionHandler(Exception.class)//选定该异常的处理方式
@ResponseBody
public String exceptionHandler(Exception e) {
e.printStackTrace();
return "";
}
}
MD5加密
需要依赖
org.apache.commons.lang3.StringUtils
package com.hn.utils;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
public class PropertiesUtil {
// private static Logger logger = LoggerFactory.getLogger(PropertiesUtil.class);
private static Properties props;
static {
String fileName = "ndcrm.properties";
props = new Properties();
try {
props.load(new InputStreamReader(PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName),"UTF-8"));
} catch (IOException e) {
// logger.error("配置文件读取异常",e);
}
}
public static String getProperty(String key){
String value = props.getProperty(key.trim());
if(StringUtils.isBlank(value)){
return null;
}
return value.trim();
}
public static String getProperty(String key,String defaultValue){
String value = props.getProperty(key.trim());
if(StringUtils.isBlank(value)){
value = defaultValue;
}
return value.trim();
}
public static void main(String[] args) {
System.out.println(PropertiesUtil.getProperty("password.salt"));
}
}
package com.hn.utils;
import java.security.MessageDigest;
public class MD5Util {
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append( byteToHexString( b[i] ) );
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
/**
* 返回大写MD5
*
* @param origin
* @param charsetname
* @return
*/
private static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String( origin );
MessageDigest md = MessageDigest.getInstance( "MD5" );
if (charsetname == null || "".equals( charsetname ))
resultString = byteArrayToHexString( md.digest( resultString.getBytes() ) );
else
resultString = byteArrayToHexString( md.digest( resultString.getBytes( charsetname ) ) );
} catch (Exception exception) {
}
return resultString.toUpperCase();
}
public static String MD5EncodeUtf8(String origin) {
origin = origin + PropertiesUtil.getProperty( "password.salt", "" );
return MD5Encode( origin, "utf-8" );
}
private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
public static void main(String[] args) {
System.out.println( MD5EncodeUtf8( "admin" ) );
}
}
ndcrm.properties文件配置盐
password.salt=hhh@@!!!ld
拦截器
通常流程:
过滤器->dispatcherServlet->RequestMappingHandlerMapping->RequestMappingHandlerAdapter->拦截器->controller
public class LoginInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(handler);
HttpSession session = request.getSession();
if ( session.getAttribute( "userType")!=null){
return true;
}
response.sendRedirect( "/login" );
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
xml配置,配置在前面的拦截器会先拦截
<mvc:interceptors>
<mvc:interceptor >
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login"/>
<mvc:exclude-mapping path="/user/do_login"/>
<bean class="com.hn.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截器分为在访问控制层前,控制层返回前,控制层后。值得注意的事情是两个拦截的情况,设为A、B,A在前。
情况一:A的pre放行,B拦截,最终A还会执行A的after。
情况二:A,B均拦截,顺序为A-pre->B->pre->B-post->A-post->B-after->A-after
定时任务
需要依赖
有xml和注解配置两种
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 配置类-->
<bean id="task" class="com.cc.timer.XMLSchedule"></bean>
<!-- 配置类中指定的方法为定时任务-->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="task"/>
<property name="targetMethod" value="t"/>
</bean>
<!-- <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">-->
<!-- <!– see the example of method invoking job above –>-->
<!-- <property name="jobDetail" ref="jobDetail"/>-->
<!-- <!– 10 seconds –>-->
<!--<!– <property name="startDelay" value="10000"/>–>-->
<!--<!– <property name="repeatInterval" value="50000"/>–>-->
<!-- </bean>-->
<!--使用cron表达式对任务进行配置-->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail"/>
<!-- run every morning at 6 AM -->
<property name="cronExpression" value="0/1 * * * * ?"/>
</bean>
<!-- 在任务工厂中添加任务-->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
</beans>
可以看得出来xml配置很繁琐,建议使用注解
@Component
@EnableScheduling
public class AnnotationSchedule {
@Scheduled(cron = "0/1 * * * * ? ")
public void t() throws InterruptedException{
System.out.println("1");
}
}
异步支持
@Component
@EnableAsync
@EnableScheduling
public class AnnotationSchedule {
@Async
@Scheduled(cron = "0/1 * * * * ? ")
public void t() throws InterruptedException{
System.out.println("1");
}
}