javax.servlet.ServletException: No collection found

本文深入解析Java集合框架,包括Collection、List、Set等接口及其实现类的特点与应用场景,指导开发者正确选择和使用集合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package  pjava;

import  java.sql.Connection;
import  java.sql.DriverManager;
import  java.sql.ResultSet;
import  java.sql.Statement;
import  java.util.Collection;
import  java.util.Vector;
public   class  GqInforDisplay  {
    Collection
<GqInforTable> coll;
       
public Collection<GqInforTable> getColl() {
        
return coll;
      }

      
public void setColl(Collection<GqInforTable> coll) {
        
this.coll = coll;
      }

      
public void GqInforQuery(String sql){
          coll
= new Vector<GqInforTable>();
          
try{
              Class.forName(
"com.microsoft.jdbc.sqlserver.SQLServerDriver");  
              
              Connection con
=DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;user=sa;password=123;DatabaseName=sql_test");
              
if(con!=null){
                  Statement stmt
=con.createStatement();
                  ResultSet rs
=stmt.executeQuery(sql);                   
                    GqInforTable gt;
                       
while(rs.next()) 
                         gt
=new GqInforTable();
                         gt.setGq_name(rs.getString(
"gq_name"));
                         gt.setZj_name(rs.getString(
"zj_name"));
                         gt.setGs_name(rs.getString(
"gs_name"));
                         gt.setGq_adress(rs.getString(
"gq_adress"));
                         coll.add(gt);   
                      }
                    
                  rs.close(); 
                  stmt.close(); 
                  con.close(); 
               }

          }
catch(Exception e){
              System.err.println(e);
              System.out.println(
"有错误");
              coll
=null;
          }

      }

      
//test
      public static void main(String args[])
           
      }

}

如上是正确的代码书写。javax.servlet.ServletException: No collection found  的错误是因为将Collection 、vector使用方法混淆了。Vector<?> vect=new Vector<?>() 这种写法冒似有问题。以至于没有发现集合,这只是一种推断,还没有得到理论的证实,所以在javabean没有建立 collection对象或者建立的对象是否正确还待思考。有一点可以说,就是在jsp中,用Vector<?> vect=new Vector<?>()这种方法建立的对象不能被引用 。如:在action中 应该有 request.setAttribute("gid", gd.getColl());
      在jsp中 <logic:present name="gid">
                 <logic:iterate id="list" name="gid">
     <tr>
                 <td>
   <bean:write name="list" property="gq_name" />
       </td>

      </tr>
     </logic:iterate>

request接受的对象是collection。

附:collection资料。(转载于DIY部落 )

  线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在java.util包中。本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类。    
 
Collection  
├List  
│├LinkedList  
│├ArrayList  
│└Vector  
│ └Stack  
└Set  
Map  
├Hashtable  
├HashMap  
└WeakHashMap  
 
Collection接口  
  Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java  SDK不提供直接继承自Collection的类,Java  SDK提供的类都是继承自Collection的“子接口”如List和Set。  
  所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。  
  如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:  
    Iterator  it  =  collection.iterator();  //  获得一个迭代子  
    while(it.hasNext())  {  
      Object  obj  =  it.next();  //  得到下一个元素  
    }  
  由Collection接口派生的两个接口是List和Set。  
 
List接口  
  List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。  
和下面要提到的Set不同,List允许有相同的元素。  
  除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。  
  实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。  
 
LinkedList类  
  LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。  
  注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:  
    List  list  =  Collections.synchronizedList(new  LinkedList(...));  
 
ArrayList类  
  ArrayList实现了可变大小的数组。

它允许所有元素,包括null。ArrayList没有同步。  
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。  
  每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。  
  和LinkedList一样,ArrayList也是非同步的(unsynchronized)。  
 
Vector类  
  Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。  
 
Stack  类  
  Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。  
 
Set接口  
  Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。  
  很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。  
  请注意:必须小心操作可变对象(Mutable  Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。  
 
Map接口  
  请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。  
 
Hashtable类  
  Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。  
  添加数据使用put(key,  value),取出数据使用get(key),这两个基本操作的时间开销为常数。  
Hashtable通过initial  capacity和load  factor两个参数调整性能。通常缺省的load  factor  0.75较好地实现了时间和空间的均衡。增大load  factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。  
使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:  
    Hashtable  numbers  =  new  Hashtable();  
    numbers.put(“one”,  new  Integer(1));  
    numbers.put(“two”,  new  Integer(2));  
    numbers.put(“three”,  new  Integer(3));  
  要取出一个数,比如2,用相应的key:  
    Integer  n  =  (Integer)numbers.get(“two”);  
    System.out.println(“two  =  ”  +  n);  
  由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希表的操作。  
  如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。  
  Hashtable是同步的。  
 
HashMap类  
  HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null  value和null  key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load  factor过低。  
 
WeakHashMap类  
  WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。  
 
总结  
  如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList 。

package com.example.st_mes.config; import com.alibaba.fastjson.JSONObject; import com.example.st_mes.model.*; import com.example.st_mes.model.dto.MySecurityUser; import com.example.st_mes.model.vo.RoleMenuButtonVo; import com.example.st_mes.service.ButtonService; import com.example.st_mes.service.UserRoleService; import com.example.st_mes.utils.JwtUtils; import com.example.st_mes.utils.ResponseTemplate; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Component public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Autowired private ObjectMapper objectMapper; @Autowired private JwtUtils jwtUtils; @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private ButtonService buttonService; @Autowired private UserRoleService userRoleService; @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { //从认证信息里获取登录用户的信息 MySecurityUser mySecurityUser = (MySecurityUser) authentication.getPrincipal(); User userInfo = mySecurityUser.getUserData(); String strUserInfo = objectMapper.writeValueAsString(userInfo);//将用户信息转换为字符串 userRoleService.getUserRole(userInfo.getUserid()); //获取用户权限信息 List<SimpleGrantedAuthority> authorities = (List<SimpleGrantedAuthority>) mySecurityUser.getAuthorities(); List<String> authList = authorities.stream().map(SimpleGrantedAuthority::getAuthority).collect(Collectors.toList()); List<RoleButton> roleButtonList = mySecurityUser.getRoleButtonList(); Integer btnSize = roleButtonList.size(); Integer[] btn = new Integer[btnSize]; String[] permissions = new String[btnSize]; int i = 0; for (RoleButton roleButton:roleButtonList){ btn[i] = roleButton.getButtonId(); Button button = buttonService.getButtonById(btn[i]); permissions[i] = button.getCode(); i++; } //生成jwt String jwtToken = jwtUtils.createJwt(strUserInfo, authList); JSONObject jsonObject = new JSONObject(); jsonObject.put("jwtToken",jwtToken); jsonObject.put("permissions",permissions); ResponseTemplate responseTemplate = ResponseTemplate.builder() .code(200) .msg("jwt生成成功") .data(jsonObject) .build(); //将jwt存放到Redis中 stringRedisTemplate.opsForValue().set("loginToken:" + jwtToken, objectMapper.writeValueAsString(authentication),30, TimeUnit.MINUTES); printToken(request,response,responseTemplate); } private void printToken(HttpServletRequest request, HttpServletResponse response, ResponseTemplate responseTemplate)throws IOException{ String strResponse = objectMapper.writeValueAsString(responseTemplate); response.setCharacterEncoding("UTF-8"); response.setContentType("application/json;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.println(strResponse); writer.flush(); } } 这段代码的问题
最新发布
06-04
### 如何在 Spring Boot 中实现 JWT 登录认证 #### 1. 添加必要依赖 为了在 Spring Boot 应用程序中实现基于 JWT 的登录认证,首先需要引入相关的 Maven 或 Gradle 依赖项。以下是常用的依赖列表: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <scope>runtime</scope> <version>0.11.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <scope>runtime</scope> <version>0.11.5</version> </dependency> ``` 以上依赖分别用于支持 Spring Security 和 JSON Web Token 的生成与解析[^1]。 --- #### 2. 配置 JWT 工具类 创建一个工具类来处理 JWT 的生成和验证逻辑。该类通常会封装加密密钥、过期时间设置等功能。 ```java import io.jsonwebtoken.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JwtUtil { private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class); private String secretKey = "yourSecretKey"; // 密钥需妥善保管并可动态加载 private long validityInMilliseconds = 3600000; // 默认有效期为1小时 public String generateToken(String username) { Claims claims = Jwts.claims().setSubject(username); return Jwts.builder() .setClaims(claims) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() + validityInMilliseconds)) .signWith(SignatureAlgorithm.HS512, secretKey.getBytes()) .compact(); } public boolean validateToken(String token) { try { Jws<Claims> claimsJws = Jwts.parser().setSigningKey(secretKey.getBytes()).parseClaimsJws(token); return !claimsJws.getBody().getExpiration().before(new Date()); } catch (JwtException | IllegalArgumentException e) { logger.error("Invalid JWT token", e); } return false; } public String extractUsername(String token) { return Jwts.parser().setSigningKey(secretKey.getBytes()).parseClaimsJws(token).getBody().getSubject(); } } ``` 此工具类提供了 `generateToken` 方法用于生成令牌,`validateToken` 方法用于校验令牌的有效性,以及 `extractUsername` 方法提取用户名信息[^4]。 --- #### 3. 创建自定义过滤器 Spring Security 使用过滤器链拦截请求并对用户进行身份验证。可以通过扩展 `OncePerRequestFilter` 类来自定义过滤器。 ```java import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component public class JwtRequestFilter extends OncePerRequestFilter { private final JwtUtil jwtUtil; public JwtRequestFilter(JwtUtil jwtUtil) { this.jwtUtil = jwtUtil; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { final String authorizationHeader = request.getHeader("Authorization"); String username = null; String jwt = null; if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { jwt = authorizationHeader.substring(7); username = jwtUtil.extractUsername(jwt); } if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( username, null, userService.loadUserByUsername(username).getAuthorities()); // 替换为实际的 UserDetailsService 实现 SecurityContextHolder.getContext().setAuthentication(authentication); } chain.doFilter(request, response); } } ``` 这个过滤器会在每次 HTTP 请求到达控制器之前检查是否存在有效的 JWT,并将其绑定到当前线程的安全上下文中[^1]。 --- #### 4. 用户详情服务 实现 `UserDetailsService` 接口以提供用户的详细信息(如角色权限)。这一步骤对于完成认证至关重要。 ```java @Service public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { Optional<UserEntity> userOptional = userRepository.findByUsername(username); if (!userOptional.isPresent()) { throw new UsernameNotFoundException("User not found with username: " + username); } UserEntity user = userOptional.get(); return new org.springframework.security.core.userdetails.User( user.getUsername(), user.getPassword(), mapRolesToAuthorities(user.getRoles())); } private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<Role> roles) { return roles.stream() .map(role -> new SimpleGrantedAuthority(role.getName())) .collect(Collectors.toList()); } } ``` 上述代码片段展示了如何从数据库或其他数据源获取用户信息,并映射其角色至 Spring Security 所需的权限结构[^3]。 --- #### 5. 配置 Spring Security 最后,在应用程序启动时配置 Spring Security 来启用 JWT 过滤器和其他安全性选项。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtRequestFilter jwtRequestFilter; @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/auth/**").permitAll() // 放行登录接口 .anyRequest().authenticated() .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 设置无状态会话策略 http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); } } ``` 这段配置禁用了 CSRF 并启用了无状态会话管理,同时将自定义的 JWT 过滤器插入到默认过滤器链前[^4]。 --- #### 总结 通过上述步骤可以成功实现在 Spring Boot 中利用 JWT 提供的无状态认证功能。整个流程涵盖了依赖导入、JWT 工具构建、定制化过滤器设计、用户信息服务搭建以及最终的安全框架调整等多个方面[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值