1, PageHelper paging plug-in
PageHelper is an excellent open-source mybatis paging plug-in in China. It supports basic mainstream and commonly used databases, such as mysql, oracle, mariaDB, DB2, SQLite, Hsqldb, etc.
There are two ways to reference the PageHelper paging plug-in:
- Introduce Jar package;
- Use Maven (recommended);
1.1 reference Jar package to realize paging
Download the latest version of the jar package from the address below
-
https://oss.sonatype.org/content/repositories/releases/com/github/pagehelper/pagehelper/
-
http://repo1.maven.org/maven2/com/github/pagehelper/pagehelper/
Because the sql parsing tool is used, you also need to download jsqlparser.jar:
1.2 paging using Maven
1.2.1 PageHelper coordinates
<!--Paging plug-in--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.8</version> </dependency>
1.2.2 configure interceptor plug-in
- Configure the interceptor plug-in in MyBatis configuration XML (or write in sqlSessionFactory object configuration of spring.xml)
<!-- plugins The position in the configuration file must meet the requirements, otherwise an error will be reported, in the following order: properties?, settings?, typeAliases?, typeHandlers?, objectFactory?,objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers? --> <plugins> <!-- com.github.pagehelper by PageHelper Package name of class --> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- Use the following method to configure parameters. All parameters will be described later --> <property name="param1" value="value1"/> </plugin> </plugins>
<!--3.to configure SqlSessionFactory object--> <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--specify data source--> <property name="dataSource" ref="dataSource"/> <!-- to configure MyBaties Global profile:mybatis-config.xml --> <!-- <property name="configLocation" value="classpath:mybatis-config.xml" />--> <!--Specifies the alias of the entity class--> <property name="typeAliasesPackage" value="cn.tsm.bean"/> <!--to configure mapper.xml file location--> <property name="mapperLocations" value="classpath:mapper/*.xml"/> <!--to configure PageHelper Interceptor plug-in--> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"></bean> </array> </property> </bean>
- Configure the interceptor plug-in in the Spring configuration file
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- Note other configurations --> <!-- afferent PageHelper Plug in for --> <property name="plugins"> <array> <!-- Objects passed in to the plug-in --> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <props> <prop key="helperDialect">mysql</prop> <prop key="reasonable">true</prop> </props> </property> </bean> </array> </property> </bean>
1.2.3 introduction to paging plug-in parameters
1. helperDialect: The paging plug-in will automatically detect the current database link and automatically select the appropriate paging method. You can configure helperDialect Property to specify which dialect the paging plug-in uses. When configuring, you can use the following abbreviations: oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby Special note: use SqlServer2012 The database needs to be manually specified as sqlserver2012,Otherwise, it will be used SqlServer2005 Pagination in the same way. You can do it, too AbstractHelperDialect,Then configure the property to the fully qualified name of the implementation class to use the custom implementation method. 2. offsetAsPageNum: The default value is false,This parameter is used for RowBounds Valid as paging parameter. When this parameter is set to true When, the RowBounds Medium offset Parameter as pageNum You can use page number and page size to page. 3. rowBoundsWithCount: The default value is false,This parameter is used for RowBounds Valid as paging parameter. When this parameter is set to true When using RowBounds Paging occurs count Query. 4. pageSizeZero: The default value is false,When this parameter is set to true When, if pageSize=0 perhaps RowBounds.limit = 0 All the results will be queried (equivalent to that the paging query is not executed, but the returned result is still Page Type). 5. reasonable: Paging rationalization parameter. The default value is false. When this parameter is set to true When, pageNum<=0 The first page will be queried, pageNum>pages(When the total number is exceeded, the last page will be queried. default false Query directly according to parameters. 6. params: To support startPage(Object params)Method is added to configure the parameter mapping, which is used to take values from the object according to the attribute name, which can be configured pageNum,pageSize,count,pageSizeZero,reasonable,The default value for mapping is not configured. The default value is pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero. 7. supportMethodsArguments: Support through Mapper Interface parameters to pass paging parameters. The default value is false,The paging plug-in will automatically select the parameter values of the query method according to the above parameters params Take values in the configured fields, and the page will be automatically paged when an appropriate value is found. For the usage method, refer to the in the test code com.github.pagehelper.test.basic Under the bag ArgumentsMapTest and ArgumentsObjTest. 8. autoRuntimeDialect: The default value is false. Set to true At runtime, it is allowed to automatically identify the paging of the corresponding dialect according to multiple data sources (automatic selection is not supported) sqlserver2012,Only use sqlserver),Refer to scenario 5 below for usage and precautions. 9. closeConn: The default value is true. When using run-time dynamic data sources or not set helperDialect Property to automatically obtain a database connection. You can use this property to set whether to close the obtained connection. By default true Off, set to false After, the obtained connection will not be closed. The setting of this parameter depends on the data source you choose. 10. aggregateFunctions(5.1.5+): The default is the aggregate function of all common databases. It allows you to add aggregate functions manually (affecting the number of rows). All functions starting with aggregate functions are added in the count When converting, a layer will be set. Other functions and columns will be replaced with count(0),among count Columns can be configured by themselves.
1.3 cases
- service interface
public interface ProductService { public List<Product> findAllProduct(int pageNum,int pageSize) ; }
- service implementation class
@Service public class ProductServiceImpl implements ProductService { @Autowired private ProductMapper productMapper; @Override public List<Product> findAllProduct(int pageNum,int pageSize) { PageHelper.startPage(pageNum, pageSize); return productMapper.findAllProduct(); } }
- controller
@RequestMapping("/findAllProduct") public String findAllProduct(@RequestParam(name = "page" ,defaultValue = "1") int pageNum, @RequestParam(name = "size" ,defaultValue = "2") int pageSize, Model model){ List<Product> productList = productService.findAllProduct(pageNum,pageSize); PageInfo pageInfo = new PageInfo(productList); model.addAttribute("pageInfo", pageInfo); return "product-list"; }
- Front page
<c:forEach items="${pageInfo.list}" var="product"> <tr> <td><input name="ids" type="checkbox"></td> <td>${product.id }</td> <td>${product.productNum }</td> <td>${product.productName }</td> <td>${product.cityName }</td> <td>${product.departureTimeStr }</td> <td class="text-center">${product.productPrice }</td> <td>${product.productDesc }</td> <td class="text-center">${product.productStatusStr }</td> <td class="text-center"> <button type="button" class="btn bg-olive btn-xs">order</button> <button type="button" class="btn bg-olive btn-xs">details</button> <button type="button" class="btn bg-olive btn-xs">edit</button> </td> </tr> </c:forEach>
- Add page number operation
<div class="box-footer"> <div class="pull-left"> <div class="form-group form-inline"> in total ${pageInfo.pages} Page of ${pageInfo.total} Data per page <select class="form-control"> <option>1</option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> </select> strip </div> </div> <div class="box-tools pull-right"> <ul class="pagination"> <li><a href="${pageContext.request.contextPath}/product/findAllProduct?page=1&size=${pageInfo.pageSize}" aria-label="Previous">home page</a></li> <li><a href="${pageContext.request.contextPath}/product/findAllProduct?page=${pageInfo.pageNum-1}&size=${pageInfo.pageSize}">previous page</a></li> <c:forEach begin="1" end="${pageInfo.pages}" var="p"> <li><a href="${pageContext.request.contextPath}/product/findAllProduct?page=${p}&size=${pageInfo.pageSize}">${p}</a></li> </c:forEach> <li> <a href="${pageContext.request.contextPath}/product/findAllProduct?page=${pageInfo.pageNum+1}&size=${pageInfo.pageSize}">next page</a> </li> <li><a href="${pageContext.request.contextPath}/product/findAllProduct?page=${pageInfo.pages}&size=${pageInfo.pageSize}" aria-label="Next">Last page</a></li> </ul> </div> </div>
- Customize the number of entries displayed per page
in total ${pageInfo.pages} Page of ${pageInfo.total} Data per page <select class="form-control" id="changePageSize" onclick="changePageSize()"> <option>1</option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> </select> strip
function changePageSize() { //Gets the value of the drop-down box var pageSize = $("#changePageSize").val(); //Send a request to the server to change the number of displayed pages location.href = "${pageContext.request.contextPath}/product/findAllProduct?page=1&size=" + pageSize; }
2, Spring security
2.1 what is spring security
The predecessor of Spring Security is Acegi Security, which is a framework used by the Spring project team to provide security authentication services.
( https://projects.spring.io/spring-security/ )Spring security provides comprehensive security services for enterprise applications based on J2EE
It is an enterprise software project developed using the Spring framework, a leading J2EE solution. People use Spring Security for many reasons, but it is usually attractive
They are cited that they can't find solutions for typical enterprise application scenarios in J2EE Servlet specification or EJB specification. In particular, they can't find solutions anymore
Migrate at the WAR or EAR level. In this way, if you change the server environment, you need to do a lot of work in the new target environment to improve your application
Reconfigure the security of the system. Using Spring Security solves these problems and provides you with many useful and other security that can be specified
Full feature. Safety includes two main operations.
- "Authentication" is to establish a declared subject for the user. The general formula of subject refers to the user, device or other system that can perform actions in your system
System.
- "Authorization" refers to whether a user can perform an operation in your application. Before reaching the authorization judgment, the subject of identity has been verified by authentication
The process is established.
These concepts are universal and not unique to Spring Security. At the authentication level, Spring Security widely supports various authentication modes,
Most of these validation models are provided by third parties or relevant standards institutions under development, such as Internet Engineering Task
Force. As a supplement, Spring Security also provides its own set of authentication functions.
Spring Security currently supports the following authentication technology: HTTP BASIC authentication headers (an IEFT RFC based authentication header)
HTTP Digest authentication headers (a standard based on IEFT RFC) http X.509 client certi? Cat exchange
(a standard based on IEFT RFC) LDAP (a very common cross platform authentication practice, especially in large environments) form based
Authentication OpenID authentication Computer Associates Siteminder JA-SIG
Central Authentication Service (CAS, a popular open source single sign on system) Transparent authentication context
propagation for Remote Method Invocation and HttpInvoker (a Spring remote invocation protocol)
2.2 spring security quick start
2.2.1 spring security coordinates
<!--introduce Security Certification services framework coordinates--> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>5.0.5.RELEASE</version> </dependency>
2.2.2 configuring web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-security.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
2.2.3 configuring spring-security.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:security="http://www.springframework.org/schema/security" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd "> <!-- Configure non intercepted resources security Is certification required none Representative does not need--> <security:http pattern="/pages/login.jsp" security="none"/> <security:http pattern="/pages/fail.jsp" security="none"/> <security:http pattern="/css/**" security="none"/> <security:http pattern="/img/**" security="none"/> <security:http pattern="/plugins/**" security="none"/> <!-- use-expressions: access Use expression --> <security:http auto-config="true" use-expressions="false" > <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN" /> <!-- Define the specific page to jump to login-page Specify the login page path address login-processing-url: Specify the login request to be intercepted (the user name and password entered by the user can be obtained through the request, which will be executed automatically userService in loadUserByName Method) --> <security:form-login login-page="/pages/login.jsp" login-processing-url="/login" default-target-url="/pages/main.jsp" authentication-failure-url="/pages/fail.jsp" authentication-success-forward-url="/pages/main.jsp" /> <!-- Turn off cross domain requests --> <security:csrf disabled="true"/> </security:http> <!-- Switch to the user name and password in the database --> <security:authentication-manager> <security:authentication-provider user-service-ref="userService"> <security:password-encoder ref="passwordEncoder"/> </security:authentication-provider> </security:authentication-manager> <!--Specifies how the password is encrypted--> <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/> <bean id="webSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"> </bean> </beans>
2.2.4 writing UserMapper
public interface UserMapper { // Query users by user name public UserInfo findUserByUserName(String username); }
2.2.5 writing UserService
package cn.yunhe.service; import org.springframework.security.core.userdetails.UserDetailsService; public interface UserService extends UserDetailsService { }
@Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //Query user information according to user name User user = userDao.queryUserByName(username); org.springframework.security.core.userdetails.User securityUser = //{noop} means that password encryption is not required new org.springframework.security.core.userdetails.User( user.getUsername(), // "{noop}"+user.getPassword(), user.getPassword(), user.getStatus() == 1 ? true : false, true, true, true, getAuthority(user.getRoleList())); return securityUser; } /** * List of simulated user roles (to be replaced later by querying the users role table) * * @return */ public List<SimpleGrantedAuthority> getAuthority(List<Role> roleList) { ArrayList<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<SimpleGrantedAuthority>(); for (Role role : roleList) { String roleName = role.getRoleName(); simpleGrantedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + roleName)); } return simpleGrantedAuthorities; } }
2.2.6 writing UserMapper.xml
<!--users,role Two table mapping--> <resultMap id="queryUserByNameMap" type="user"> <id column="uid" property="id"/> <result column="username" property="username"/> <result column="email" property="email"/> <result column="password" property="password"/> <result column="phoneNum" property="phoneNum"/> <result column="status" property="status"/> <!--Users and roles one to many--> <collection property="roleList" ofType="role"> <id column="rid" property="id"/> <result column="roleName" property="roleName"/> <result column="roleDesc" property="roleDesc"/> </collection> </resultMap> <!--Query user information through user name (user information, role information)--> <select id="queryUserByName" parameterType="String" resultMap="queryUserByNameMap"> select users.id uid, users.username, users.password, users.email, users.phoneNum, users.status, r.id rid, r.roleName, r.roleDesc from users join users_role ur on users.id = ur.userId join role r on r.id = ur.roleId where username = #{username} </select>
3, AOP log
- AOP coordinates
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency>
- Enable AOP auto proxy annotation
<!-- support AOP Annotation support for, AOP The bottom layer uses agent technology JDK Dynamic proxy requires an interface cglib Proxy, generate subclass objects, proxy-target-class="true" Default use cglib The way --> <aop:aspectj-autoproxy proxy-target-class="true"/>
- Configure the listener of request in web.xml
<listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
- Create AOP facet class under controller
@Component @Aspect public class LogAOP { @Autowired private HttpServletRequest request; @Autowired private SysLogService sysLogService; private Date visitTime; private Class clazz; private Method method; @Before("execution(* cn.yunhe.controller.*.*(..))") // * cn.yunhe.controller.*.*(..) public void doBefore(JoinPoint jp) throws NoSuchMethodException { visitTime = new Date();//The current time is the time when the access started clazz = jp.getTarget().getClass(); //Specific class to access String methodName = jp.getSignature().getName(); //Gets the name of the method accessed Object[] args = jp.getArgs();//Gets the parameters of the accessed method //Gets the Method object of the Method to be executed if (args == null || args.length == 0) { method = clazz.getMethod(methodName); //Only methods without parameters can be obtained } else { Class[] classArgs = new Class[args.length]; for (int i = 0; i < args.length; i++) { if(args[i].getClass() == BindingAwareModelMap.class){ classArgs[i] = Model.class; }else{ classArgs[i] = args[i].getClass(); } } method = clazz.getMethod(methodName, classArgs); } } @After("execution(* cn.yunhe.controller.*.*(..))") public void doAfter(JoinPoint jp){ long time = new Date().getTime() - visitTime.getTime(); //Gets the duration of the access String url = ""; //Get url if (clazz != null && method != null && clazz != LogAOP.class) { //1. Get @ RequestMapping("/xxx") on the class RequestMapping classAnnotation = clazz.getAnnotation(RequestMapping.class); if (classAnnotation != null) { String[] classValue = classAnnotation.value(); //2. Get @ RequestMapping(xxx) on the method RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class); if (methodAnnotation != null) { String[] methodValue = methodAnnotation.value(); // Splice url url = classValue[0] + methodValue[0]; //Get access ip String ip = request.getRemoteAddr(); //Gets the user of the current operation SecurityContext context = SecurityContextHolder.getContext();//The currently logged in user was obtained from the context User user = (User) context.getAuthentication().getPrincipal(); String username = user.getUsername(); //Encapsulate log related information into SysLog objects SysLog sysLog = new SysLog(); sysLog.setExecutionTime(time); //Execution duration sysLog.setIp(ip); sysLog.setMethod("[Class name] " + clazz.getName() + "[Method name] " + method.getName()); sysLog.setUrl(url); sysLog.setUsername(username); sysLog.setVisitTime(visitTime); //Call Service to complete the operation sysLogService.addSysLog(sysLog); } } } } }